diff --git a/.tx/config b/.tx/config index 1374640b0..795d3959f 100644 --- a/.tx/config +++ b/.tx/config @@ -12,9 +12,11 @@ trans.it = apps/i2ptunnel/locale/messages_it.po trans.ja = apps/i2ptunnel/locale/messages_ja.po trans.nb = apps/i2ptunnel/locale/messages_nb.po trans.nl = apps/i2ptunnel/locale/messages_nl.po +trans.nn = apps/i2ptunnel/locale/messages_nn.po trans.pl = apps/i2ptunnel/locale/messages_pl.po trans.pt = apps/i2ptunnel/locale/messages_pt.po trans.pt_BR = apps/i2ptunnel/locale/messages_pt_BR.po +trans.ro = apps/i2ptunnel/locale/messages_ro.po trans.ru_RU = apps/i2ptunnel/locale/messages_ru.po trans.sk = apps/i2ptunnel/locale/messages_sk.po trans.sv_SE = apps/i2ptunnel/locale/messages_sv.po @@ -31,6 +33,8 @@ trans.de = apps/i2ptunnel/locale-proxy/messages_de.po trans.es = apps/i2ptunnel/locale-proxy/messages_es.po trans.fr = apps/i2ptunnel/locale-proxy/messages_fr.po trans.hu = apps/i2ptunnel/locale-proxy/messages_hu.po +;; Java converts id to in +trans.id = apps/i2ptunnel/locale-proxy/messages_in.po trans.it = apps/i2ptunnel/locale-proxy/messages_it.po trans.nb = apps/i2ptunnel/locale-proxy/messages_nb.po trans.nl = apps/i2ptunnel/locale-proxy/messages_nl.po @@ -39,6 +43,7 @@ trans.pt = apps/i2ptunnel/locale-proxy/messages_pt.po trans.pt_BR = apps/i2ptunnel/locale-proxy/messages_pt_BR.po trans.ro = apps/i2ptunnel/locale-proxy/messages_ro.po trans.ru_RU = apps/i2ptunnel/locale-proxy/messages_ru.po +trans.sk = apps/i2ptunnel/locale-proxy/messages_sk.po trans.sv_SE = apps/i2ptunnel/locale-proxy/messages_sv.po trans.uk_UA = apps/i2ptunnel/locale-proxy/messages_uk.po trans.vi = apps/i2ptunnel/locale-proxy/messages_vi.po @@ -78,10 +83,16 @@ source_lang = en trans.ar = apps/routerconsole/locale-news/messages_ar.po trans.de = apps/routerconsole/locale-news/messages_de.po trans.es = apps/routerconsole/locale-news/messages_es.po +trans.fi = apps/routerconsole/locale-news/messages_fi.po trans.fr = apps/routerconsole/locale-news/messages_fr.po trans.he = apps/routerconsole/locale-news/messages_he.po -trans.ja = apps/routerconsole/locale-news/messages_ja.po +;; Java converts id to in +trans.id = apps/routerconsole/locale-news/messages_in.po trans.it = apps/routerconsole/locale-news/messages_it.po +trans.ja = apps/routerconsole/locale-news/messages_ja.po +trans.ko = apps/routerconsole/locale-news/messages_ko.po +trans.mg = apps/routerconsole/locale-news/messages_mg.po +trans.nb = apps/routerconsole/locale-news/messages_nb.po trans.nl = apps/routerconsole/locale-news/messages_nl.po trans.pl = apps/routerconsole/locale-news/messages_pl.po trans.pt = apps/routerconsole/locale-news/messages_pt.po @@ -89,14 +100,17 @@ trans.pt_BR = apps/routerconsole/locale-news/messages_pt_BR.po trans.ro = apps/routerconsole/locale-news/messages_ro.po trans.ru_RU = apps/routerconsole/locale-news/messages_ru.po trans.sk = apps/routerconsole/locale-news/messages_sk.po +trans.sq = apps/routerconsole/locale-news/messages_sq.po trans.sv_SE = apps/routerconsole/locale-news/messages_sv.po trans.tr_TR = apps/routerconsole/locale-news/messages_tr.po +trans.uk_UA = apps/routerconsole/locale-news/messages_uk.po trans.zh_CN = apps/routerconsole/locale-news/messages_zh.po [I2P.countries] type = PO source_file = apps/routerconsole/locale-countries/messages_en.po source_lang = en +trans.ca = apps/routerconsole/locale-countries/messages_ca.po trans.da = apps/routerconsole/locale-countries/messages_da.po trans.de = apps/routerconsole/locale-countries/messages_de.po trans.el = apps/routerconsole/locale-countries/messages_el.po @@ -107,6 +121,7 @@ trans.fr = apps/routerconsole/locale-countries/messages_fr.po trans.hu = apps/routerconsole/locale-countries/messages_hu.po trans.it = apps/routerconsole/locale-countries/messages_it.po trans.ja = apps/routerconsole/locale-countries/messages_ja.po +trans.mg = apps/routerconsole/locale-countries/messages_mg.po trans.nb = apps/routerconsole/locale-countries/messages_nb.po trans.nl = apps/routerconsole/locale-countries/messages_nl.po trans.pl = apps/routerconsole/locale-countries/messages_pl.po @@ -115,7 +130,9 @@ trans.pt_BR = apps/routerconsole/locale-countries/messages_pt_BR.po trans.ro = apps/routerconsole/locale-countries/messages_ro.po trans.ru_RU = apps/routerconsole/locale-countries/messages_ru.po trans.sk = apps/routerconsole/locale-countries/messages_sk.po +trans.sq = apps/routerconsole/locale-countries/messages_sq.po trans.sv_SE = apps/routerconsole/locale-countries/messages_sv.po +trans.uk_UA = apps/routerconsole/locale-countries/messages_uk.po trans.tr_TR = apps/routerconsole/locale-countries/messages_tr.po trans.vi = apps/routerconsole/locale-countries/messages_vi.po trans.zh_CN = apps/routerconsole/locale-countries/messages_zh.po @@ -134,6 +151,7 @@ trans.nb = apps/i2psnark/locale/messages_nb.po trans.nl = apps/i2psnark/locale/messages_nl.po trans.pl = apps/i2psnark/locale/messages_pl.po trans.pt = apps/i2psnark/locale/messages_pt.po +trans.pt_BR = apps/i2psnark/locale/messages_pt_bR.po trans.ro = apps/i2psnark/locale/messages_ro.po trans.ru_RU = apps/i2psnark/locale/messages_ru.po trans.sk = apps/i2psnark/locale/messages_sk.po @@ -161,6 +179,7 @@ trans.pt_BR = apps/susidns/locale/messages_pt_BR.po trans.ro = apps/susidns/locale/messages_ro.po trans.ru_RU = apps/susidns/locale/messages_ru.po trans.sv_SE = apps/susidns/locale/messages_sv.po +trans.tr_TR = apps/susidns/locale/messages_tr.po trans.uk_UA = apps/susidns/locale/messages_uk.po trans.vi = apps/susidns/locale/messages_vi.po trans.zh_CN = apps/susidns/locale/messages_zh.po @@ -194,19 +213,25 @@ trans.zh_CN = apps/desktopgui/locale/messages_zh.po source_file = apps/susimail/locale/messages_en.po source_lang = en trans.cs = apps/susimail/locale/messages_cs.po +trans.da = apps/susimail/locale/messages_da.po trans.de = apps/susimail/locale/messages_de.po trans.es = apps/susimail/locale/messages_es.po +trans.fi = apps/susimail/locale/messages_fi.po trans.fr = apps/susimail/locale/messages_fr.po trans.hu = apps/susimail/locale/messages_hu.po +;; Java converts id to in +trans.id = apps/susimail/locale/messages_in.po trans.it = apps/susimail/locale/messages_it.po trans.ja = apps/susimail/locale/messages_ja.po +trans.mg = apps/susimail/locale/messages_mg.po trans.nl = apps/susimail/locale/messages_nl.po -trans.ru_RU = apps/susimail/locale/messages_ru.po -trans.sv_SE = apps/susimail/locale/messages_sv.po trans.pl = apps/susimail/locale/messages_pl.po trans.pt = apps/susimail/locale/messages_pt.po trans.pt_BR = apps/susimail/locale/messages_pt_BR.po trans.ro = apps/susimail/locale/messages_ro.po +trans.ru_RU = apps/susimail/locale/messages_ru.po +trans.sq = apps/susimail/locale/messages_sq.po +trans.sv_SE = apps/susimail/locale/messages_sv.po trans.uk_UA = apps/susimail/locale/messages_uk.po trans.vi = apps/susimail/locale/messages_vi.po trans.zh_CN = apps/susimail/locale/messages_zh.po @@ -218,16 +243,21 @@ trans.cs = debian/po/cs.po trans.de = debian/po/de.po trans.el = debian/po/el.po trans.es = debian/po/es.po +trans.fi = debian/po/fi.po trans.fr = debian/po/fr.po +trans.id = debian/po/id.po trans.it = debian/po/it.po trans.hu = debian/po/hu.po trans.ja = debian/po/ja.po trans.ko = debian/po/ko.po +trans.nl = debian/po/nl.po trans.pl = debian/po/pl.po trans.pt = debian/po/pt.po +trans.pt_BR = debian/po/pt_BR.po trans.ro = debian/po/ro.po trans.ru_RU = debian/po/ru.po trans.sk = debian/po/sk.po +trans.sq = debian/po/sq.po trans.sv_SE = debian/po/sv.po trans.uk_UA = debian/po/uk.po trans.tr_TR = debian/po/tr.po @@ -236,12 +266,21 @@ trans.zh_CN = debian/po/zh.po [I2P.i2prouter-script] source_file = installer/resources/locale/po/messages_en.po source_lang = en +;; currently fails check +;;trans.ca = installer/resources/locale/po/messages_ca.po trans.de = installer/resources/locale/po/messages_de.po trans.es = installer/resources/locale/po/messages_es.po +;; currently fails check +;;trans.fi = installer/resources/locale/po/messages_fi.po trans.fr = installer/resources/locale/po/messages_fr.po +trans.id = installer/resources/locale/po/messages_id.po trans.it = installer/resources/locale/po/messages_it.po trans.pl = installer/resources/locale/po/messages_pl.po trans.ja = installer/resources/locale/po/messages_ja.po +;; currently fails check +;;trans.ko = installer/resources/locale/po/messages_ko.po +trans.nl = installer/resources/locale/po/messages_nl.po +trans.pl = installer/resources/locale/po/messages_pl.po trans.pt = installer/resources/locale/po/messages_pt.po trans.pt_BR = installer/resources/locale/po/messages_pt_BR.po trans.ro = installer/resources/locale/po/messages_ro.po @@ -249,6 +288,8 @@ trans.ru_RU = installer/resources/locale/po/messages_ru.po trans.sk = installer/resources/locale/po/messages_sk.po trans.sv_SE = installer/resources/locale/po/messages_sv.po trans.tr_TR = installer/resources/locale/po/messages_tr.po +;; currently fails check +;;trans.uk_UA = installer/resources/locale/po/messages_uk.po trans.zh_CN = installer/resources/locale/po/messages_zh.po [I2P.getopt] @@ -258,22 +299,46 @@ type = PROPERTIES trans.cs = core/java/src/gnu/getopt/MessagesBundle_cs.properties trans.de = core/java/src/gnu/getopt/MessagesBundle_de.properties trans.es = core/java/src/gnu/getopt/MessagesBundle_es.properties +trans.fi = core/java/src/gnu/getopt/MessagesBundle_fi.properties trans.fr = core/java/src/gnu/getopt/MessagesBundle_fr.properties trans.hu = core/java/src/gnu/getopt/MessagesBundle_hu.properties +;; Java converts id to in +trans.id = core/java/src/gnu/getopt/MessagesBundle_in.properties trans.it = core/java/src/gnu/getopt/MessagesBundle_it.properties trans.ja = core/java/src/gnu/getopt/MessagesBundle_ja.properties +trans.ko = core/java/src/gnu/getopt/MessagesBundle_ko.properties trans.nl = core/java/src/gnu/getopt/MessagesBundle_nl.properties trans.nb = core/java/src/gnu/getopt/MessagesBundle_nb.properties trans.pl = core/java/src/gnu/getopt/MessagesBundle_pl.properties -trans.pt_BR = core/java/src/gnu/getopt/MessagesBundle_pt_BR.properties +;; currently corrupt, non-UTF-8 +;;trans.pt = core/java/src/gnu/getopt/MessagesBundle_pt.properties +;; currently corrupt, non-UTF-8 +;;trans.pt_BR = core/java/src/gnu/getopt/MessagesBundle_pt_BR.properties trans.ro = core/java/src/gnu/getopt/MessagesBundle_ro.properties trans.ru_RU = core/java/src/gnu/getopt/MessagesBundle_ru.properties trans.sk = core/java/src/gnu/getopt/MessagesBundle_sk.properties +;; currently corrupt, non-UTF-8 +;;trans.sq = core/java/src/gnu/getopt/MessagesBundle_sq.properties +trans.uk_UA = core/java/src/gnu/getopt/MessagesBundle_uk.properties trans.zh_CN = core/java/src/gnu/getopt/MessagesBundle_zh.properties [I2P.streaming] source_file = apps/ministreaming/locale/messages_en.po source_lang = en +trans.ca = apps/ministreaming/locale/messages_ca.po +trans.de = apps/ministreaming/locale/messages_de.po +trans.es = apps/ministreaming/locale/messages_es.po +trans.fr = apps/ministreaming/locale/messages_fr.po +;; Java converts id to in +trans.id = apps/ministreaming/locale/messages_in.po +trans.it = apps/ministreaming/locale/messages_it.po +trans.nb = apps/ministreaming/locale/messages_nb.po +trans.pl = apps/ministreaming/locale/messages_pl.po +trans.ro = apps/ministreaming/locale/messages_ro.po +trans.ru_RU = apps/ministreaming/locale/messages_ru.po +trans.sv_SE = apps/ministreaming/locale/messages_sv.po +trans.uk_UA = apps/ministreaming/locale/messages_uk.po +trans.zh_CN = apps/ministreaming/locale/messages_zh.po [main] host = https://www.transifex.com diff --git a/INSTALL-headless.txt b/INSTALL-headless.txt index 6f5457580..3ae8a14f0 100644 --- a/INSTALL-headless.txt +++ b/INSTALL-headless.txt @@ -25,21 +25,22 @@ where there are comments labeled "PORTABLE". Do this before you run I2P for the first time. To start I2P: - (*nix): sh i2prouter start + (*nix, BSD, Mac): sh i2prouter start (win*): I2P.exe - (non-x86 platforms PPC, ARM, etc): sh runplain.sh + (platforms without wrapper support): sh runplain.sh To stop I2P (gracefully): lynx http://localhost:7657/summaryframe (click "Shutdown") + or (*nix, BSD, Mac) sh i2prouter graceful To stop I2P immediately: - sh i2prouter stop + (*nix, BSD, Mac) sh i2prouter stop To uninstall I2P: rm -rf $I2PInstallDir ~/.i2p Supported JVMs: - All platforms: Java 1.6 or higher required; 1.7 or higher recommended + All platforms: Java 1.7 or higher required Windows: OpenJDK or Oracle from http://java.com/download Linux: OpenJDK or Oracle from http://java.com/download FreeBSD: OpenJDK or Oracle from http://java.com/download diff --git a/INSTALL.txt b/INSTALL.txt index 23701b041..d9960fc3a 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -1,8 +1,9 @@ I2P source installation instructions Prerequisites to build from source: - Java SDK (preferably Oracle/Sun or OpenJDK) 1.6.0 or higher + Java SDK (preferably Oracle/Sun or OpenJDK) 1.7.0 or higher Non-linux operating systems and JVMs: See https://trac.i2p2.de/wiki/java + Certain subsystems for embedded (core, router, mstreaming, streaming, i2ptunnel) require only Java 1.6 Apache Ant 1.7.0 or higher The xgettext, msgfmt, and msgmerge tools installed from the GNU gettext package http://www.gnu.org/software/gettext/ @@ -40,29 +41,30 @@ or on Windows, just double-click on i2pinstall.exe. Or move the i2pupdate.zip file into an existing installation directory and restart. To start I2P: - (*nix): sh i2prouter start + (*nix, BSD, Mac): sh i2prouter start (win*): I2P.exe or i2prouter.bat - (non-x86 platforms PPC, ARM, etc): sh runplain.sh + (platforms without wrapper support): sh runplain.sh To install I2P as a system service: - (*nix) sh i2prouter install + (*nix, BSD, Mac) sh i2prouter install (win*) install_i2p_service_winnt.bat To uninstall I2P as a system service: - (*nix) sh i2prouter remove + (*nix, BSD, Mac) sh i2prouter remove (win*) uninstall_i2p-service_winnt.bat To stop I2P (gracefully): lynx http://localhost:7657/summaryframe (click "Shutdown") + or (*nix, BSD, Mac) sh i2prouter graceful To stop I2P immediately: - sh i2prouter stop + (*nix, BSD, Mac) sh i2prouter stop To uninstall I2P: rm -rf $I2PInstallDir ~/.i2p Supported JVMs: - Windows: Latest available from http://java.com/download (1.5+ supported) - Linux: Latest available from http://java.com/download (1.5+ supported) - FreeBSD: 1.5-compatible (NIO required) + Windows: Latest available from http://java.com/download (1.7+ supported) + Linux: Latest available from http://java.com/download (1.7+ supported) + FreeBSD: 1.7-compatible (NIO required) Other operating systems and JVMs: See http://trac.i2p2.de/wiki/java diff --git a/LICENSE.txt b/LICENSE.txt index 11dd51e38..295da33aa 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -80,6 +80,10 @@ Public domain except as listed below: Copyright (c) 1998 by Aaron M. Renn (arenn@urbanophile.com) See licenses/LICENSE-LGPLv2.1.txt + HostnameVerifier: + From Apache HttpClient 4.4.1 and HttpCore 4.4.1 + See licenses/LICENSE-Apache2.0.txt + Router (router.jar): Public domain except as listed below: @@ -87,7 +91,7 @@ Public domain except as listed below: From freenet See licenses/LICENSE-GPLv2.txt - UPnP subsystem (CyberLink) 2.1: + UPnP subsystem (CyberLink) 3.0: Copyright (C) 2003-2010 Satoshi Konno See licenses/LICENSE-UPnP.txt @@ -137,7 +141,7 @@ Installer: -Java Service Wrapper Community Edition 32-bit 3.5.19: +Java Service Wrapper Community Edition 32-bit 3.5.25: Copyright (C) 1999-2011 Tanuki Software, Ltd. All Rights Reserved. See licenses/LICENSE-Wrapper.txt @@ -182,7 +186,7 @@ Applications: By welterde. See licenses/LICENSE-GPLv2.txt - Jetty 8.1.15.v20140411: + Jetty 8.1.17.v20150415: See licenses/ABOUT-Jetty.html See licenses/NOTICE-Jetty.html See licenses/LICENSE-Apache2.0.txt @@ -248,8 +252,8 @@ Applications: Bundles systray4j-2.4.1: See licenses/LICENSE-LGPLv2.1.txt - Tomcat 6.0.41: - Copyright 1999-2014 The Apache Software Foundation + Tomcat 6.0.44: + Copyright 1999-2015 The Apache Software Foundation See licenses/LICENSE-Apache2.0.txt See licenses/NOTICE-Tomcat.txt diff --git a/README.txt b/README.txt index 1f6932ec3..577af8717 100644 --- a/README.txt +++ b/README.txt @@ -1,6 +1,7 @@ Prerequisites to build from source: - Java SDK (preferably Oracle/Sun or OpenJDK) 1.6.0 or higher + Java SDK (preferably Oracle/Sun or OpenJDK) 1.7.0 or higher Non-linux operating systems and JVMs: See https://trac.i2p2.de/wiki/java + Certain subsystems for embedded (core, router, mstreaming, streaming, i2ptunnel) require only Java 1.6 Apache Ant 1.7.0 or higher The xgettext, msgfmt, and msgmerge tools installed from the GNU gettext package http://www.gnu.org/software/gettext/ @@ -30,7 +31,8 @@ Old build system: Documentation: https://geti2p.net/how - API: run 'ant javadoc' then start at build/javadoc/index.html + API: http://docs.i2p-projekt.de/javadoc/ + or run 'ant javadoc' then start at build/javadoc/index.html Latest release: https://geti2p.net/download @@ -45,6 +47,15 @@ Need help? IRC irc.freenode.net #i2p http://forum.i2p/ +Bug reports: + https://trac.i2p2.de/report/1 + +Contact information, security issues, press inquiries: + https://geti2p.net/en/contact + +Twitter: + @i2p, @geti2p + Licenses: See LICENSE.txt diff --git a/apps/BOB/Demos/echo/echoclient/src/net/i2p/BOB/Demos/echo/echoclient/Main.java b/apps/BOB/Demos/echo/echoclient/src/net/i2p/BOB/Demos/echo/echoclient/Main.java index ca7b82889..313f10f2c 100644 --- a/apps/BOB/Demos/echo/echoclient/src/net/i2p/BOB/Demos/echo/echoclient/Main.java +++ b/apps/BOB/Demos/echo/echoclient/src/net/i2p/BOB/Demos/echo/echoclient/Main.java @@ -66,7 +66,7 @@ public class Main { } static void wrtxt(OutputStream CMDout, String s) throws IOException { - CMDout.write(s.getBytes()); + CMDout.write(DataHelper.getUTF8(s)); CMDout.write('\n'); CMDout.flush(); } diff --git a/apps/BOB/Demos/echo/echoserver/src/net/i2p/BOB/Demos/echo/echoserver/Main.java b/apps/BOB/Demos/echo/echoserver/src/net/i2p/BOB/Demos/echo/echoserver/Main.java index 6b7be2518..93bd7d753 100644 --- a/apps/BOB/Demos/echo/echoserver/src/net/i2p/BOB/Demos/echo/echoserver/Main.java +++ b/apps/BOB/Demos/echo/echoserver/src/net/i2p/BOB/Demos/echo/echoserver/Main.java @@ -63,7 +63,7 @@ public class Main { } static void wrtxt(OutputStream CMDout, String s) throws IOException { - CMDout.write(s.getBytes()); + CMDout.write(DataHelper.getUTF8(s)); CMDout.write('\n'); CMDout.flush(); } diff --git a/apps/BOB/src/net/i2p/BOB/BOB.java b/apps/BOB/src/net/i2p/BOB/BOB.java index 8277fd259..c8b06b5e9 100644 --- a/apps/BOB/src/net/i2p/BOB/BOB.java +++ b/apps/BOB/src/net/i2p/BOB/BOB.java @@ -38,7 +38,6 @@ import net.i2p.I2PAppContext; import net.i2p.app.*; import net.i2p.client.I2PClient; import net.i2p.util.I2PAppThread; -import net.i2p.util.SimpleScheduler; import net.i2p.util.SimpleTimer2; /** @@ -119,15 +118,16 @@ public class BOB implements Runnable, ClientApp { public final static String PROP_BOB_HOST = "BOB.host"; public final static String PROP_CFG_VER = "BOB.CFG.VER"; + /** unused when started via the ClientApp interface */ private static BOB _bob; - private NamedDB database; - private Properties props = new Properties(); - private AtomicBoolean spin = new AtomicBoolean(true); + private final NamedDB database; + private final Properties props = new Properties(); + private final AtomicBoolean spin = new AtomicBoolean(true); private static final String P_RUNNING = "RUNNING"; private static final String P_STARTING = "STARTING"; private static final String P_STOPPING = "STOPPING"; - private AtomicBoolean lock = new AtomicBoolean(false); + private final AtomicBoolean lock = new AtomicBoolean(false); // no longer used. // private static int maxConnections = 0; @@ -143,8 +143,9 @@ public class BOB implements Runnable, ClientApp { * Stop BOB gracefully * @deprecated unused */ - public static void stop() { - _bob.shutdown(null); + public synchronized static void stop() { + if (_bob != null) + _bob.shutdown(null); } /** @@ -189,7 +190,7 @@ public class BOB implements Runnable, ClientApp { * * @param args */ - public static void main(String[] args) { + public synchronized static void main(String[] args) { try { _bob = new BOB(I2PAppContext.getGlobalContext(), null, args); _bob.startup(); @@ -212,9 +213,7 @@ public class BOB implements Runnable, ClientApp { // Re-reading the config file in each thread is pretty damn stupid. String configLocation = System.getProperty(PROP_CONFIG_LOCATION, "bob.config"); // This is here just to ensure there is no interference with our threadgroups. - SimpleScheduler Y1 = SimpleScheduler.getInstance(); SimpleTimer2 Y2 = SimpleTimer2.getInstance(); - i = Y1.hashCode(); i = Y2.hashCode(); { File cfg = new File(configLocation); @@ -248,11 +247,11 @@ public class BOB implements Runnable, ClientApp { save = true; } if (!props.containsKey("inbound.length")) { - props.setProperty("inbound.length", "1"); + props.setProperty("inbound.length", "3"); save = true; } if (!props.containsKey("outbound.length")) { - props.setProperty("outbound.length", "1"); + props.setProperty("outbound.length", "3"); save = true; } if (!props.containsKey("inbound.lengthVariance")) { @@ -339,7 +338,7 @@ public class BOB implements Runnable, ClientApp { if (g) { DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log); - Thread t = new Thread(conn_c); + Thread t = new I2PAppThread(conn_c); t.setName("BOB.DoCMDS " + i); t.start(); i++; diff --git a/apps/BOB/src/net/i2p/BOB/DoCMDS.java b/apps/BOB/src/net/i2p/BOB/DoCMDS.java index 957f0ea3f..7e5bd1014 100644 --- a/apps/BOB/src/net/i2p/BOB/DoCMDS.java +++ b/apps/BOB/src/net/i2p/BOB/DoCMDS.java @@ -25,12 +25,13 @@ import java.util.Locale; import java.util.Properties; import java.util.StringTokenizer; import java.util.concurrent.atomic.AtomicBoolean; + import net.i2p.I2PAppContext; import net.i2p.I2PException; import net.i2p.client.I2PClientFactory; -//import net.i2p.data.DataFormatException; import net.i2p.data.Destination; -//import net.i2p.i2ptunnel.I2PTunnel; +import net.i2p.util.I2PAppThread; + // needed only for debugging. // import java.util.logging.Level; // import java.util.logging.Logger; @@ -1307,7 +1308,7 @@ public class DoCMDS implements Runnable { // wait } tunnel = new MUXlisten(lock, database, nickinfo, _log); - Thread t = new Thread(tunnel); + Thread t = new I2PAppThread(tunnel); t.start(); // try { // Thread.sleep(1000 * 10); // Slow down the startup. diff --git a/apps/BOB/src/net/i2p/BOB/I2Plistener.java b/apps/BOB/src/net/i2p/BOB/I2Plistener.java index 28c053a3a..ebe488860 100644 --- a/apps/BOB/src/net/i2p/BOB/I2Plistener.java +++ b/apps/BOB/src/net/i2p/BOB/I2Plistener.java @@ -18,10 +18,12 @@ package net.i2p.BOB; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.util.concurrent.atomic.AtomicBoolean; + import net.i2p.I2PException; import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketManager; +import net.i2p.util.I2PAppThread; /** * Listen on I2P and connect to TCP @@ -30,16 +32,15 @@ import net.i2p.client.streaming.I2PSocketManager; */ public class I2Plistener implements Runnable { - private NamedDB info, database; - private Logger _log; - public I2PSocketManager socketManager; - public I2PServerSocket serverSocket; - private AtomicBoolean lives; + private final NamedDB info, database; + private final Logger _log; + private final I2PServerSocket serverSocket; + private final AtomicBoolean lives; /** * Constructor * @param SS - * @param S + * @param S unused * @param info * @param database * @param _log @@ -48,7 +49,6 @@ public class I2Plistener implements Runnable { this.database = database; this.info = info; this._log = _log; - this.socketManager = S; this.serverSocket = SS; this.lives = lives; } @@ -79,7 +79,7 @@ public class I2Plistener implements Runnable { conn++; // toss the connection to a new thread. I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives); - Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn); + Thread t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn); t.start(); } diff --git a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java index bf699db60..11b401029 100644 --- a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java +++ b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java @@ -19,7 +19,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.concurrent.atomic.AtomicBoolean; + import net.i2p.client.streaming.I2PSocket; +import net.i2p.data.DataHelper; +import net.i2p.util.I2PAppThread; /** * Process I2P->TCP @@ -104,15 +107,15 @@ public class I2PtoTCP implements Runnable { if (tell) { // tell who is connecting - out.write(I2P.getPeerDestination().toBase64().getBytes()); + out.write(DataHelper.getASCII(I2P.getPeerDestination().toBase64())); out.write(10); // nl out.flush(); // not really needed, but... } // setup to cross the streams TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app - t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA"); - q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB"); + t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA"); + q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB"); // Fire! t.start(); q.start(); diff --git a/apps/BOB/src/net/i2p/BOB/MUXlisten.java b/apps/BOB/src/net/i2p/BOB/MUXlisten.java index f330be971..81dbe0845 100644 --- a/apps/BOB/src/net/i2p/BOB/MUXlisten.java +++ b/apps/BOB/src/net/i2p/BOB/MUXlisten.java @@ -21,11 +21,13 @@ import java.net.InetAddress; import java.net.ServerSocket; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; + import net.i2p.I2PException; import net.i2p.client.I2PClient; import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManagerFactory; +import net.i2p.util.I2PAppThread; import net.i2p.util.Log; /** @@ -201,14 +203,14 @@ public class MUXlisten implements Runnable { // I2P -> TCP SS = socketManager.getServerSocket(); I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log, lives); - t = new Thread(tg, conn, "BOBI2Plistener " + N); + t = new I2PAppThread(tg, conn, "BOBI2Plistener " + N); t.start(); } if (come_in) { // TCP -> I2P TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log, lives); - q = new Thread(tg, conn, "BOBTCPlistener " + N); + q = new I2PAppThread(tg, conn, "BOBTCPlistener " + N); q.start(); } diff --git a/apps/BOB/src/net/i2p/BOB/Main.java b/apps/BOB/src/net/i2p/BOB/Main.java index 89fd95489..9382cd44e 100644 --- a/apps/BOB/src/net/i2p/BOB/Main.java +++ b/apps/BOB/src/net/i2p/BOB/Main.java @@ -15,7 +15,6 @@ */ package net.i2p.BOB; -import net.i2p.util.SimpleScheduler; import net.i2p.util.SimpleTimer2; /** @@ -31,12 +30,10 @@ public class Main { */ public static void main(String[] args) { // THINK THINK THINK THINK THINK THINK - SimpleScheduler Y1 = SimpleScheduler.getInstance(); SimpleTimer2 Y2 = SimpleTimer2.getInstance(); BOB.main(args); Y2.stop(); - Y1.stop(); } } diff --git a/apps/BOB/src/net/i2p/BOB/NamedDB.java b/apps/BOB/src/net/i2p/BOB/NamedDB.java index 5a1b8e45f..dda9ab268 100644 --- a/apps/BOB/src/net/i2p/BOB/NamedDB.java +++ b/apps/BOB/src/net/i2p/BOB/NamedDB.java @@ -64,7 +64,7 @@ public class NamedDB { } /** - * Find objects in the array, returns it's index or throws exception + * Find objects in the array, returns its index or throws exception * @param key * @return an objects index * @throws ArrayIndexOutOfBoundsException when key does not exist diff --git a/apps/BOB/src/net/i2p/BOB/TCPlistener.java b/apps/BOB/src/net/i2p/BOB/TCPlistener.java index e5dd41d59..2ad1b5af6 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPlistener.java +++ b/apps/BOB/src/net/i2p/BOB/TCPlistener.java @@ -20,8 +20,10 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.util.concurrent.atomic.AtomicBoolean; + import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PSocketManager; +import net.i2p.util.I2PAppThread; /** * Listen on TCP port and connect to I2P @@ -30,12 +32,11 @@ import net.i2p.client.streaming.I2PSocketManager; */ public class TCPlistener implements Runnable { - private NamedDB info, database; - private Logger _log; - public I2PSocketManager socketManager; - public I2PServerSocket serverSocket; - private ServerSocket listener; - private AtomicBoolean lives; + private final NamedDB info, database; + private final Logger _log; + private final I2PSocketManager socketManager; + private final ServerSocket listener; + private final AtomicBoolean lives; /** * Constructor @@ -76,7 +77,7 @@ public class TCPlistener implements Runnable { conn++; // toss the connection to a new thread. TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives); - Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn); + Thread t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn); t.start(); g = false; } diff --git a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java index 0ce587257..3f196af28 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java +++ b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java @@ -24,13 +24,14 @@ import java.net.NoRouteToHostException; import java.net.Socket; import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; + +import net.i2p.I2PAppContext; import net.i2p.I2PException; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketManager; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; -//import net.i2p.i2ptunnel.I2PTunnel; -import net.i2p.I2PAppContext; +import net.i2p.util.I2PAppThread; /** * @@ -158,8 +159,8 @@ public class TCPtoI2P implements Runnable { // setup to cross the streams TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app - t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA"); - q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB"); + t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA"); + q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB"); // Fire! t.start(); q.start(); diff --git a/apps/BOB/src/net/i2p/BOB/UDPIOthread.java b/apps/BOB/src/net/i2p/BOB/UDPIOthread.java index 1b6f4249d..9448d1d7b 100644 --- a/apps/BOB/src/net/i2p/BOB/UDPIOthread.java +++ b/apps/BOB/src/net/i2p/BOB/UDPIOthread.java @@ -34,15 +34,17 @@ import net.i2p.util.Log; * The skeletal frame is here, just needs to be finished. * * @author sponge + * @deprecated incomplete, unused */ public class UDPIOthread implements I2PSessionListener, Runnable { - private NamedDB info; - private Log _log; - private Socket socket; + private final NamedDB info; + private final Log _log; + private final Socket socket; private DataInputStream in; private DataOutputStream out; - private I2PSession _session; + private final I2PSession _session; + // FIXME never set private Destination _peerDestination; private boolean up; @@ -58,7 +60,6 @@ public class UDPIOthread implements I2PSessionListener, Runnable { this._log = _log; this.socket = socket; this._session = _session; - } /** diff --git a/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java b/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java index 4a124e488..fea030774 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/AddressBook.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.regex.Pattern; import net.i2p.I2PAppContext; import net.i2p.util.EepGet; @@ -49,6 +50,26 @@ class AddressBook { private boolean modified; private static final boolean DEBUG = false; + private static final int MIN_DEST_LENGTH = 516; + private static final int MAX_DEST_LENGTH = MIN_DEST_LENGTH + 100; // longer than any known cert type for now + + /** + * 5-67 chars lower/upper case + */ + private static final Pattern HOST_PATTERN = + Pattern.compile("^[0-9a-zA-Z\\.-]{5,67}$"); + + /** + * 52 chars lower/upper case + * Always ends in 'a' or 'q' + */ + private static final Pattern B32_PATTERN = + Pattern.compile("^[2-7a-zA-Z]{51}[aAqQ]$"); + + /** not a complete qualification, just a quick check */ + private static final Pattern B64_PATTERN = + Pattern.compile("^[0-9a-zA-Z~-]{" + MIN_DEST_LENGTH + ',' + MAX_DEST_LENGTH + "}={0,2}$"); + /** * Construct an AddressBook from the contents of the Map addresses. * @@ -159,8 +180,13 @@ class AddressBook { * @since 0.8.7 */ public Iterator> iterator() { - if (this.subFile != null) - return new ConfigIterator(this.subFile); + if (this.subFile != null) { + try { + return new ConfigIterator(this.subFile); + } catch (IOException ioe) { + return new ConfigIterator(); + } + } return this.addresses.entrySet().iterator(); } @@ -201,9 +227,6 @@ class AddressBook { return "Map containing " + this.addresses.size() + " entries"; } - private static final int MIN_DEST_LENGTH = 516; - private static final int MAX_DEST_LENGTH = MIN_DEST_LENGTH + 100; // longer than any known cert type for now - /** * Do basic validation of the hostname * hostname was already converted to lower case by ConfigParser.parse() @@ -220,9 +243,10 @@ class AddressBook { host.indexOf("..") < 0 && // IDN - basic check, not complete validation (host.indexOf("--") < 0 || host.startsWith("xn--") || host.indexOf(".xn--") > 0) && - host.replaceAll("[a-z0-9.-]", "").length() == 0 && + HOST_PATTERN.matcher(host).matches() && // Base32 spoofing (52chars.i2p) - (! (host.length() == 56 && host.substring(0,52).replaceAll("[a-z2-7]", "").length() == 0)) && + // We didn't do it this way, we use a .b32.i2p suffix, but let's prohibit it anyway + (! (host.length() == 56 && B32_PATTERN.matcher(host.substring(0,52)).matches())) && // ... or maybe we do Base32 this way ... (! host.equals("b32.i2p")) && (! host.endsWith(".b32.i2p")) && @@ -246,7 +270,7 @@ class AddressBook { (dest.length() > MIN_DEST_LENGTH && dest.length() <= MAX_DEST_LENGTH)) && // B64 comes in groups of 2, 3, or 4 chars, but never 1 ((dest.length() % 4) != 1) && - dest.replaceAll("[a-zA-Z0-9~-]", "").length() == 0 + B64_PATTERN.matcher(dest).matches() ; } @@ -332,4 +356,27 @@ class AddressBook { protected void finalize() { delete(); } + +/**** + public static void main(String[] args) { + String[] tests = { "foo.i2p", + "3bnipzzu67cdq2rcygyxz52xhvy6ylokn4zfrk36ywn6pixmaoza.b32.i2p", + "9rhEy4dT9fMlcSOhDzfWRxCV2aen4Zp4eSthOf5f9gVKMa4PtQJ-wEzm2KEYeDXkbM6wEDvMQ6ou4LIniSE6bSAwy7fokiXk5oabels-sJmftnQWRbZyyXEAsLc3gpJJvp9km7kDyZ0z0YGL5tf3S~OaWdptB5tSBOAOjm6ramcYZMWhyUqm~xSL1JyXUqWEHRYwhoDJNL6-L516VpDYVigMBpIwskjeFGcqK8BqWAe0bRwxIiFTPN6Ck8SDzQvS1l1Yj-zfzg3X3gOknzwR8nrHUkjsWtEB6nhbOr8AR21C9Hs0a7MUJvSe2NOuBoNTrtxT76jDruI78JcG5r~WKl6M12yM-SqeBNE9hQn2QCHeHAKju7FdRCbqaZ99IwyjfwvZbkiYYQVN1xlUuGaXrj98XDzK7GORYdH-PrVGfEbMXQ40KLHUWHz8w4tQXAOQrCHEichod0RIzuuxo3XltCWKrf1xGZhkAo9bk2qXi6digCijvYNaKmQdXZYWW~RtAAAA", + "6IZTYacjlXjSAxu-uXEO5oGsj-f4tfePHEvGjs5pu-AMXMwD7-xFdi8kdobDMJp9yRAl96U7yLl~0t9zHeqqYmNeZnDSkTmAcSC2PT45ZJDXBobKi1~a77zuqfPwnzEatYfW3GL1JQAEkAmiwNJoG7ThTZ3zT7W9ekVJpHi9mivpTbaI~rALLfuAg~Mvr60nntZHjqhEZuiU4dTXrmc5nykl~UaMnBdwHL4jKmoN5CotqHyLYZfp74fdD-Oq4SkhuBhU8wkBIM3lz3Ul1o6-s0lNUMdYJq1CyxnyP7jeekdfAlSx4P4sU4M0dPaYvPdOFWPWwBuEh0pCs5Mj01B2xeEBhpV~xSLn6ru5Vq98TrmaR33KHxd76OYYFsWwzVbBuMVSd800XpBghGFucGw01YHYsPh3Afb01sXbf8Nb1bkxCy~DsrmoH4Ww3bpx66JhRTWvg5al3oWlCX51CnJUqaaK~dPL-pBvAyLKIA5aYvl8ca66jtA7AFDxsOb2texBBQAEAAcAAA==", + "te9Ky7XvVcLLr5vQqvfmOasg915P3-ddP3iDqpMMk7v5ufFKobLAX~1k-E4WVsJVlkYvkHVOjxix-uT1IdewKmLd81s5wZtz0GQ3ZC6p0C3S2cOxz7kQqf7QYSR0BrhZC~2du3-GdQO9TqNmsnHrah5lOZf0LN2JFEFPqg8ZB5JNm3JjJeSqePBRk3zAUogNaNK3voB1MVI0ZROKopXAJM4XMERNqI8tIH4ngGtV41SEJJ5pUFrrTx~EiUPqmSEaEA6UDYZiqd23ZlewZ31ExXQj97zvkuhKCoS9A9MNkzZejJhP-TEXWF8~KHur9f51H--EhwZ42Aj69-3GuNjsMdTwglG5zyIfhd2OspxJrXzCPqIV2sXn80IbPgwxHu0CKIJ6X43B5vTyVu87QDI13MIRNGWNZY5KmM5pilGP7jPkOs4xQDo4NHzpuJR5igjWgJIBPU6fI9Pzq~BMzjLiZOMp8xNWey1zKC96L0eX4of1MG~oUvq0qmIHGNa1TlUwBQAEAAEAAA==", + "(*&(*&(*&(*", + "9rhEy4dT9fMlcSOhDzfWRxCV2aen4Zp4eSthOf5f9gVKMa4PtQJ-wEzm2KEYeDXkbM6wEDvMQ6ou4LIniSE6bSAwy7fokiXk5oabels-sJmftnQWRbZyyXEAsLc3gpJJvp9km7kDyZ0z0YGL5tf3S~OaWdptB5tSBOAOjm6ramcYZMWhyUqm~xSL1JyXUqWEHRYwhoDJNL6-L516VpDYVigMBpIwskjeFGcqK8BqWAe0bRwxIiFTPN6Ck8SDzQvS1l1Yj-zfzg3X3gOknzwR8nrHUkjsWtEB6nhbOr8AR21C9Hs0a7MUJvSe2NOuBoNTrtxT76jDruI78JcG5r~WKl6M12yM-SqeBNE9hQn2QCHeHAKju7FdRCbqaZ99IwyjfwvZbkiYYQVN1xlUuGaXrj98XDzK7GORYdH-PrVGfEbMXQ40KLHUWHz8w4tQXAOQrCHEichod0RIzuuxo3XltCWKrf1xGZhkAo9bk2qXi6digCijvYNaKmQdXZYWW~RtAAA", + "6IZTYacjlXjSAxu-uXEO5oGsj-f4tfePHEvGjs5pu-AMXMwD7-xFdi8kdobDMJp9yRAl96U7yLl~0t9zHeqqYmNeZnDSkTmAcSC2PT45ZJDXBobKi1~a77zuqfPwnzEatYfW3GL1JQAEkAmiwNJoG7ThTZ3zT7W9ekVJpHi9mivpTbaI~rALLfuAg~Mvr60nntZHjqhEZuiU4dTXrmc5nykl~UaMnBdwHL4jKmoN5CotqHyLYZfp74fdD-Oq4SkhuBhU8wkBIM3lz3Ul1o6-s0lNUMdYJq1CyxnyP7jeekdfAlSx4P4sU4M0dPaYvPdOFWPWwBuEh0pCs5Mj01B2xeEBhpV~xSLn6ru5Vq98TrmaR33KHxd76OYYFsWwzVbBuMVSd800XpBghGFucGw01YHYsPh3Afb01sXbf8Nb1bkxCy~DsrmoH4Ww3bpx66JhRTWvg5al3oWlCX51CnJUqaaK~dPL-pBvAyLKIA5aYvl8ca66jtA7AFDxsOb2texBBQAEAAcAAA===", + "!e9Ky7XvVcLLr5vQqvfmOasg915P3-ddP3iDqpMMk7v5ufFKobLAX~1k-E4WVsJVlkYvkHVOjxix-uT1IdewKmLd81s5wZtz0GQ3ZC6p0C3S2cOxz7kQqf7QYSR0BrhZC~2du3-GdQO9TqNmsnHrah5lOZf0LN2JFEFPqg8ZB5JNm3JjJeSqePBRk3zAUogNaNK3voB1MVI0ZROKopXAJM4XMERNqI8tIH4ngGtV41SEJJ5pUFrrTx~EiUPqmSEaEA6UDYZiqd23ZlewZ31ExXQj97zvkuhKCoS9A9MNkzZejJhP-TEXWF8~KHur9f51H--EhwZ42Aj69-3GuNjsMdTwglG5zyIfhd2OspxJrXzCPqIV2sXn80IbPgwxHu0CKIJ6X43B5vTyVu87QDI13MIRNGWNZY5KmM5pilGP7jPkOs4xQDo4NHzpuJR5igjWgJIBPU6fI9Pzq~BMzjLiZOMp8xNWey1zKC96L0eX4of1MG~oUvq0qmIHGNa1TlUwBQAEAAEAAA==", + "x" + }; + for (String s : tests) { + test(s); + } + } + + public static void test(String s) { + System.out.println(s + " valid host? " + isValidKey(s) + " valid dest? " + isValidDest(s)); + } +****/ } diff --git a/apps/addressbook/java/src/net/i2p/addressbook/ConfigIterator.java b/apps/addressbook/java/src/net/i2p/addressbook/ConfigIterator.java index 955363eaf..10119d844 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/ConfigIterator.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/ConfigIterator.java @@ -22,6 +22,7 @@ package net.i2p.addressbook; import java.io.BufferedReader; +import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -31,6 +32,8 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import net.i2p.data.DataHelper; + /** * A class to iterate through a hosts.txt or config file without * reading the whole thing into memory. @@ -41,7 +44,7 @@ import java.util.NoSuchElementException; * * @since 0.8.7 */ -class ConfigIterator implements Iterator> { +class ConfigIterator implements Iterator>, Closeable { private BufferedReader input; private ConfigEntry next; @@ -54,11 +57,9 @@ class ConfigIterator implements Iterator> { /** * An iterator over the key/value pairs in the file. */ - public ConfigIterator(File file) { - try { + public ConfigIterator(File file) throws IOException { FileInputStream fileStream = new FileInputStream(file); - input = new BufferedReader(new InputStreamReader(fileStream)); - } catch (IOException ioe) {} + input = new BufferedReader(new InputStreamReader(fileStream, "UTF-8")); } public boolean hasNext() { @@ -70,7 +71,7 @@ class ConfigIterator implements Iterator> { String inputLine = input.readLine(); while (inputLine != null) { inputLine = ConfigParser.stripComments(inputLine); - String[] splitLine = inputLine.split("="); + String[] splitLine = DataHelper.split(inputLine, "="); if (splitLine.length == 2) { next = new ConfigEntry(splitLine[0].trim().toLowerCase(Locale.US), splitLine[1].trim()); return true; diff --git a/apps/addressbook/java/src/net/i2p/addressbook/ConfigParser.java b/apps/addressbook/java/src/net/i2p/addressbook/ConfigParser.java index 47e9bb0fb..625b6e3d0 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/ConfigParser.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/ConfigParser.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import net.i2p.data.DataHelper; import net.i2p.util.SecureFile; import net.i2p.util.SecureFileOutputStream; import net.i2p.util.SystemVersion; @@ -64,10 +65,11 @@ class ConfigParser { if (inputLine.startsWith(";")) { return ""; } - if (inputLine.split("#").length > 0) { - return inputLine.split("#")[0]; + int hash = inputLine.indexOf('#'); + if (hash >= 0) { + return inputLine.substring(0, hash); } else { - return ""; + return inputLine; } } @@ -92,7 +94,7 @@ class ConfigParser { inputLine = input.readLine(); while (inputLine != null) { inputLine = stripComments(inputLine); - String[] splitLine = inputLine.split("="); + String[] splitLine = DataHelper.split(inputLine, "="); if (splitLine.length == 2) { result.put(splitLine[0].trim().toLowerCase(Locale.US), splitLine[1].trim()); } @@ -115,7 +117,7 @@ class ConfigParser { public static Map parse(File file) throws IOException { FileInputStream fileStream = new FileInputStream(file); BufferedReader input = new BufferedReader(new InputStreamReader( - fileStream)); + fileStream, "UTF-8")); Map rv = parse(input); try { fileStream.close(); @@ -204,7 +206,7 @@ class ConfigParser { public static List parseSubscriptions(File file) throws IOException { FileInputStream fileStream = new FileInputStream(file); BufferedReader input = new BufferedReader(new InputStreamReader( - fileStream)); + fileStream, "UTF-8")); List rv = parseSubscriptions(input); try { fileStream.close(); diff --git a/apps/addressbook/java/src/net/i2p/addressbook/DaemonThread.java b/apps/addressbook/java/src/net/i2p/addressbook/DaemonThread.java index fe74c7a83..b0689a208 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/DaemonThread.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/DaemonThread.java @@ -25,6 +25,7 @@ import java.util.Properties; import net.i2p.I2PAppContext; import net.i2p.client.naming.NamingServiceUpdater; +import net.i2p.util.I2PAppThread; /** * A thread that waits five minutes, then runs the addressbook daemon. @@ -32,7 +33,7 @@ import net.i2p.client.naming.NamingServiceUpdater; * @author Ragnarok * */ -public class DaemonThread extends Thread implements NamingServiceUpdater { +public class DaemonThread extends I2PAppThread implements NamingServiceUpdater { private String[] args; diff --git a/apps/addressbook/java/src/net/i2p/addressbook/Log.java b/apps/addressbook/java/src/net/i2p/addressbook/Log.java index d0f01904f..a87af2537 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/Log.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/Log.java @@ -23,8 +23,9 @@ package net.i2p.addressbook; import java.io.BufferedWriter; import java.io.File; -import java.io.FileWriter; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStreamWriter; import java.util.Date; /** @@ -56,8 +57,8 @@ class Log { public void append(String entry) { BufferedWriter bw = null; try { - bw = new BufferedWriter(new FileWriter(this.file, - true)); + bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.file, + true), "UTF-8")); String timestamp = new Date().toString(); bw.write(timestamp + " -- " + entry); bw.newLine(); diff --git a/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java b/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java index cf7b04fc0..74e946f95 100644 --- a/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java +++ b/apps/addressbook/java/src/net/i2p/addressbook/SubscriptionIterator.java @@ -26,6 +26,7 @@ import java.util.Iterator; import java.util.List; import net.i2p.I2PAppContext; +import net.i2p.util.PortMapper; /** * An iterator over the subscriptions in a SubscriptionList. Note that this iterator @@ -69,11 +70,14 @@ class SubscriptionIterator implements Iterator { * Yes, the EepGet fetch() is done in here in next(). * * see java.util.Iterator#next() - * @return an AddressBook (empty if the minimum delay has not been met) + * @return non-null AddressBook (empty if the minimum delay has not been met, + * or there is no proxy tunnel, or the fetch otherwise fails) */ public AddressBook next() { Subscription sub = this.subIterator.next(); - if (sub.getLastFetched() + this.delay < I2PAppContext.getGlobalContext().clock().now()) { + if (sub.getLastFetched() + this.delay < I2PAppContext.getGlobalContext().clock().now() && + I2PAppContext.getGlobalContext().portMapper().getPort(PortMapper.SVC_HTTP_PROXY) >= 0 && + !I2PAppContext.getGlobalContext().getBooleanProperty("i2p.vmCommSystem")) { //System.err.println("Fetching addressbook from " + sub.getLocation()); return new AddressBook(sub, this.proxyHost, this.proxyPort); } else { diff --git a/apps/addressbook/java/src/net/i2p/addressbook/package.html b/apps/addressbook/java/src/net/i2p/addressbook/package.html new file mode 100644 index 000000000..cd4490657 --- /dev/null +++ b/apps/addressbook/java/src/net/i2p/addressbook/package.html @@ -0,0 +1,11 @@ + + +

+The addressbook application, which fetches hosts.txt files from subscription URLS via +HTTP and adds new hosts to the local database. +While implemented as a webapp, this application contains no user interface. +May also be packaged as a jar, as is done for Android. +The webapp named 'addressbook' in the console is actually SusiDNS. +

+ + diff --git a/apps/addressbook/web.xml b/apps/addressbook/web.xml index b791b4ea0..d86d32289 100644 --- a/apps/addressbook/web.xml +++ b/apps/addressbook/web.xml @@ -4,6 +4,15 @@ "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"> + + XSSFilter + net.i2p.servlet.filters.XSSFilter + + + XSSFilter + /* + + addressbook net.i2p.addressbook.Servlet @@ -19,4 +28,11 @@ /* + + + 30 + + true + + diff --git a/apps/admin/java/src/net/i2p/router/admin/AdminRunner.java b/apps/admin/java/src/net/i2p/router/admin/AdminRunner.java index 2851d7d86..d5c63c60d 100644 --- a/apps/admin/java/src/net/i2p/router/admin/AdminRunner.java +++ b/apps/admin/java/src/net/i2p/router/admin/AdminRunner.java @@ -11,6 +11,7 @@ import java.util.Iterator; import java.util.Set; import net.i2p.data.Hash; +import net.i2p.data.DataHelper import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.util.I2PThread; @@ -47,7 +48,7 @@ class AdminRunner implements Runnable { reply(out, "this is not a website"); } else if ( (command.indexOf("routerStats.html") >= 0) || (command.indexOf("oldstats.jsp") >= 0) ) { try { - out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes()); + out.write(DataHelper.getASCII("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n")); _generator.generateStatsPage(new OutputStreamWriter(out)); out.close(); } catch (IOException ioe) { @@ -61,7 +62,7 @@ class AdminRunner implements Runnable { reply(out, shutdown(command)); } else if (true || command.indexOf("routerConsole.html") > 0) { try { - out.write("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n".getBytes()); + out.write(DataHelper.getASCII("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n")); _context.router().renderStatusHTML(new OutputStreamWriter(out)); out.close(); } catch (IOException ioe) { @@ -80,7 +81,7 @@ class AdminRunner implements Runnable { reply.append("Content-type: text/html\n\n"); reply.append(content); try { - out.write(reply.toString().getBytes()); + out.write(DataHelper.getASCII(reply.toString())); out.close(); } catch (IOException ioe) { if (_log.shouldLog(Log.WARN)) @@ -97,7 +98,7 @@ class AdminRunner implements Runnable { reply.append("Content-type: text/plain\n\n"); reply.append(content); try { - out.write(reply.toString().getBytes()); + out.write(DataHelper.getASCII(reply.toString())); out.close(); } catch (IOException ioe) { if (_log.shouldLog(Log.WARN)) diff --git a/apps/apparmor/home.i2p.i2prouter b/apps/apparmor/home.i2p.i2prouter new file mode 100644 index 000000000..7f7dcb7ef --- /dev/null +++ b/apps/apparmor/home.i2p.i2prouter @@ -0,0 +1,99 @@ +#Last Modified: Sun Dec 06 12:30:32 2015 +# vim:syntax=apparmor et ts=8 sw=4 + +#include + +$INSTALL_PATH/{i2prouter,runplain.sh} flags=(complain) { + #include + #include + #include + #include + + capability sys_ptrace, + network inet stream, + network inet6 stream, + + $INSTALL_PATH/ r, + $INSTALL_PATH/{i2psvc,wrapper} rmix, + owner $INSTALL_PATH/** rwkm, + + # Needed for Java + owner @{PROC} r, + owner @{PROC}/[0-9]*/ r, + owner @{PROC}/[0-9]*/status r, + owner @{PROC}/[0-9]*/stat r, + owner @{PROC}/[0-9]*/cmdline r, + @{PROC}/uptime r, + @{PROC}/sys/kernel/pid_max r, + /sys/devices/system/cpu/ r, + /sys/devices/system/cpu/** r, + + /dev/random r, + /dev/urandom r, + + @{PROC}/1/comm r, + + /etc/ssl/certs/java/** r, + /etc/timezone r, + /usr/share/javazi/** r, + + # Debian + /etc/java-{6,7,8}-openjdk/** r, + /usr/lib/jvm/default-java/jre/bin/java rix, + + # Debian, Ubuntu, openSUSE + /usr/lib{,32,64}/jvm/java-*-openjdk-*/jre/bin/java rix, + /usr/lib{,32,64}/jvm/java-*-openjdk-*/jre/bin/keytool rix, + + # Raspbian + /usr/lib/jvm/jdk-*-oracle-*/jre/bin/java rix, + /usr/lib/jvm/jdk-*-oracle-*/jre/bin/keytool rix, + + + # Fonts are needed for I2P's graphs + /usr/share/java/java-atk-wrapper.jar r, + + # Used by some plugins + /usr/share/java/eclipse-ecj-*.jar r, + + /{,var/}tmp/ rwm, + owner /{,var/}tmp/** rwkm, + + /{,usr/}bin/{,b,d}ash rix, + /{,usr/}bin/cat rix, + /{,usr/}bin/cut rix, + /{,usr/}bin/dirname rix, + /{,usr/}bin/expr rix, + /{,usr/}bin/{,g,m}awk rix, + /{,usr/}bin/grep rix, + /{,usr/}bin/id rix, + /{,usr/}bin/ldd rix, + /{,usr/}bin/ls rix, + /{,usr/}bin/mkdir rix, + /{,usr/}bin/nohup rix, + /{,usr/}bin/ps rix, + /{,usr/}bin/rm rix, + /{,usr/}bin/sed rix, + /{,usr/}bin/sleep rix, + /{,usr/}bin/tail rix, + /{,usr/}bin/tr rix, + /{,usr/}bin/uname rix, + /{,usr/}bin/which rix, + + @{HOME}/.java/fonts/** r, + owner @{HOME}/.i2p/ rw, + owner @{HOME}/.i2p/** rwk, + + # Prevent spamming the logs + deny owner @{HOME}/.java/ wk, + deny @{HOME}/.fontconfig/ wk, + deny @{HOME}/.java/fonts/** w, + deny /dev/tty rw, + deny /dev/pts/[0-9]* rw, + deny @{PROC}/[0-9]*/fd/ r, + deny /usr/local/share/fonts/ r, + deny /var/cache/fontconfig/ wk, + # Used by some versions of the Tanuki wrapper but never used by I2P + deny /usr/share/java/hamcrest*.jar r, + deny /usr/share/java/junit*.jar r, +} diff --git a/apps/desktopgui/bundle-messages.sh b/apps/desktopgui/bundle-messages.sh index 22b6038ce..6823dde03 100644 --- a/apps/desktopgui/bundle-messages.sh +++ b/apps/desktopgui/bundle-messages.sh @@ -26,12 +26,12 @@ then fi # on windows, one must specify the path of commnad find -# since windows has its own retarded version of find. +# since windows has its own version of find. if which find|grep -q -i windows ; then export PATH=.:/bin:/usr/local/bin:$PATH fi # Fast mode - update ondemond -# set LG2 to the language you need in envrionment varibales to enable this +# set LG2 to the language you need in environment variables to enable this # add ../java/ so the refs will work in the po file JPATHS="src" @@ -64,19 +64,19 @@ do echo "Updating the $i file from the tags..." # extract strings from java and jsp files, and update messages.po files # translate calls must be one of the forms: - # _("foo") + # _t("foo") # _x("foo") - # intl._("foo") + # intl._t("foo") # intl.title("foo") - # handler._("foo") - # formhandler._("foo") + # handler._t("foo") + # formhandler._t("foo") # net.i2p.router.web.Messages.getString("foo") # In a jsp, you must use a helper or handler that has the context set. # To start a new translation, copy the header from an old translation to the new .po file, # then ant distclean updater. find $JPATHS -name *.java > $TMPFILE xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\ - --keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \ + --keyword=_t --keyword=_x --keyword=intl._ --keyword=intl.title \ --keyword=handler._ --keyword=formhandler._ \ --keyword=net.i2p.router.web.Messages.getString \ -o ${i}t diff --git a/apps/desktopgui/locale/messages_pl.po b/apps/desktopgui/locale/messages_pl.po index dbc2c92bf..f47b0aeac 100644 --- a/apps/desktopgui/locale/messages_pl.po +++ b/apps/desktopgui/locale/messages_pl.po @@ -3,20 +3,22 @@ # This file is distributed under the same license as the desktopgui package. # To contribute translations, see http://www.i2p2.de/newdevelopers # -# , 2011. +# Translators: +# PolishAnon , 2011 +# polacco , 2015 msgid "" msgstr "" "Project-Id-Version: I2P\n" -"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n" -"POT-Creation-Date: 2011-03-03 18:29+0000\n" -"PO-Revision-Date: 2011-05-25 18:36+0000\n" -"Last-Translator: PolishAnon \n" -"Language-Team: Polish (http://www.transifex.net/projects/p/I2P/team/pl/)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-01-09 19:27+0000\n" +"PO-Revision-Date: 2015-02-17 20:54+0000\n" +"Last-Translator: polacco \n" +"Language-Team: Polish (http://www.transifex.com/projects/p/I2P/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: src/net/i2p/desktopgui/ExternalTrayManager.java:23 msgid "Start I2P" @@ -32,7 +34,7 @@ msgstr "Uruchamianie" #: src/net/i2p/desktopgui/InternalTrayManager.java:26 msgid "Launch I2P Browser" -msgstr "Uruchom Przeglądarke I2P" +msgstr "Uruchom przeglądarkę I2P" #: src/net/i2p/desktopgui/InternalTrayManager.java:50 msgid "Configure desktopgui" @@ -46,12 +48,10 @@ msgstr "Zrestartuj I2P" msgid "Stop I2P" msgstr "Zatrzymaj I2P" -#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44 +#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:43 msgid "Tray icon configuration" msgstr "Konfiguracja ikony zasobnika" -#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47 +#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:46 msgid "Should tray icon be enabled?" msgstr "Czy ikona zasobnika powinna być aktywna?" - - diff --git a/apps/desktopgui/locale/messages_pt_BR.po b/apps/desktopgui/locale/messages_pt_BR.po index 667269059..6f889afe4 100644 --- a/apps/desktopgui/locale/messages_pt_BR.po +++ b/apps/desktopgui/locale/messages_pt_BR.po @@ -4,14 +4,15 @@ # To contribute translations, see http://www.i2p2.de/newdevelopers # # Translators: +# testsubject67 , 2014 # blueboy, 2013 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-03-03 18:29+0000\n" -"PO-Revision-Date: 2013-11-23 16:31+0000\n" -"Last-Translator: blueboy\n" +"POT-Creation-Date: 2014-01-09 19:27+0000\n" +"PO-Revision-Date: 2014-07-05 17:40+0000\n" +"Last-Translator: testsubject67 \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/I2P/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -33,11 +34,11 @@ msgstr "Conectando" #: src/net/i2p/desktopgui/InternalTrayManager.java:26 msgid "Launch I2P Browser" -msgstr "" +msgstr "Lançar o navegador I2P " #: src/net/i2p/desktopgui/InternalTrayManager.java:50 msgid "Configure desktopgui" -msgstr "" +msgstr "Configurar desktopgui" #: src/net/i2p/desktopgui/InternalTrayManager.java:67 msgid "Restart I2P" @@ -47,10 +48,10 @@ msgstr "Reinicializar o roteador I2P" msgid "Stop I2P" msgstr "Interromper o roteador I2P" -#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44 +#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:43 msgid "Tray icon configuration" -msgstr "" +msgstr "Configuração de ícone de bandeja" -#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47 +#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:46 msgid "Should tray icon be enabled?" -msgstr "" +msgstr "Ativar ícone de bandeja?" diff --git a/apps/desktopgui/locale/messages_uk.po b/apps/desktopgui/locale/messages_uk.po index e82777739..3084ecab5 100644 --- a/apps/desktopgui/locale/messages_uk.po +++ b/apps/desktopgui/locale/messages_uk.po @@ -3,20 +3,23 @@ # This file is distributed under the same license as the desktopgui package. # To contribute translations, see http://www.i2p2.de/newdevelopers # -# , 2011. +# Translators: +# Denis Lysenko , 2011 +# LinuxChata, 2014 +# madjong , 2014 msgid "" msgstr "" "Project-Id-Version: I2P\n" -"Report-Msgid-Bugs-To: https://trac.i2p2.de/\n" -"POT-Creation-Date: 2011-03-03 18:29+0000\n" -"PO-Revision-Date: 2011-06-19 14:01+0000\n" -"Last-Translator: Pharmasolin \n" -"Language-Team: Ukrainian (Ukraine) (http://www.transifex.net/projects/p/I2P/team/uk_UA/)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-01-09 19:27+0000\n" +"PO-Revision-Date: 2015-08-07 16:31+0000\n" +"Last-Translator: Denis Lysenko \n" +"Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/otf/I2P/language/uk_UA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: uk_UA\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: src/net/i2p/desktopgui/ExternalTrayManager.java:23 msgid "Start I2P" @@ -46,12 +49,10 @@ msgstr "Перезапустити I2P" msgid "Stop I2P" msgstr "Зупинити I2P" -#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:44 +#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:43 msgid "Tray icon configuration" -msgstr "Настройка трей-іконки" +msgstr "Налаштування трей-іконки" -#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:47 +#: src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java:46 msgid "Should tray icon be enabled?" -msgstr "Чм повинна трей-іконка бути включена?" - - +msgstr "Чи повинна трей-іконка бути включена?" diff --git a/apps/desktopgui/src/net/i2p/desktopgui/ExternalTrayManager.java b/apps/desktopgui/src/net/i2p/desktopgui/ExternalTrayManager.java index 6fea46fef..2a3a16b63 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/ExternalTrayManager.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/ExternalTrayManager.java @@ -20,7 +20,7 @@ public class ExternalTrayManager extends TrayManager { @Override public PopupMenu getMainMenu() { PopupMenu popup = new PopupMenu(); - MenuItem startItem = new MenuItem(_("Start I2P")); + MenuItem startItem = new MenuItem(_t("Start I2P")); startItem.addActionListener(new ActionListener() { @Override @@ -35,7 +35,7 @@ public class ExternalTrayManager extends TrayManager { @Override protected void done() { - trayIcon.displayMessage(_("Starting"), _("I2P is starting!"), TrayIcon.MessageType.INFO); + trayIcon.displayMessage(_t("Starting"), _t("I2P is starting!"), TrayIcon.MessageType.INFO); //Hide the tray icon. //We cannot stop the desktopgui program entirely, //since that risks killing the I2P process as well. diff --git a/apps/desktopgui/src/net/i2p/desktopgui/InternalTrayManager.java b/apps/desktopgui/src/net/i2p/desktopgui/InternalTrayManager.java index e1247dde6..1cb464308 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/InternalTrayManager.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/InternalTrayManager.java @@ -23,7 +23,7 @@ public class InternalTrayManager extends TrayManager { public PopupMenu getMainMenu() { PopupMenu popup = new PopupMenu(); - MenuItem browserLauncher = new MenuItem(_("Launch I2P Browser")); + MenuItem browserLauncher = new MenuItem(_t("Launch I2P Browser")); browserLauncher.addActionListener(new ActionListener() { @Override @@ -47,7 +47,7 @@ public class InternalTrayManager extends TrayManager { }.execute(); } }); - MenuItem desktopguiConfigurationLauncher = new MenuItem(_("Configure desktopgui")); + MenuItem desktopguiConfigurationLauncher = new MenuItem(_t("Configure desktopgui")); desktopguiConfigurationLauncher.addActionListener(new ActionListener() { @Override @@ -64,7 +64,7 @@ public class InternalTrayManager extends TrayManager { } }); - MenuItem restartItem = new MenuItem(_("Restart I2P")); + MenuItem restartItem = new MenuItem(_t("Restart I2P")); restartItem.addActionListener(new ActionListener() { @Override @@ -82,7 +82,7 @@ public class InternalTrayManager extends TrayManager { } }); - MenuItem stopItem = new MenuItem(_("Stop I2P")); + MenuItem stopItem = new MenuItem(_t("Stop I2P")); stopItem.addActionListener(new ActionListener() { @Override diff --git a/apps/desktopgui/src/net/i2p/desktopgui/TrayManager.java b/apps/desktopgui/src/net/i2p/desktopgui/TrayManager.java index f124ee3f6..227050735 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/TrayManager.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/TrayManager.java @@ -78,7 +78,7 @@ public abstract class TrayManager { return image; } - protected static String _(String s) { - return DesktopguiTranslator._(s); + protected static String _t(String s) { + return DesktopguiTranslator._t(s); } } diff --git a/apps/desktopgui/src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java index 1e49f6609..a697c5779 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java @@ -40,10 +40,10 @@ public class DesktopguiConfigurationFrame extends javax.swing.JFrame { cancelButton = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - setTitle(_("Tray icon configuration")); + setTitle(_t("Tray icon configuration")); desktopguiEnabled.setSelected(true); - desktopguiEnabled.setText(_("Should tray icon be enabled?")); + desktopguiEnabled.setText(_t("Should tray icon be enabled?")); desktopguiEnabled.setActionCommand("shouldDesktopguiBeEnabled"); okButton.setText("OK"); @@ -98,8 +98,8 @@ public class DesktopguiConfigurationFrame extends javax.swing.JFrame { configureDesktopgui(); }//GEN-LAST:event_okButtonMouseReleased - protected static String _(String s) { - return DesktopguiTranslator._(s); + protected static String _t(String s) { + return DesktopguiTranslator._t(s); } private void configureDesktopgui() { diff --git a/apps/desktopgui/src/net/i2p/desktopgui/i18n/DesktopguiTranslator.java b/apps/desktopgui/src/net/i2p/desktopgui/i18n/DesktopguiTranslator.java index e95cbc01f..3778c4ad9 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/i18n/DesktopguiTranslator.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/i18n/DesktopguiTranslator.java @@ -16,11 +16,11 @@ public class DesktopguiTranslator { return ctx; } - public static String _(String s) { + public static String _t(String s) { return Translate.getString(s, getRouterContext(), BUNDLE_NAME); } - public static String _(String s, Object o) { + public static String _t(String s, Object o) { return Translate.getString(s, o, getRouterContext(), BUNDLE_NAME); } } diff --git a/apps/i2psnark/COPYING b/apps/i2psnark/COPYING index d60c31a97..a0d98f2a6 100644 --- a/apps/i2psnark/COPYING +++ b/apps/i2psnark/COPYING @@ -1,340 +1 @@ - 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. +See ../../licenses/LICENSE-GPLv2.txt diff --git a/apps/i2psnark/TODO b/apps/i2psnark/TODO deleted file mode 100644 index 6f89c0f50..000000000 --- a/apps/i2psnark/TODO +++ /dev/null @@ -1,24 +0,0 @@ -- I2PSnark: - - add multitorrent support by checking the metainfo hash in the - PeerAcceptor and feeding it off to the appropriate coordinator - - add a web interface - -- BEncode - - Byte array length indicator can overflow. - - Support really big BigNums (only 256 chars allowed now) - - Better BEValue toString(). Uses stupid heuristic now for debugging. - - Implemented bencoding. - - Remove application level hack to calculate sha1 hash for metainfo - (But can it be done as efficiently?) - -- Storage - - Check file name filter. - -- TrackerClient - - Support undocumented &numwant= request. - -- PeerCoordinator - - Disconnect from other seeds as soon as you are a seed yourself. - -- Text UI - - Make it completely silent. diff --git a/apps/i2psnark/authors.snark b/apps/i2psnark/authors-snark.txt similarity index 100% rename from apps/i2psnark/authors.snark rename to apps/i2psnark/authors-snark.txt diff --git a/apps/i2psnark/changelog.snark b/apps/i2psnark/changelog-snark.txt similarity index 100% rename from apps/i2psnark/changelog.snark rename to apps/i2psnark/changelog-snark.txt diff --git a/apps/i2psnark/java/build.xml b/apps/i2psnark/java/build.xml index a4fd04c06..5a4d3dd24 100644 --- a/apps/i2psnark/java/build.xml +++ b/apps/i2psnark/java/build.xml @@ -100,15 +100,15 @@ - - + + - + @@ -121,7 +121,7 @@ - + diff --git a/apps/i2psnark/java/bundle-messages.sh b/apps/i2psnark/java/bundle-messages.sh index c301622ed..7ef207a6d 100755 --- a/apps/i2psnark/java/bundle-messages.sh +++ b/apps/i2psnark/java/bundle-messages.sh @@ -25,12 +25,12 @@ then fi # on windows, one must specify the path of commnad find -# since windows has its own retarded version of find. +# since windows has its own version of find. if which find|grep -q -i windows ; then export PATH=.:/bin:/usr/local/bin:$PATH fi # Fast mode - update ondemond -# set LG2 to the language you need in envrionment varibales to enable this +# set LG2 to the language you need in environment variables to enable this # add ../java/ so the refs will work in the po file JPATHS="../java/src" @@ -63,13 +63,13 @@ do echo "Updating the $i file from the tags..." # extract strings from java and jsp files, and update messages.po files # translate calls must be one of the forms: - # _("foo") + # _t("foo") # _x("foo") # To start a new translation, copy the header from an old translation to the new .po file, # then ant distclean poupdate. find $JPATHS -name *.java > $TMPFILE xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\ - --keyword=_ --keyword=_x \ + --keyword=_t --keyword=_x \ -o ${i}t if [ $? -ne 0 ] then diff --git a/apps/i2psnark/java/src/org/klomp/snark/BitField.java b/apps/i2psnark/java/src/org/klomp/snark/BitField.java index d18ef1343..f724f71d7 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/BitField.java +++ b/apps/i2psnark/java/src/org/klomp/snark/BitField.java @@ -20,6 +20,8 @@ package org.klomp.snark; +import java.util.Arrays; + /** * Container of a byte array representing set and unset bits. @@ -66,7 +68,7 @@ public class BitField /** * This returns the actual byte array used. Changes to this array - * effect this BitField. Note that some bits at the end of the byte + * affect this BitField. Note that some bits at the end of the byte * array are supposed to be always unset if they represent bits * bigger then the size of the bitfield. */ @@ -105,6 +107,37 @@ public class BitField } } + /** + * Sets the given bit to false. + * + * @exception IndexOutOfBoundsException if bit is smaller then zero + * bigger then size (inclusive). + * @since 0.9.22 + */ + public void clear(int bit) + { + if (bit < 0 || bit >= size) + throw new IndexOutOfBoundsException(Integer.toString(bit)); + int index = bit/8; + int mask = 128 >> (bit % 8); + synchronized(this) { + if ((bitfield[index] & mask) != 0) { + count--; + bitfield[index] &= ~mask; + } + } + } + + /** + * Sets all bits to true. + * + * @since 0.9.21 + */ + public void setAll() { + Arrays.fill(bitfield, (byte) 0xff); + count = size; + } + /** * Return true if the bit is set or false if it is not. * diff --git a/apps/i2psnark/java/src/org/klomp/snark/CompleteListener.java b/apps/i2psnark/java/src/org/klomp/snark/CompleteListener.java index 77fa9c98b..1d48654ba 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/CompleteListener.java +++ b/apps/i2psnark/java/src/org/klomp/snark/CompleteListener.java @@ -54,7 +54,15 @@ public interface CompleteListener { */ public void gotPiece(Snark snark); - // not really listeners but the easiest way to get back to an optional SnarkManager + /** not really listeners but the easiest way to get back to an optional SnarkManager */ public long getSavedTorrentTime(Snark snark); public BitField getSavedTorrentBitField(Snark snark); + /** + * @since 0.9.15 + */ + public boolean getSavedPreserveNamesSetting(Snark snark); + /** + * @since 0.9.15 + */ + public long getSavedUploaded(Snark snark); } diff --git a/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java b/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java index 057e0780f..18493854d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java +++ b/apps/i2psnark/java/src/org/klomp/snark/ConnectionAcceptor.java @@ -24,6 +24,7 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.ConnectException; import net.i2p.I2PAppContext; import net.i2p.I2PException; @@ -213,6 +214,20 @@ class ConnectionAcceptor implements Runnable } } } + catch (ConnectException ioe) + { + // This is presumed to be due to socket closing by I2PSnarkUtil.disconnect(), + // which does not currently call our halt(), although it should + if (_log.shouldWarn()) + _log.warn("Error while accepting", ioe); + synchronized(this) { + if (!stop) { + locked_halt(); + thread = null; + stop = true; + } + } + } catch (IOException ioe) { int level = stop ? Log.WARN : Log.ERROR; diff --git a/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java b/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java index 001897764..a711d9a05 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java +++ b/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandler.java @@ -42,7 +42,7 @@ abstract class ExtensionHandler { * @param dht advertise DHT capability * @return bencoded outgoing handshake message */ - public static byte[] getHandshake(int metasize, boolean pexAndMetadata, boolean dht) { + public static byte[] getHandshake(int metasize, boolean pexAndMetadata, boolean dht, boolean uploadOnly) { Map handshake = new HashMap(); Map m = new HashMap(); if (pexAndMetadata) { @@ -59,6 +59,9 @@ abstract class ExtensionHandler { handshake.put("p", Integer.valueOf(TrackerClient.PORT)); handshake.put("v", "I2PSnark"); handshake.put("reqq", Integer.valueOf(5)); + // BEP 21 + if (uploadOnly) + handshake.put("upload_only", Integer.valueOf(1)); return BEncoder.bencode(handshake); } @@ -90,17 +93,20 @@ abstract class ExtensionHandler { peer.setHandshakeMap(map); Map msgmap = map.get("m").getMap(); - if (msgmap.get(TYPE_PEX) != null) { - if (log.shouldLog(Log.DEBUG)) - log.debug("Peer supports PEX extension: " + peer); - // peer state calls peer listener calls sendPEX() - } + if (log.shouldLog(Log.DEBUG)) + log.debug("Peer " + peer + " supports extensions: " + msgmap.keySet()); - if (msgmap.get(TYPE_DHT) != null) { - if (log.shouldLog(Log.DEBUG)) - log.debug("Peer supports DHT extension: " + peer); - // peer state calls peer listener calls sendDHT() - } + //if (msgmap.get(TYPE_PEX) != null) { + // if (log.shouldLog(Log.DEBUG)) + // log.debug("Peer supports PEX extension: " + peer); + // // peer state calls peer listener calls sendPEX() + //} + + //if (msgmap.get(TYPE_DHT) != null) { + // if (log.shouldLog(Log.DEBUG)) + // log.debug("Peer supports DHT extension: " + peer); + // // peer state calls peer listener calls sendDHT() + //} MagnetState state = peer.getMagnetState(); @@ -204,30 +210,31 @@ abstract class ExtensionHandler { if (log.shouldLog(Log.DEBUG)) log.debug("Got request for " + piece + " from: " + peer); byte[] pc; + int totalSize; synchronized(state) { pc = state.getChunk(piece); + totalSize = state.getSize(); } - sendPiece(peer, piece, pc); + sendPiece(peer, piece, pc, totalSize); // Do this here because PeerConnectionOut only reports for PIECE messages peer.uploaded(pc.length); listener.uploaded(peer, pc.length); } else if (type == TYPE_DATA) { - int size = map.get("total_size").getInt(); - if (log.shouldLog(Log.DEBUG)) - log.debug("Got data for " + piece + " length " + size + " from: " + peer); + // On close reading of BEP 9, this is the total metadata size. + // Prior to 0.9.21, we sent the piece size, so we can't count on it. + // just ignore it. The actual length will be verified in saveChunk() + //int size = map.get("total_size").getInt(); + //if (log.shouldLog(Log.DEBUG)) + // log.debug("Got data for " + piece + " length " + size + " from: " + peer); boolean done; int chk = -1; synchronized(state) { if (state.isComplete()) return; int len = is.available(); - if (len != size) { - // probably fatal - if (log.shouldLog(Log.WARN)) - log.warn("total_size " + size + " but avail data " + len); - } peer.downloaded(len); listener.downloaded(peer, len); + // this checks the size done = state.saveChunk(piece, bs, bs.length - len, len); if (log.shouldLog(Log.INFO)) log.info("Got chunk " + piece + " from " + peer); @@ -290,11 +297,15 @@ abstract class ExtensionHandler { } } - private static void sendPiece(Peer peer, int piece, byte[] data) { + private static void sendPiece(Peer peer, int piece, byte[] data, int totalSize) { Map map = new HashMap(); map.put("msg_type", Integer.valueOf(TYPE_DATA)); map.put("piece", Integer.valueOf(piece)); - map.put("total_size", Integer.valueOf(data.length)); + // BEP 9 + // "This key has the same semantics as the 'metadata_size' in the extension header" + // which apparently means the same value. Fixed in 0.9.21. + //map.put("total_size", Integer.valueOf(data.length)); + map.put("total_size", Integer.valueOf(totalSize)); byte[] dict = BEncoder.bencode(map); byte[] payload = new byte[dict.length + data.length]; System.arraycopy(dict, 0, payload, 0, dict.length); diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index d1038534f..1bff1a74b 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -3,14 +3,18 @@ package org.klomp.snark; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; + import net.i2p.I2PAppContext; import net.i2p.I2PException; +import net.i2p.client.I2PClient; import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.client.streaming.I2PServerSocket; @@ -71,9 +75,7 @@ public class I2PSnarkUtil { private static final int EEPGET_CONNECT_TIMEOUT_SHORT = 5*1000; public static final int DEFAULT_STARTUP_DELAY = 3; public static final boolean DEFAULT_USE_OPENTRACKERS = true; - public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a"; - public static final int DEFAULT_MAX_UP_BW = 8; //KBps - public static final int MAX_CONNECTIONS = 16; // per torrent + public static final int MAX_CONNECTIONS = 24; // per torrent public static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond"; public static final boolean DEFAULT_USE_DHT = true; public static final String EEPGET_USER_AGENT = "I2PSnark"; @@ -95,18 +97,17 @@ public class I2PSnarkUtil { setI2CPConfig("127.0.0.1", 7654, null); _banlist = new ConcurrentHashSet(); _maxUploaders = Snark.MAX_TOTAL_UPLOADERS; - _maxUpBW = DEFAULT_MAX_UP_BW; + _maxUpBW = SnarkManager.DEFAULT_MAX_UP_BW; _maxConnections = MAX_CONNECTIONS; _startupDelay = DEFAULT_STARTUP_DELAY; _shouldUseOT = DEFAULT_USE_OPENTRACKERS; - // FIXME split if default has more than one - _openTrackers = Collections.singletonList(DEFAULT_OPENTRACKERS); + _openTrackers = Collections.emptyList(); _shouldUseDHT = DEFAULT_USE_DHT; // This is used for both announce replies and .torrent file downloads, // so it must be available even if not connected to I2CP. // so much for multiple instances - _tmpDir = new SecureDirectory(ctx.getTempDir(), baseName); - FileUtil.rmdir(_tmpDir, false); + _tmpDir = new SecureDirectory(ctx.getTempDir(), baseName + '-' + ctx.random().nextInt()); + //FileUtil.rmdir(_tmpDir, false); _tmpDir.mkdirs(); } @@ -135,6 +136,7 @@ public class I2PSnarkUtil { public boolean configured() { return _configured; } + @SuppressWarnings({"unchecked", "rawtypes"}) public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) { if (i2cpHost != null) _i2cpHost = i2cpHost; @@ -255,6 +257,8 @@ public class I2PSnarkUtil { opts.setProperty("i2p.streaming.disableRejectLogging", "true"); if (opts.getProperty("i2p.streaming.answerPings") == null) opts.setProperty("i2p.streaming.answerPings", "false"); + if (opts.getProperty(I2PClient.PROP_SIGTYPE) == null) + opts.setProperty(I2PClient.PROP_SIGTYPE, "EdDSA_SHA512_Ed25519"); _manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts); _connecting = false; } @@ -328,7 +332,7 @@ public class I2PSnarkUtil { return rv; } catch (I2PException ie) { _banlist.add(dest); - _context.simpleScheduler().addEvent(new Unbanlist(dest), 10*60*1000); + _context.simpleTimer2().addEvent(new Unbanlist(dest), 10*60*1000); IOException ioe = new IOException("Unable to reach the peer " + peer); ioe.initCause(ie); throw ioe; @@ -456,7 +460,7 @@ public class I2PSnarkUtil { return null; } - String getOurIPString() { + public String getOurIPString() { Destination dest = getMyDestination(); if (dest != null) return dest.toBase64(); @@ -565,12 +569,12 @@ public class I2PSnarkUtil { return rv; } - /** @param ot non-null */ + /** @param ot non-null list of announce URLs */ public void setOpenTrackers(List ot) { _openTrackers = ot; } - /** List of open trackers to use as backups + /** List of open tracker announce URLs to use as backups * @return non-null, possibly unmodifiable, empty if disabled */ public List getOpenTrackers() { @@ -580,7 +584,22 @@ public class I2PSnarkUtil { } /** - * List of open trackers to use as backups even if disabled + * Is this announce URL probably for an open tracker? + * + * @since 0.9.17 + */ + public boolean isKnownOpenTracker(String url) { + try { + URI u = new URI(url); + String host = u.getHost(); + return host != null && SnarkManager.KNOWN_OPENTRACKERS.contains(host); + } catch (URISyntaxException use) { + return false; + } + } + + /** + * List of open tracker announce URLs to use as backups even if disabled * @return non-null * @since 0.9.4 */ @@ -642,7 +661,7 @@ public class I2PSnarkUtil { * The {0} will be replaced by the parameter. * Single quotes must be doubled, i.e. ' -> '' in the string. * @param o parameter, not translated. - * To tranlslate parameter also, use _("foo {0} bar", _("baz")) + * To translate parameter also, use _t("foo {0} bar", _t("baz")) * Do not double the single quotes in the parameter. * Use autoboxing to call with ints, longs, floats, etc. */ diff --git a/apps/i2psnark/java/src/org/klomp/snark/IdleChecker.java b/apps/i2psnark/java/src/org/klomp/snark/IdleChecker.java index ff6454ee2..1a109654a 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/IdleChecker.java +++ b/apps/i2psnark/java/src/org/klomp/snark/IdleChecker.java @@ -29,6 +29,9 @@ class IdleChecker extends SimpleTimer2.TimedEvent { private int _consec; private int _consecNotRunning; private boolean _isIdle; + private String _lastIn = "3"; + private String _lastOut = "3"; + private final Object _lock = new Object(); private static final long CHECK_TIME = 63*1000; private static final int MAX_CONSEC_IDLE = 4; @@ -46,16 +49,19 @@ class IdleChecker extends SimpleTimer2.TimedEvent { } public void timeReached() { + synchronized (_lock) { + locked_timeReached(); + } + } + + private void locked_timeReached() { if (_util.connected()) { boolean torrentRunning = false; - boolean hasPeers = false; + int peerCount = 0; for (PeerCoordinator pc : _pcs) { if (!pc.halted()) { torrentRunning = true; - if (pc.getPeers() > 0) { - hasPeers = true; - break; - } + peerCount += pc.getPeers(); } } @@ -66,25 +72,29 @@ class IdleChecker extends SimpleTimer2.TimedEvent { if (_log.shouldLog(Log.WARN)) _log.warn("Closing tunnels on idle"); _util.disconnect(); - _mgr.addMessage(_util.getString("I2P tunnel closed.")); + _mgr.addMessage(_util.getString("No more torrents running.") + ' ' + + _util.getString("I2P tunnel closed.")); schedule(3 * CHECK_TIME); return; } } - if (hasPeers) { - if (_isIdle) - restoreTunnels(); + if (peerCount > 0) { + restoreTunnels(peerCount); } else { if (!_isIdle) { if (_consec++ >= MAX_CONSEC_IDLE) reduceTunnels(); + else + restoreTunnels(1); // pretend we have one peer for now } } } else { _isIdle = false; _consec = 0; _consecNotRunning = 0; + _lastIn = "3"; + _lastOut = "3"; } schedule(CHECK_TIME); } @@ -100,26 +110,50 @@ class IdleChecker extends SimpleTimer2.TimedEvent { } /** - * Restore tunnel count + * Restore or adjust tunnel count based on current peer count + * @param peerCount greater than zero */ - private void restoreTunnels() { - _isIdle = false; - if (_log.shouldLog(Log.INFO)) + private void restoreTunnels(int peerCount) { + if (_isIdle && _log.shouldLog(Log.INFO)) _log.info("Restoring tunnels on activity"); + _isIdle = false; Map opts = _util.getI2CPOptions(); String i = opts.get("inbound.quantity"); if (i == null) - i = "3"; + i = Integer.toString(SnarkManager.DEFAULT_TUNNEL_QUANTITY); String o = opts.get("outbound.quantity"); if (o == null) - o = "3"; + o = Integer.toString(SnarkManager.DEFAULT_TUNNEL_QUANTITY); String ib = opts.get("inbound.backupQuantity"); if (ib == null) ib = "0"; String ob= opts.get("outbound.backupQuantity"); if (ob == null) ob = "0"; - setTunnels(i, o, ib, ob); + // we don't need more tunnels than we have peers, reduce if so + // reduce to max(peerCount / 2, 2) + int in, out; + try { + in = Integer.parseInt(i); + } catch (NumberFormatException nfe) { + in = 3; + } + try { + out = Integer.parseInt(o); + } catch (NumberFormatException nfe) { + out = 3; + } + int target = Math.max(peerCount / 2, 2); + if (target < in && in > 2) { + in = target; + i = Integer.toString(in); + } + if (target < out && out > 2) { + out = target; + o = Integer.toString(out); + } + if (!(_lastIn.equals(i) && _lastOut.equals(o))) + setTunnels(i, o, ib, ob); } /** @@ -131,12 +165,16 @@ class IdleChecker extends SimpleTimer2.TimedEvent { if (mgr != null) { I2PSession sess = mgr.getSession(); if (sess != null) { + if (_log.shouldLog(Log.INFO)) + _log.info("New tunnel settings " + i + " / " + o + " / " + ib + " / " + ob); Properties newProps = new Properties(); newProps.setProperty("inbound.quantity", i); newProps.setProperty("outbound.quantity", o); newProps.setProperty("inbound.backupQuantity", ib); newProps.setProperty("outbound.backupQuantity", ob); sess.updateOptions(newProps); + _lastIn = i; + _lastOut = o; } } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/MagnetURI.java b/apps/i2psnark/java/src/org/klomp/snark/MagnetURI.java index 9044d62ff..dadba5849 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/MagnetURI.java +++ b/apps/i2psnark/java/src/org/klomp/snark/MagnetURI.java @@ -42,7 +42,7 @@ public class MagnetURI { name = util.getString("Magnet") + ' ' + ihash; String dn = getParam("dn", url); if (dn != null) - name += " (" + Storage.filterName(dn) + ')'; + name += " (" + dn + ')'; } else if (url.startsWith(MAGGOT)) { // maggot://0691e40aae02e552cfcb57af1dca56214680c0c5:0b557bbdf8718e95d352fbe994dec3a383e2ede7 ihash = url.substring(MAGGOT.length()).trim(); @@ -82,7 +82,7 @@ public class MagnetURI { } /** - * @return pretty name or null + * @return pretty name or null, NOT HTML escaped */ public String getName() { return _name; @@ -175,18 +175,25 @@ public class MagnetURI { } /** - * Decode %xx encoding, convert to UTF-8 if necessary - * Copied from i2ptunnel LocalHTTPServer + * Decode %xx encoding, convert to UTF-8 if necessary. + * Copied from i2ptunnel LocalHTTPServer. + * Also converts '+' to ' ' so the dn parameter comes out right + * These are coming in via a application/x-www-form-urlencoded form so + * the pluses are in there... + * hopefully any real + is encoded as %2B. + * * @since 0.9.1 */ private static String decode(String s) { - if (!s.contains("%")) + if (!(s.contains("%") || s.contains("+"))) return s; StringBuilder buf = new StringBuilder(s.length()); boolean utf8 = false; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); - if (c != '%') { + if (c == '+') { + buf.append(' '); + } else if (c != '%') { buf.append(c); } else { try { diff --git a/apps/i2psnark/java/src/org/klomp/snark/Message.java b/apps/i2psnark/java/src/org/klomp/snark/Message.java index 9f2197d2b..ee07ae9ef 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Message.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Message.java @@ -55,11 +55,13 @@ class Message byte type; // Used for HAVE, REQUEST, PIECE and CANCEL messages. + // Also SUGGEST, REJECT, ALLOWED_FAST // low byte used for EXTENSION message // low two bytes used for PORT message int piece; // Used for REQUEST, PIECE and CANCEL messages. + // Also REJECT int begin; int length; @@ -104,15 +106,18 @@ class Message int datalen = 1; // piece is 4 bytes. - if (type == HAVE || type == REQUEST || type == PIECE || type == CANCEL) + if (type == HAVE || type == REQUEST || type == PIECE || type == CANCEL || + type == SUGGEST || type == REJECT || type == ALLOWED_FAST) datalen += 4; // begin/offset is 4 bytes - if (type == REQUEST || type == PIECE || type == CANCEL) + if (type == REQUEST || type == PIECE || type == CANCEL || + type == REJECT) datalen += 4; // length is 4 bytes - if (type == REQUEST || type == CANCEL) + if (type == REQUEST || type == CANCEL || + type == REJECT) datalen += 4; // msg type is 1 byte @@ -131,15 +136,18 @@ class Message dos.writeByte(type & 0xFF); // Send additional info (piece number) - if (type == HAVE || type == REQUEST || type == PIECE || type == CANCEL) + if (type == HAVE || type == REQUEST || type == PIECE || type == CANCEL || + type == SUGGEST || type == REJECT || type == ALLOWED_FAST) dos.writeInt(piece); // Send additional info (begin/offset) - if (type == REQUEST || type == PIECE || type == CANCEL) + if (type == REQUEST || type == PIECE || type == CANCEL || + type == REJECT) dos.writeInt(begin); // Send additional info (length); for PIECE this is implicit. - if (type == REQUEST || type == CANCEL) + if (type == REQUEST || type == CANCEL || + type == REJECT) dos.writeInt(length); if (type == EXTENSION) @@ -173,21 +181,32 @@ class Message case UNINTERESTED: return "UNINTERESTED"; case HAVE: - return "HAVE(" + piece + ")"; + return "HAVE(" + piece + ')'; case BITFIELD: return "BITFIELD"; case REQUEST: - return "REQUEST(" + piece + "," + begin + "," + length + ")"; + return "REQUEST(" + piece + ',' + begin + ',' + length + ')'; case PIECE: - return "PIECE(" + piece + "," + begin + "," + length + ")"; + return "PIECE(" + piece + ',' + begin + ',' + length + ')'; case CANCEL: - return "CANCEL(" + piece + "," + begin + "," + length + ")"; + return "CANCEL(" + piece + ',' + begin + ',' + length + ')'; case PORT: - return "PORT(" + piece + ")"; + return "PORT(" + piece + ')'; case EXTENSION: return "EXTENSION(" + piece + ',' + data.length + ')'; + // fast extensions below here + case SUGGEST: + return "SUGGEST(" + piece + ')'; + case HAVE_ALL: + return "HAVE_ALL"; + case HAVE_NONE: + return "HAVE_NONE"; + case REJECT: + return "REJECT(" + piece + ',' + begin + ',' + length + ')'; + case ALLOWED_FAST: + return "ALLOWED_FAST(" + piece + ')'; default: - return ""; + return "UNKNOWN (" + type + ')'; } } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java b/apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java index 5fca72eb3..a40a68f8d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java +++ b/apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java @@ -74,10 +74,11 @@ public class MetaInfo * @param files null for single-file torrent * @param lengths null for single-file torrent * @param announce_list may be null + * @param created_by may be null */ MetaInfo(String announce, String name, String name_utf8, List> files, List lengths, int piece_length, byte[] piece_hashes, long length, boolean privateTorrent, - List> announce_list) + List> announce_list, String created_by) { this.announce = announce; this.name = name; @@ -91,8 +92,8 @@ public class MetaInfo this.privateTorrent = privateTorrent; this.announce_list = announce_list; this.comment = null; - this.created_by = null; - this.creation_date = 0; + this.created_by = created_by; + this.creation_date = I2PAppContext.getGlobalContext().clock().now(); // TODO if we add a parameter for other keys //if (other != null) { @@ -444,7 +445,7 @@ public class MetaInfo /** * The creation date (ms) or zero. - * Not available for locally-created torrents. + * As of 0.9.19, available for locally-created torrents. * @since 0.9.7 */ public long getCreationDate() { @@ -595,6 +596,14 @@ public class MetaInfo m.put("announce", announce); if (announce_list != null) m.put("announce-list", announce_list); + // misc. optional top-level stuff + if (comment != null) + m.put("comment", comment); + if (created_by != null) + m.put("created by", created_by); + if (creation_date != 0) + m.put("creation date", creation_date / 1000); + Map info = createInfoMap(); m.put("info", info); // don't save this locally, we should only do this once diff --git a/apps/i2psnark/java/src/org/klomp/snark/PartialPiece.java b/apps/i2psnark/java/src/org/klomp/snark/PartialPiece.java index bcf0aefd0..6cf35836d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PartialPiece.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PartialPiece.java @@ -108,7 +108,8 @@ class PartialPiece implements Comparable { /** * Convert this PartialPiece to a request for the next chunk. - * Used by PeerState only. + * Used by PeerState only. This depends on the downloaded value + * as set by setDownloaded() or read(). */ public Request getRequest() { @@ -128,14 +129,16 @@ class PartialPiece implements Comparable { } /** - * How many bytes are good - only valid by setDownloaded() + * How many bytes are good - as set by setDownloaded() or read() */ public int getDownloaded() { return this.off; } /** - * Call this before returning a PartialPiece to the PeerCoordinator + * Call this if necessary before returning a PartialPiece to the PeerCoordinator. + * We do not use a bitmap to track individual chunks received. + * Any chunks after a 'hole' will be lost. * @since 0.9.1 */ public void setDownloaded(int offset) { @@ -191,11 +194,20 @@ class PartialPiece implements Comparable { /** * Blocking. + * If offset matches the previous downloaded amount + * (as set by a previous call to read() or setDownlaoded()), + * the downloaded amount will be incremented by len. + * * @since 0.9.1 */ - public void read(DataInputStream din, int off, int len) throws IOException { + public void read(DataInputStream din, int offset, int len) throws IOException { if (bs != null) { - din.readFully(bs, off, len); + din.readFully(bs, offset, len); + synchronized (this) { + // only works for in-order chunks + if (this.off == offset) + this.off += len; + } } else { // read in fully before synching on raf ByteArray ba; @@ -211,8 +223,11 @@ class PartialPiece implements Comparable { synchronized (this) { if (raf == null) createTemp(); - raf.seek(off); + raf.seek(offset); raf.write(tmp); + // only works for in-order chunks + if (this.off == offset) + this.off += len; } if (ba != null) _cache.release(ba, false); diff --git a/apps/i2psnark/java/src/org/klomp/snark/Peer.java b/apps/i2psnark/java/src/org/klomp/snark/Peer.java index ab15bb85c..68258022e 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Peer.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Peer.java @@ -57,12 +57,12 @@ public class Peer implements Comparable private DataOutputStream dout; /** running counters */ - private long downloaded; - private long uploaded; + private final AtomicLong downloaded = new AtomicLong(); + private final AtomicLong uploaded = new AtomicLong(); // Keeps state for in/out connections. Non-null when the handshake // was successful, the connection setup and runs - PeerState state; + volatile PeerState state; /** shared across all peers on this torrent */ MagnetState magnetState; @@ -79,15 +79,15 @@ public class Peer implements Comparable private long uploaded_old[] = {-1,-1,-1}; private long downloaded_old[] = {-1,-1,-1}; - // bytes per bt spec: 0011223344556677 - static final long OPTION_EXTENSION = 0x0000000000100000l; - static final long OPTION_FAST = 0x0000000000000004l; - static final long OPTION_DHT = 0x0000000000000001l; + // bytes per bt spec: 0011223344556677 + private static final long OPTION_EXTENSION = 0x0000000000100000l; + private static final long OPTION_FAST = 0x0000000000000004l; + //private static final long OPTION_DHT = 0x0000000000000001l; /** we use a different bit since the compact format is different */ /* no, let's use an extension message static final long OPTION_I2P_DHT = 0x0000000040000000l; */ - static final long OPTION_AZMP = 0x1000000000000000l; + //private static final long OPTION_AZMP = 0x1000000000000000l; private long options; /** @@ -217,9 +217,11 @@ public class Peer implements Comparable * * If the given BitField is non-null it is send to the peer as first * message. + * + * @param uploadOnly if we are complete with skipped files, i.e. a partial seed */ - public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField bitfield, MagnetState mState) - { + public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField bitfield, + MagnetState mState, boolean uploadOnly) { if (state != null) throw new IllegalStateException("Peer already started"); @@ -275,17 +277,9 @@ public class Peer implements Comparable int metasize = metainfo != null ? metainfo.getInfoBytes().length : -1; boolean pexAndMetadata = metainfo == null || !metainfo.isPrivate(); boolean dht = util.getDHT() != null; - out.sendExtension(0, ExtensionHandler.getHandshake(metasize, pexAndMetadata, dht)); + out.sendExtension(0, ExtensionHandler.getHandshake(metasize, pexAndMetadata, dht, uploadOnly)); } - // Old DHT PORT message - //if ((options & OPTION_I2P_DHT) != 0 && util.getDHT() != null) { - // if (_log.shouldLog(Log.DEBUG)) - // _log.debug("Peer supports DHT, sending PORT message"); - // int port = util.getDHT().getPort(); - // out.sendPort(port); - //} - // Send our bitmap if (bitfield != null) s.out.sendBitfield(bitfield); @@ -297,7 +291,7 @@ public class Peer implements Comparable if (_log.shouldLog(Log.DEBUG)) _log.debug("Start running the reader with " + toString()); - // Use this thread for running the incomming connection. + // Use this thread for running the incoming connection. // The outgoing connection creates its own Thread. out.startup(); Thread.currentThread().setName("Snark reader from " + peerID); @@ -338,6 +332,9 @@ public class Peer implements Comparable dout.write("BitTorrent protocol".getBytes("UTF-8")); // Handshake write - options long myOptions = OPTION_EXTENSION; + // we can't handle HAVE_ALL or HAVE_NONE if we don't know the number of pieces + if (metainfo != null) + myOptions |= OPTION_FAST; // FIXME get util here somehow //if (util.getDHT() != null) // myOptions |= OPTION_I2P_DHT; @@ -385,15 +382,15 @@ public class Peer implements Comparable if (options != 0) { // send them something in runConnection() above if (_log.shouldLog(Log.DEBUG)) - _log.debug("Peer supports options 0x" + Long.toString(options, 16) + ": " + toString()); + _log.debug("Peer supports options 0x" + Long.toHexString(options) + ": " + toString()); } return bs; } - /** @since 0.8.4 */ - public long getOptions() { - return options; + /** @since 0.9.21 */ + public boolean supportsFast() { + return (options & OPTION_FAST) != 0; } /** @since 0.8.4 */ @@ -618,7 +615,7 @@ public class Peer implements Comparable * @since 0.8.4 */ public void downloaded(int size) { - downloaded += size; + downloaded.addAndGet(size); } /** @@ -626,7 +623,7 @@ public class Peer implements Comparable * @since 0.8.4 */ public void uploaded(int size) { - uploaded += size; + uploaded.addAndGet(size); } /** @@ -635,7 +632,7 @@ public class Peer implements Comparable */ public long getDownloaded() { - return downloaded; + return downloaded.get(); } /** @@ -644,7 +641,7 @@ public class Peer implements Comparable */ public long getUploaded() { - return uploaded; + return uploaded.get(); } /** @@ -652,8 +649,8 @@ public class Peer implements Comparable */ public void resetCounters() { - downloaded = 0; - uploaded = 0; + downloaded.set(0); + uploaded.set(0); } public long getInactiveTime() { diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java index b7759f901..c2abf6660 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java @@ -75,6 +75,8 @@ class PeerCheckerTask implements Runnable List removed = new ArrayList(); int uploadLimit = coordinator.allowedUploaders(); boolean overBWLimit = coordinator.overUpBWLimit(); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("peers: " + peerList.size() + " limit: " + uploadLimit + " overBW? " + overBWLimit); DHT dht = _util.getDHT(); for (Peer peer : peerList) { @@ -265,7 +267,23 @@ class PeerCheckerTask implements Runnable // close out unused files, but we don't need to do it every time Storage storage = coordinator.getStorage(); - if (storage != null && (_runCount % 4) == 0) { + if (storage != null) { + // The more files a torrent has, the more often we call the cleaner, + // to keep from running out of FDs + int files = storage.getFileCount(); + int skip; + if (files == 1) + skip = 6; + else if (files <= 4) + skip = 4; + else if (files <= 20) + skip = 3; + else if (files <= 50) + skip = 2; + else + skip = 1; + + if ((_runCount % skip) == 0) storage.cleanRAFs(); } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionIn.java b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionIn.java index 32ed0473c..da1b94333 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionIn.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionIn.java @@ -39,7 +39,7 @@ class PeerConnectionIn implements Runnable private static final int MAX_MSG_SIZE = Math.max(PeerState.PARTSIZE + 9, MagnetState.CHUNK_SIZE + 100); // 100 for the ext msg dictionary - private Thread thread; + private volatile Thread thread; private volatile boolean quit; long lastRcvd; @@ -75,9 +75,12 @@ class PeerConnectionIn implements Runnable thread = Thread.currentThread(); try { - PeerState ps = peer.state; - while (!quit && ps != null) + while (!quit) { + final PeerState ps = peer.state; + if (ps == null) + break; + // Common variables used for some messages. int piece; int begin; @@ -91,59 +94,64 @@ class PeerConnectionIn implements Runnable if (i == 0) { - ps.keepAliveMessage(); if (_log.shouldLog(Log.DEBUG)) _log.debug("Received keepalive from " + peer); + ps.keepAliveMessage(); continue; } byte b = din.readByte(); - Message m = new Message(); - m.type = b; switch (b) { - case 0: - ps.chokeMessage(true); + case Message.CHOKE: if (_log.shouldLog(Log.DEBUG)) _log.debug("Received choke from " + peer); + ps.chokeMessage(true); break; - case 1: - ps.chokeMessage(false); + + case Message.UNCHOKE: if (_log.shouldLog(Log.DEBUG)) _log.debug("Received unchoke from " + peer); + ps.chokeMessage(false); break; - case 2: - ps.interestedMessage(true); + + case Message.INTERESTED: if (_log.shouldLog(Log.DEBUG)) _log.debug("Received interested from " + peer); + ps.interestedMessage(true); break; - case 3: - ps.interestedMessage(false); + + case Message.UNINTERESTED: if (_log.shouldLog(Log.DEBUG)) _log.debug("Received not interested from " + peer); + ps.interestedMessage(false); break; - case 4: + + case Message.HAVE: piece = din.readInt(); - ps.haveMessage(piece); if (_log.shouldLog(Log.DEBUG)) _log.debug("Received havePiece(" + piece + ") from " + peer); + ps.haveMessage(piece); break; - case 5: + + case Message.BITFIELD: byte[] bitmap = new byte[i-1]; din.readFully(bitmap); - ps.bitfieldMessage(bitmap); if (_log.shouldLog(Log.DEBUG)) _log.debug("Received bitmap from " + peer + ": size=" + (i-1) /* + ": " + ps.bitfield */ ); + ps.bitfieldMessage(bitmap); break; - case 6: + + case Message.REQUEST: piece = din.readInt(); begin = din.readInt(); len = din.readInt(); - ps.requestMessage(piece, begin, len); if (_log.shouldLog(Log.DEBUG)) _log.debug("Received request(" + piece + "," + begin + ") from " + peer); + ps.requestMessage(piece, begin, len); break; - case 7: + + case Message.PIECE: piece = din.readInt(); begin = din.readInt(); len = i-9; @@ -151,9 +159,9 @@ class PeerConnectionIn implements Runnable if (req != null) { req.read(din); - ps.pieceMessage(req); if (_log.shouldLog(Log.DEBUG)) _log.debug("Received data(" + piece + "," + begin + ") from " + peer); + ps.pieceMessage(req); } else { @@ -165,21 +173,24 @@ class PeerConnectionIn implements Runnable _log.debug("Received UNWANTED data(" + piece + "," + begin + ") from " + peer); } break; - case 8: + + case Message.CANCEL: piece = din.readInt(); begin = din.readInt(); len = din.readInt(); - ps.cancelMessage(piece, begin, len); if (_log.shouldLog(Log.DEBUG)) _log.debug("Received cancel(" + piece + "," + begin + ") from " + peer); + ps.cancelMessage(piece, begin, len); break; - case 9: // PORT message + + case Message.PORT: int port = din.readUnsignedShort(); - ps.portMessage(port); if (_log.shouldLog(Log.DEBUG)) _log.debug("Received port message from " + peer); + ps.portMessage(port); break; - case 20: // Extension message + + case Message.EXTENSION: int id = din.readUnsignedByte(); byte[] payload = new byte[i-2]; din.readFully(payload); @@ -187,6 +198,43 @@ class PeerConnectionIn implements Runnable _log.debug("Received extension message from " + peer); ps.extensionMessage(id, payload); break; + + // fast extensions below here + case Message.SUGGEST: + piece = din.readInt(); + ps.suggestMessage(piece); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Received suggest(" + piece + ") from " + peer); + break; + + case Message.HAVE_ALL: + ps.haveMessage(true); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Received have_all from " + peer); + break; + + case Message.HAVE_NONE: + ps.haveMessage(false); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Received have_none from " + peer); + break; + + case Message.REJECT: + piece = din.readInt(); + begin = din.readInt(); + len = din.readInt(); + ps.rejectMessage(piece, begin, len); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Received reject(" + piece + ',' + begin + ',' + len + ") from " + peer); + break; + + case Message.ALLOWED_FAST: + piece = din.readInt(); + ps.allowedFastMessage(piece); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Received allowed_fast(" + piece + ") from " + peer); + break; + default: byte[] bs = new byte[i-1]; din.readFully(bs); @@ -202,11 +250,9 @@ class PeerConnectionIn implements Runnable if (_log.shouldLog(Log.INFO)) _log.info("IOError talking with " + peer, ioe); } - catch (Throwable t) + catch (RuntimeException t) { _log.error("Error talking with " + peer, t); - if (t instanceof OutOfMemoryError) - throw (OutOfMemoryError)t; } finally { diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java index c78ade3e8..314b534bc 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java @@ -22,15 +22,15 @@ package org.klomp.snark; import java.io.DataOutputStream; import java.io.IOException; -import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicLong; import net.i2p.I2PAppContext; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; -//import net.i2p.util.SimpleScheduler; //import net.i2p.util.SimpleTimer; class PeerConnectionOut implements Runnable @@ -43,7 +43,7 @@ class PeerConnectionOut implements Runnable private boolean quit; // Contains Messages. - private final List sendQueue = new ArrayList(); + private final BlockingQueue sendQueue = new LinkedBlockingQueue(); private static final AtomicLong __id = new AtomicLong(); private final long _id; @@ -125,6 +125,16 @@ class PeerConnectionOut implements Runnable if (state.choking) { it.remove(); //SimpleTimer.getInstance().removeEvent(nm.expireEvent); + if (peer.supportsFast()) { + Message r = new Message(); + r.type = Message.REJECT; + r.piece = nm.piece; + r.begin = nm.begin; + r.length = nm.length; + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Send " + peer + ": " + r); + r.sendMessage(dout); + } } nm = null; } @@ -142,8 +152,8 @@ class PeerConnectionOut implements Runnable it.remove(); } } - if (m == null && !sendQueue.isEmpty()) { - m = sendQueue.remove(0); + if (m == null) { + m = sendQueue.poll(); //SimpleTimer.getInstance().removeEvent(m.expireEvent); } } @@ -160,6 +170,8 @@ class PeerConnectionOut implements Runnable lastSent = System.currentTimeMillis(); // Remove all piece messages after sending a choke message. + // FiXME this causes REJECT messages to be sent before sending the CHOKE; + // BEP 6 recommends sending them after. if (m.type == Message.CHOKE) removeMessage(Message.PIECE); @@ -234,7 +246,7 @@ class PeerConnectionOut implements Runnable { synchronized(sendQueue) { - sendQueue.add(m); + sendQueue.offer(m); sendQueue.notifyAll(); } } @@ -278,11 +290,22 @@ class PeerConnectionOut implements Runnable while (it.hasNext()) { Message m = it.next(); - if (m.type == type) - { + if (m.type == type) { it.remove(); removed = true; - } + if (type == Message.PIECE && peer.supportsFast()) { + Message r = new Message(); + r.type = Message.REJECT; + r.piece = m.piece; + r.begin = m.begin; + r.length = m.length; + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Send " + peer + ": " + r); + try { + r.sendMessage(dout); + } catch (IOException ioe) {} + } + } } sendQueue.notifyAll(); } @@ -297,7 +320,7 @@ class PeerConnectionOut implements Runnable synchronized(sendQueue) { if(sendQueue.isEmpty()) - sendQueue.add(m); + sendQueue.offer(m); sendQueue.notifyAll(); } } @@ -350,12 +373,19 @@ class PeerConnectionOut implements Runnable void sendBitfield(BitField bitfield) { - Message m = new Message(); - m.type = Message.BITFIELD; - m.data = bitfield.getFieldBytes(); - m.off = 0; - m.len = m.data.length; - addMessage(m); + boolean fast = peer.supportsFast(); + if (fast && bitfield.complete()) { + sendHaveAll(); + } else if (fast && bitfield.count() <= 0) { + sendHaveNone(); + } else { + Message m = new Message(); + m.type = Message.BITFIELD; + m.data = bitfield.getFieldBytes(); + m.off = 0; + m.len = m.data.length; + addMessage(m); + } } /** reransmit requests not received in 7m */ @@ -480,7 +510,6 @@ class PeerConnectionOut implements Runnable m.len = length; // since we have the data already loaded, queue a timeout to remove it // no longer prefetched - //SimpleScheduler.getInstance().addEvent(new RemoveTooSlow(m), SEND_TIMEOUT); addMessage(m); } @@ -511,7 +540,8 @@ class PeerConnectionOut implements Runnable } /** - * Remove all Request messages from the queue + * Remove all Request messages from the queue. + * Does not send a cancel message. * @since 0.8.2 */ void cancelRequestMessages() { @@ -523,9 +553,12 @@ class PeerConnectionOut implements Runnable } } - // Called by the PeerState when the other side doesn't want this - // request to be handled anymore. Removes any pending Piece Message - // from out send queue. + /** + * Called by the PeerState when the other side doesn't want this + * request to be handled anymore. Removes any pending Piece Message + * from out send queue. + * Does not send a cancel message. + */ void cancelRequest(int piece, int begin, int length) { synchronized (sendQueue) @@ -561,4 +594,50 @@ class PeerConnectionOut implements Runnable m.piece = port; addMessage(m); } + + /** + * Unused + * @since 0.9.21 + */ + void sendSuggest(int piece) { + Message m = new Message(); + m.type = Message.SUGGEST; + m.piece = piece; + addMessage(m); + } + + /** @since 0.9.21 */ + private void sendHaveAll() { + Message m = new Message(); + m.type = Message.HAVE_ALL; + addMessage(m); + } + + /** @since 0.9.21 */ + private void sendHaveNone() { + Message m = new Message(); + m.type = Message.HAVE_NONE; + addMessage(m); + } + + /** @since 0.9.21 */ + void sendReject(int piece, int begin, int length) { + Message m = new Message(); + m.type = Message.REJECT; + m.piece = piece; + m.begin = begin; + m.length = length; + addMessage(m); + } + + /** + * Unused + * @since 0.9.21 + */ + void sendAllowedFast(int piece) { + Message m = new Message(); + m.type = Message.ALLOWED_FAST; + m.piece = piece; + addMessage(m); + } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java index c43651610..2542f8aa8 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java @@ -25,14 +25,15 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Queue; import java.util.Random; import java.util.Set; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.atomic.AtomicLong; import net.i2p.I2PAppContext; import net.i2p.data.ByteArray; @@ -52,7 +53,7 @@ import org.klomp.snark.dht.DHT; */ class PeerCoordinator implements PeerListener { - private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerCoordinator.class); + private final Log _log; /** * External use by PeerMonitorTask only. @@ -69,7 +70,7 @@ class PeerCoordinator implements PeerListener // package local for access by CheckDownLoadersTask final static long CHECK_PERIOD = 40*1000; // 40 seconds - final static int MAX_UPLOADERS = 6; + final static int MAX_UPLOADERS = 8; public static final long MAX_INACTIVE = 8*60*1000; /** @@ -87,8 +88,8 @@ class PeerCoordinator implements PeerListener // final static int MAX_DOWNLOADERS = MAX_CONNECTIONS; // int downloaders = 0; - private long uploaded; - private long downloaded; + private final AtomicLong uploaded = new AtomicLong(); + private final AtomicLong downloaded = new AtomicLong(); final static int RATE_DEPTH = 3; // make following arrays RATE_DEPTH long private final long uploaded_old[] = {-1,-1,-1}; private final long downloaded_old[] = {-1,-1,-1}; @@ -98,7 +99,7 @@ class PeerCoordinator implements PeerListener * This is a Queue, not a Set, because PeerCheckerTask keeps things in order for choking/unchoking. * External use by PeerMonitorTask only. */ - final Queue peers; + final Deque peers; /** * Peers we heard about via PEX @@ -144,6 +145,7 @@ class PeerCoordinator implements PeerListener { _util = util; _random = util.getContext().random(); + _log = util.getContext().logManager().getLog(PeerCoordinator.class); this.id = id; this.infohash = infohash; this.metainfo = metainfo; @@ -154,7 +156,7 @@ class PeerCoordinator implements PeerListener wantedPieces = new ArrayList(); setWantedPieces(); partialPieces = new ArrayList(getMaxConnections() + 1); - peers = new LinkedBlockingQueue(); + peers = new LinkedBlockingDeque(); magnetState = new MagnetState(infohash, metainfo); pexPeers = new ConcurrentHashSet(); @@ -278,7 +280,15 @@ class PeerCoordinator implements PeerListener */ public long getUploaded() { - return uploaded; + return uploaded.get(); + } + + /** + * Sets the initial total of uploaded bytes of all peers (from a saved status) + * @since 0.9.15 + */ + public void setUploaded(long up) { + uploaded.set(up); } /** @@ -286,7 +296,7 @@ class PeerCoordinator implements PeerListener */ public long getDownloaded() { - return downloaded; + return downloaded.get(); } /** @@ -312,16 +322,22 @@ class PeerCoordinator implements PeerListener */ public long getDownloadRate() { + if (halted) + return 0; return getRate(downloaded_old); } public long getUploadRate() { + if (halted) + return 0; return getRate(uploaded_old); } public long getCurrentUploadRate() { + if (halted) + return 0; // no need to synchronize, only one value long r = uploaded_old[0]; if (r <= 0) @@ -387,7 +403,7 @@ class PeerCoordinator implements PeerListener * Formerly used to * reduce max if huge pieces to keep from ooming when leeching * but now we don't - * @return usually 16 + * @return usually I2PSnarkUtil.MAX_CONNECTIONS */ private int getMaxConnections() { if (metainfo == null) @@ -514,7 +530,10 @@ class PeerCoordinator implements PeerListener // Can't add to beginning since we converted from a List to a Queue // We can do this in Java 6 with a Deque //peers.add(0, peer); - peers.add(peer); + if (_util.getContext().random().nextInt(4) == 0) + peers.push(peer); + else + peers.add(peer); peerCount = peers.size(); unchokePeer(); @@ -585,11 +604,13 @@ class PeerCoordinator implements PeerListener bitfield = storage.getBitField(); else bitfield = null; + // if we aren't a seed but we don't want any more + final boolean partialComplete = wantedBytes == 0 && bitfield != null && !bitfield.complete(); Runnable r = new Runnable() { public void run() { - peer.runConnection(_util, listener, bitfield, magnetState); + peer.runConnection(_util, listener, bitfield, magnetState, partialComplete); } }; String threadName = "Snark peer " + peer.toString(); @@ -901,6 +922,7 @@ class PeerCoordinator implements PeerListener * Returns a byte array containing the requested piece or null of * the piece is unknown. * + * @return bytes or null for errors such as not having the piece yet * @throws RuntimeException on IOE getting the data */ public ByteArray gotRequest(Peer peer, int piece, int off, int len) @@ -932,7 +954,7 @@ class PeerCoordinator implements PeerListener */ public void uploaded(Peer peer, int size) { - uploaded += size; + uploaded.addAndGet(size); //if (listener != null) // listener.peerChange(this, peer); @@ -943,7 +965,7 @@ class PeerCoordinator implements PeerListener */ public void downloaded(Peer peer, int size) { - downloaded += size; + downloaded.addAndGet(size); //if (listener != null) // listener.peerChange(this, peer); @@ -964,8 +986,9 @@ class PeerCoordinator implements PeerListener } int piece = pp.getPiece(); - synchronized(wantedPieces) - { + // try/catch outside the synch to avoid deadlock in the catch + try { + synchronized(wantedPieces) { Piece p = new Piece(piece); if (!wantedPieces.contains(p)) { @@ -981,8 +1004,7 @@ class PeerCoordinator implements PeerListener } } - try - { + // try/catch moved outside of synch // this takes forever if complete, as it rechecks if (storage.putPiece(pp)) { @@ -991,26 +1013,38 @@ class PeerCoordinator implements PeerListener } else { + // so we will try again + markUnrequested(peer, piece); + // just in case + removePartialPiece(piece); // Oops. We didn't actually download this then... :( - downloaded -= metainfo.getPieceLength(piece); - _log.warn("Got BAD piece " + piece + "/" + metainfo.getPieces() + " from " + peer + " for " + metainfo.getName()); + downloaded.addAndGet(0 - metainfo.getPieceLength(piece)); + // Mark this peer as not having the piece. PeerState will update its bitfield. + for (Piece pc : wantedPieces) { + if (pc.getId() == piece) { + pc.removePeer(peer); + break; + } + } + if (_log.shouldWarn()) + _log.warn("Got BAD piece " + piece + "/" + metainfo.getPieces() + " from " + peer + " for " + metainfo.getName()); return false; // No need to announce BAD piece to peers. } - } - catch (IOException ioe) - { + + wantedPieces.remove(p); + wantedBytes -= metainfo.getPieceLength(p.getId()); + } // synch + } catch (IOException ioe) { String msg = "Error writing storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe; _log.error(msg, ioe); if (listener != null) { listener.addMessage(msg); listener.addMessage("Fatal storage error: Stopping torrent " + metainfo.getName()); } + // deadlock was here snark.stopTorrent(); throw new RuntimeException(msg, ioe); - } - wantedPieces.remove(p); - wantedBytes -= metainfo.getPieceLength(p.getId()); - } + } // just in case removePartialPiece(piece); @@ -1122,8 +1156,9 @@ class PeerCoordinator implements PeerListener * * Also mark the piece unrequested if this peer was the only one. * - * @param peer partials, must include the zero-offset (empty) ones too - * No dup pieces, piece.setDownloaded() must be set + * @param peer partials, must include the zero-offset (empty) ones too. + * No dup pieces, piece.setDownloaded() must be set. + * len field in Requests is ignored. * @since 0.8.2 */ public void savePartialPieces(Peer peer, List partials) @@ -1202,22 +1237,23 @@ class PeerCoordinator implements PeerListener boolean skipped = false; for(Piece piece : wantedPieces) { if (piece.getId() == savedPiece) { - if (peer.isCompleted() && piece.getPeerCount() > 1) { + if (peer.isCompleted() && piece.getPeerCount() > 1 && + wantedPieces.size() > 2*END_GAME_THRESHOLD) { // Try to preserve rarest-first - // by not requesting a partial piece that non-seeders also have + // by not requesting a partial piece that at least two non-seeders also have // from a seeder - boolean nonSeeds = false; + int nonSeeds = 0; for (Peer pr : peers) { PeerState state = pr.state; if (state == null) continue; BitField bf = state.bitfield; if (bf == null) continue; if (bf.get(savedPiece) && !pr.isCompleted()) { - nonSeeds = true; - break; + if (++nonSeeds > 1) + break; } } - if (nonSeeds) { + if (nonSeeds > 1) { skipped = true; break; } @@ -1452,8 +1488,8 @@ class PeerCoordinator implements PeerListener public int allowedUploaders() { if (listener != null && listener.overUploadLimit(uploaders)) { - // if (_log.shouldLog(Log.DEBUG)) - // _log.debug("Over limit, uploaders was: " + uploaders); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Over limit, uploaders was: " + uploaders); return uploaders - 1; } else if (uploaders < MAX_UPLOADERS) return uploaders + 1; diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java index 35008394e..23cbe5690 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java @@ -21,6 +21,7 @@ package org.klomp.snark; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -155,15 +156,28 @@ class PeerState implements DataLoader setInteresting(true); } - void bitfieldMessage(byte[] bitmap) - { - synchronized(this) - { - if (_log.shouldLog(Log.DEBUG)) - _log.debug(peer + " rcv bitfield"); + void bitfieldMessage(byte[] bitmap) { + bitfieldMessage(bitmap, false); + } + + /** + * @param bitmap null to use the isAll param + * @param isAll only if bitmap == null: true for have_all, false for have_none + * @since 0.9.21 + */ + private void bitfieldMessage(byte[] bitmap, boolean isAll) { + if (_log.shouldLog(Log.DEBUG)) { + if (bitmap != null) + _log.debug(peer + " rcv bitfield bytes: " + bitmap.length); + else if (isAll) + _log.debug(peer + " rcv bitfield HAVE_ALL"); + else + _log.debug(peer + " rcv bitfield HAVE_NONE"); + } + synchronized(this) { if (bitfield != null) { - // XXX - Be liberal in what you except? + // XXX - Be liberal in what you accept? if (_log.shouldLog(Log.WARN)) _log.warn("Got unexpected bitfield message from " + peer); return; @@ -172,10 +186,24 @@ class PeerState implements DataLoader // XXX - Check for weird bitfield and disconnect? // FIXME will have to regenerate the bitfield after we know exactly // how many pieces there are, as we don't know how many spare bits there are. - if (metainfo == null) - bitfield = new BitField(bitmap, bitmap.length * 8); - else - bitfield = new BitField(bitmap, metainfo.getPieces()); + if (metainfo == null) { + if (bitmap != null) { + bitfield = new BitField(bitmap, bitmap.length * 8); + } else { + // we can't handle this situation + if (_log.shouldLog(Log.WARN)) + _log.warn("have_x w/o metainfo: " + isAll); + return; + } + } else { + if (bitmap != null) { + bitfield = new BitField(bitmap, metainfo.getPieces()); + } else { + bitfield = new BitField(metainfo.getPieces()); + if (isAll) + bitfield.setAll(); + } + } } if (metainfo == null) return; @@ -198,14 +226,21 @@ class PeerState implements DataLoader + piece + ", " + begin + ", " + length + ") "); if (metainfo == null) return; - if (choking) - { - if (_log.shouldLog(Log.INFO)) - _log.info("Request received, but choking " + peer); + if (choking) { + if (peer.supportsFast()) { + if (_log.shouldInfo()) + _log.info("Request received, sending reject to choked " + peer); + out.sendReject(piece, begin, length); + } else { + if (_log.shouldInfo()) + _log.info("Request received, but choking " + peer); + } return; - } + } // Sanity check + // There is no check here that we actually have the piece; + // this will be caught in loadData() below if (piece < 0 || piece >= metainfo.getPieces() || begin < 0 @@ -219,6 +254,8 @@ class PeerState implements DataLoader + ", " + begin + ", " + length + "' message from " + peer); + if (peer.supportsFast()) + out.sendReject(piece, begin, length); return; } @@ -227,8 +264,14 @@ class PeerState implements DataLoader // Todo: limit number of requests also? (robert 64 x 4KB) if (out.queuedBytes() + length > MAX_PIPELINE_BYTES) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Discarding request over pipeline limit from " + peer); + if (peer.supportsFast()) { + if (_log.shouldWarn()) + _log.warn("Rejecting request over pipeline limit from " + peer); + out.sendReject(piece, begin, length); + } else { + if (_log.shouldWarn()) + _log.warn("Discarding request over pipeline limit from " + peer); + } return; } @@ -243,7 +286,8 @@ class PeerState implements DataLoader /** * This is the callback that PeerConnectionOut calls * - * @return bytes or null for errors + * @return bytes or null for errors such as not having the piece yet + * @throws RuntimeException on IOE getting the data * @since 0.8.2 */ public ByteArray loadData(int piece, int begin, int length) { @@ -253,6 +297,8 @@ class PeerState implements DataLoader // XXX - Protocol error-> diconnect? if (_log.shouldLog(Log.WARN)) _log.warn("Got request for unknown piece: " + piece); + if (peer.supportsFast()) + out.sendReject(piece, begin, length); return null; } @@ -265,6 +311,8 @@ class PeerState implements DataLoader + ", " + begin + ", " + length + "' message from " + peer); + if (peer.supportsFast()) + out.sendReject(piece, begin, length); return null; } @@ -322,6 +370,11 @@ class PeerState implements DataLoader { if (_log.shouldLog(Log.WARN)) _log.warn("Got BAD " + req.getPiece() + " from " + peer); + synchronized(this) { + // so we don't ask again + if (bitfield != null) + bitfield.clear(req.getPiece()); + } } } @@ -455,7 +508,12 @@ class PeerState implements DataLoader for (Integer p : pcs) { Request req = getLowestOutstandingRequest(p.intValue()); if (req != null) { - req.getPartialPiece().setDownloaded(req.off); + PartialPiece pp = req.getPartialPiece(); + synchronized(pp) { + int dl = pp.getDownloaded(); + if (req.off != dl) + req = new Request(pp, dl, 1); + } rv.add(req); } } @@ -536,6 +594,89 @@ class PeerState implements DataLoader listener.gotPort(peer, port, port + 1); } + /////////// fast message handlers ///////// + + /** + * BEP 6 + * Treated as "have" for now + * @since 0.9.21 + */ + void suggestMessage(int piece) { + if (_log.shouldInfo()) + _log.info("Handling suggest as have(" + piece + ") from " + peer); + haveMessage(piece); + } + + /** + * BEP 6 + * @param isAll true for have_all, false for have_none + * @since 0.9.21 + */ + void haveMessage(boolean isAll) { + bitfieldMessage(null, isAll); + } + + /** + * BEP 6 + * If the peer rejects lower chunks but not higher ones, thus creating holes, + * we won't figure it out and the piece will fail, since we don't currently + * keep a chunk bitmap in PartialPiece. + * As long as the peer rejects all the chunks, or rejects only the last chunks, + * no holes are created and we will be fine. The reject messages may be in any order, + * just don't make a hole when it's over. + * + * @since 0.9.21 + */ + void rejectMessage(int piece, int begin, int length) { + if (_log.shouldInfo()) + _log.info("Got reject(" + piece + ',' + begin + ',' + length + ") from " + peer); + out.cancelRequest(piece, begin, length); + synchronized(this) { + Request deletedRequest = null; + // for this piece only + boolean haveMoreRequests = false; + for (Iterator iter = outstandingRequests.iterator(); iter.hasNext(); ) { + Request req = iter.next(); + if (req.getPiece() == piece) { + if (req.off == begin && req.len == length) { + iter.remove(); + deletedRequest = req; + } else { + haveMoreRequests = true; + } + } + } + if (deletedRequest != null && !haveMoreRequests) { + // We must return the piece to the coordinator + // Create a new fake request so we can set the offset correctly + PartialPiece pp = deletedRequest.getPartialPiece(); + int downloaded = pp.getDownloaded(); + Request req; + if (deletedRequest.off == downloaded) + req = deletedRequest; + else + req = new Request(pp, downloaded, 1); + List pcs = Collections.singletonList(req); + listener.savePartialPieces(this.peer, pcs); + if (_log.shouldWarn()) + _log.warn("Returned to coord. w/ offset " + pp.getDownloaded() + " due to reject(" + piece + ',' + begin + ',' + length + ") from " + peer); + } + if (lastRequest != null && lastRequest.getPiece() == piece && + lastRequest.off == begin && lastRequest.len == length) + lastRequest = null; + } + } + + /** + * BEP 6 + * Ignored for now + * @since 0.9.21 + */ + void allowedFastMessage(int piece) { + if (_log.shouldInfo()) + _log.info("Ignoring allowed_fast(" + piece + ") from " + peer); + } + void unknownMessage(int type, byte[] bs) { if (_log.shouldLog(Log.WARN)) @@ -543,6 +684,8 @@ class PeerState implements DataLoader + " length: " + bs.length); } + /////////// end message handlers ///////// + /** * We now have this piece. * Tell the peer and cancel any requests for the piece. diff --git a/apps/i2psnark/java/src/org/klomp/snark/Request.java b/apps/i2psnark/java/src/org/klomp/snark/Request.java index d6a621b1f..fddbb2b53 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Request.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Request.java @@ -43,13 +43,13 @@ class Request */ Request(PartialPiece piece, int off, int len) { - // Sanity check - if (off < 0 || len <= 0 || off + len > piece.getLength()) - throw new IndexOutOfBoundsException("Illegal Request " + toString()); - this.piece = piece; this.off = off; this.len = len; + + // Sanity check + if (off < 0 || len <= 0 || off + len > piece.getLength()) + throw new IndexOutOfBoundsException("Illegal Request " + toString()); } /** diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java index d57fc3c45..78e3b33e9 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java @@ -27,13 +27,13 @@ import java.io.InputStream; import java.util.Collections; import java.util.List; import java.util.Properties; -import java.util.Random; import java.util.StringTokenizer; import net.i2p.I2PAppContext; import net.i2p.client.streaming.I2PServerSocket; import net.i2p.data.Destination; import net.i2p.util.Log; +import net.i2p.util.SecureFile; /** * Main Snark program startup class. @@ -221,7 +221,7 @@ public class Snark private PeerCoordinator coordinator; private ConnectionAcceptor acceptor; private TrackerClient trackerclient; - private String rootDataDir = "."; + private final File rootDataDir; private final CompleteListener completeListener; private volatile boolean stopped; private volatile boolean starting; @@ -236,15 +236,27 @@ public class Snark private volatile boolean _autoStoppable; // String indicating main activity private volatile String activity = "Not started"; + private final long savedUploaded; - /** from main() via parseArguments() single torrent */ + /** + * from main() via parseArguments() single torrent + * + * @deprecated unused + */ +/**** Snark(I2PSnarkUtil util, String torrent, String ip, int user_port, StorageListener slistener, CoordinatorListener clistener) { this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, "."); } +****/ - /** single torrent - via router */ + /** + * single torrent - via router + * + * @deprecated unused + */ +/**** public Snark(I2PAppContext ctx, Properties opts, String torrent, StorageListener slistener, boolean start, String rootDir) { this(new I2PSnarkUtil(ctx), torrent, null, -1, slistener, null, null, null, null, false, rootDir); @@ -274,12 +286,32 @@ public class Snark if (start) this.startTorrent(); } +****/ - /** multitorrent */ + /** + * multitorrent + * @throws RuntimeException via fatal() + */ public Snark(I2PSnarkUtil util, String torrent, String ip, int user_port, StorageListener slistener, CoordinatorListener clistener, CompleteListener complistener, PeerCoordinatorSet peerCoordinatorSet, ConnectionAcceptor connectionAcceptor, boolean start, String rootDir) + { + this(util, torrent, ip, user_port, slistener, clistener, complistener, + peerCoordinatorSet, connectionAcceptor, start, rootDir, null); + } + + /** + * multitorrent + * + * @param baseFile if null, use rootDir/torrentName; if non-null, use it instead + * @throws RuntimeException via fatal() + * @since 0.9.11 + */ + public Snark(I2PSnarkUtil util, String torrent, String ip, int user_port, + StorageListener slistener, CoordinatorListener clistener, + CompleteListener complistener, PeerCoordinatorSet peerCoordinatorSet, + ConnectionAcceptor connectionAcceptor, boolean start, String rootDir, File baseFile) { if (slistener == null) slistener = this; @@ -291,7 +323,7 @@ public class Snark acceptor = connectionAcceptor; this.torrent = torrent; - this.rootDataDir = rootDir; + this.rootDataDir = new File(rootDir); stopped = true; activity = "Network setup"; @@ -394,13 +426,22 @@ public class Snark try { activity = "Checking storage"; - storage = new Storage(_util, meta, slistener); + boolean shouldPreserve = completeListener != null && completeListener.getSavedPreserveNamesSetting(this); + if (baseFile == null) { + String base = meta.getName(); + if (!shouldPreserve) + base = Storage.filterName(base); + if (_util.getFilesPublic()) + baseFile = new File(rootDataDir, base); + else + baseFile = new SecureFile(rootDataDir, base); + } + storage = new Storage(_util, baseFile, meta, slistener, shouldPreserve); if (completeListener != null) { - storage.check(rootDataDir, - completeListener.getSavedTorrentTime(this), + storage.check(completeListener.getSavedTorrentTime(this), completeListener.getSavedTorrentBitField(this)); } else { - storage.check(rootDataDir); + storage.check(); } // have to figure out when to reopen // if (!start) @@ -428,6 +469,7 @@ public class Snark trackerclient = new TrackerClient(meta, coordinator); */ + savedUploaded = (completeListener != null) ? completeListener.getSavedUploaded(this) : 0; if (start) startTorrent(); } @@ -438,6 +480,7 @@ public class Snark * @param torrent a fake name for now (not a file name) * @param ih 20-byte info hash * @param trackerURL may be null + * @throws RuntimeException via fatal() * @since 0.8.4 */ public Snark(I2PSnarkUtil util, String torrent, byte[] ih, String trackerURL, @@ -452,7 +495,8 @@ public class Snark this.torrent = torrent; this.infoHash = ih; this.additionalTrackerURL = trackerURL; - this.rootDataDir = rootDir; + this.rootDataDir = rootDir != null ? new File(rootDir) : null; // null only for FetchAndAdd extension + savedUploaded = 0; stopped = true; id = generateID(); @@ -477,24 +521,21 @@ public class Snark // Create a new ID and fill it with something random. First nine // zeros bytes, then three bytes filled with snark and then - // sixteen random bytes. + // eight random bytes. byte snark = (((3 + 7 + 10) * (1000 - 8)) / 992) - 17; byte[] rv = new byte[20]; - Random random = I2PAppContext.getGlobalContext().random(); - int i; - for (i = 0; i < 9; i++) - rv[i] = 0; - rv[i++] = snark; - rv[i++] = snark; - rv[i++] = snark; - while (i < 20) - rv[i++] = (byte)random.nextInt(256); + rv[9] = snark; + rv[10] = snark; + rv[11] = snark; + I2PAppContext.getGlobalContext().random().nextBytes(rv, 12, 8); return rv; } /** * Start up contacting peers and querying the tracker. * Blocks if tunnel is not yet open. + * + * @throws RuntimeException via fatal() */ public synchronized void startTorrent() { starting = true; @@ -521,6 +562,7 @@ public class Snark _log.info("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient"); activity = "Collecting pieces"; coordinator = new PeerCoordinator(_util, id, infoHash, meta, storage, this, this); + coordinator.setUploaded(savedUploaded); if (_peerCoordinatorSet != null) { // multitorrent _peerCoordinatorSet.add(coordinator); @@ -547,7 +589,7 @@ public class Snark } else if (trackerclient.halted()) { if (storage != null) { try { - storage.reopen(rootDataDir); + storage.reopen(); } catch (IOException ioe) { try { storage.close(); } catch (IOException ioee) { ioee.printStackTrace(); @@ -575,7 +617,6 @@ public class Snark * @since 0.9.1 */ public synchronized void stopTorrent(boolean fast) { - stopped = true; TrackerClient tc = trackerclient; if (tc != null) tc.halt(fast); @@ -583,17 +624,28 @@ public class Snark if (pc != null) pc.halt(); Storage st = storage; + if (!fast) + // HACK: Needed a way to distinguish between user-stop and + // shutdown-stop. stopTorrent(true) is in stopAllTorrents(). + // (#766) + stopped = true; if (st != null) { - boolean changed = storage.isChanged(); + // TODO: Cache the config-in-mem to compare vs config-on-disk + // (needed for auto-save to not double-save in some cases) + //boolean changed = storage.isChanged() || getUploaded() != savedUploaded; + boolean changed = true; + if (changed && completeListener != null) + completeListener.updateStatus(this); try { storage.close(); } catch (IOException ioe) { System.out.println("Error closing " + torrent); ioe.printStackTrace(); } - if (changed && completeListener != null) - completeListener.updateStatus(this); } + if (fast) + // HACK: See above if(!fast) + stopped = true; if (pc != null && _peerCoordinatorSet != null) _peerCoordinatorSet.remove(pc); if (_peerCoordinatorSet == null) @@ -693,6 +745,18 @@ public class Snark return storage != null && storage.isChecking(); } + /** + * If checking is in progress, return completion 0.0 ... 1.0, + * else return 1.0. + * @since 0.9.23 + */ + public double getCheckingProgress() { + if (storage != null && storage.isChecking()) + return storage.getCheckingProgress(); + else + return 1.0d; + } + /** * Disk allocation (ballooning) in progress. * @since 0.9.3 @@ -738,7 +802,7 @@ public class Snark PeerCoordinator coord = coordinator; if (coord != null) return coord.getUploaded(); - return 0; + return savedUploaded; } /** @@ -762,6 +826,7 @@ public class Snark } /** + * Not HTML escaped. * @return String returned from tracker, or null if no error * @since 0.8.4 */ @@ -834,7 +899,7 @@ public class Snark } /** - * Bytes still wanted. DOES account for skipped files. + * Bytes still wanted. DOES account for (i.e. does not include) skipped files. * FIXME -1 when not running. * @return exact value. or -1 if no storage yet or when not running. * @since 0.9.1 @@ -847,7 +912,31 @@ public class Snark } /** - * Does not account for skipped files. + * Bytes not received and set to skipped. + * This is not the same as the total of all skipped files, + * since pieces may span multiple files. + * + * @return exact value. or 0 if no storage yet. + * @since 0.9.24 + */ + public long getSkippedLength() { + PeerCoordinator coord = coordinator; + if (coord != null) { + // fast way + long r = getRemainingLength(); + if (r <= 0) + return 0; + long n = coord.getNeededLength(); + return r - n; + } else if (storage != null) { + // slow way + return storage.getSkippedLength(); + } + return 0; + } + + /** + * Does not account (i.e. includes) for skipped files. * @return number of pieces still needed (magnet mode or not), or -1 if unknown * @since 0.8.4 */ @@ -918,6 +1007,7 @@ public class Snark * non-valid argument list. The given listeners will be * passed to all components that take one. */ +/**** private static Snark parseArguments(String[] args, StorageListener slistener, CoordinatorListener clistener) @@ -932,6 +1022,7 @@ public class Snark int i = 0; while (i < args.length) { +****/ /* if (args[i].equals("--debug")) { @@ -953,7 +1044,9 @@ public class Snark catch (NumberFormatException nfe) { } } } - else */ if (args[i].equals("--port")) + else */ +/**** + if (args[i].equals("--port")) { if (args.length - 1 < i + 1) usage("--port needs port number to listen on"); @@ -1059,6 +1152,7 @@ public class Snark System.out.println (" \tor (with --share) a file to share."); } +****/ /** * Aborts program abnormally. @@ -1102,9 +1196,15 @@ public class Snark */ public void gotMetaInfo(PeerCoordinator coordinator, MetaInfo metainfo) { try { + String base = Storage.filterName(metainfo.getName()); + File baseFile; + if (_util.getFilesPublic()) + baseFile = new File(rootDataDir, base); + else + baseFile = new SecureFile(rootDataDir, base); // The following two may throw IOE... - storage = new Storage(_util, metainfo, this); - storage.check(rootDataDir); + storage = new Storage(_util, baseFile, metainfo, this, false); + storage.check(); // ... so don't set meta until here meta = metainfo; if (completeListener != null) { @@ -1200,7 +1300,8 @@ public class Snark public void setWantedPieces(Storage storage) { - coordinator.setWantedPieces(); + if (coordinator != null) + coordinator.setWantedPieces(); } ///////////// End StorageListener methods @@ -1209,7 +1310,7 @@ public class Snark /** SnarkSnutdown callback unused */ public void shutdown() { - // Should not be necessary since all non-deamon threads should + // Should not be necessary since all non-daemon threads should // have died. But in reality this does not always happen. //System.exit(0); } @@ -1228,7 +1329,7 @@ public class Snark * coordinatorListener */ final static int MIN_TOTAL_UPLOADERS = 4; - final static int MAX_TOTAL_UPLOADERS = 10; + final static int MAX_TOTAL_UPLOADERS = 20; public boolean overUploadLimit(int uploaders) { if (_peerCoordinatorSet == null || uploaders <= 0) @@ -1239,7 +1340,8 @@ public class Snark totalUploaders += c.uploaders; } int limit = _util.getMaxUploaders(); - // debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Total uploaders: " + totalUploaders + " Limit: " + limit); return totalUploaders > limit; } diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index ba6733bcc..aa463d94d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -8,6 +8,7 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -15,6 +16,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; @@ -26,6 +28,8 @@ import java.util.concurrent.LinkedBlockingQueue; import net.i2p.I2PAppContext; import net.i2p.app.ClientAppManager; +import net.i2p.crypto.SHA1Hash; +import net.i2p.crypto.SigType; import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.update.*; @@ -40,6 +44,7 @@ import net.i2p.util.SimpleTimer; import net.i2p.util.SimpleTimer2; import org.klomp.snark.dht.DHT; +import org.klomp.snark.dht.KRPC; /** * Manage multiple snarks @@ -55,7 +60,10 @@ public class SnarkManager implements CompleteListener { /** used to prevent DirMonitor from deleting torrents that don't have a torrent file yet */ private final Set _magnets; private final Object _addSnarkLock; - private /* FIXME final FIXME */ File _configFile; + private File _configFile; + private File _configDir; + /** one lock for all config, files for simplicity */ + private final Object _configLock = new Object(); private Properties _config; private final I2PAppContext _context; private final String _contextPath; @@ -81,14 +89,29 @@ public class SnarkManager implements CompleteListener { public static final String PROP_UPLOADERS_TOTAL = "i2psnark.uploaders.total"; public static final String PROP_UPBW_MAX = "i2psnark.upbw.max"; public static final String PROP_DIR = "i2psnark.dir"; - public static final String PROP_META_PREFIX = "i2psnark.zmeta."; - public static final String PROP_META_BITFIELD_SUFFIX = ".bitfield"; - public static final String PROP_META_PRIORITY_SUFFIX = ".priority"; - public static final String PROP_META_MAGNET_PREFIX = "i2psnark.magnet."; + private static final String PROP_META_PREFIX = "i2psnark.zmeta."; + private static final String PROP_META_RUNNING = "running"; + private static final String PROP_META_STAMP = "stamp"; + private static final String PROP_META_BASE = "base"; + private static final String PROP_META_BITFIELD = "bitfield"; + private static final String PROP_META_PRIORITY = "priority"; + private static final String PROP_META_PRESERVE_NAMES = "preserveFileNames"; + private static final String PROP_META_UPLOADED = "uploaded"; + private static final String PROP_META_ADDED = "added"; + private static final String PROP_META_COMPLETED = "completed"; + private static final String PROP_META_MAGNET = "magnet"; + private static final String PROP_META_MAGNET_DN = "magnet_dn"; + private static final String PROP_META_MAGNET_TR = "magnet_tr"; + private static final String PROP_META_MAGNET_DIR = "magnet_dir"; + //private static final String PROP_META_BITFIELD_SUFFIX = ".bitfield"; + //private static final String PROP_META_PRIORITY_SUFFIX = ".priority"; + private static final String PROP_META_MAGNET_PREFIX = "i2psnark.magnet."; private static final String CONFIG_FILE_SUFFIX = ".config"; + private static final String CONFIG_FILE = "i2psnark" + CONFIG_FILE_SUFFIX; public static final String PROP_FILES_PUBLIC = "i2psnark.filesPublic"; - public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops + public static final String PROP_OLD_AUTO_START = "i2snark.autoStart"; // oops + public static final String PROP_AUTO_START = "i2psnark.autoStart"; // convert in migration to new config file public static final String DEFAULT_AUTO_START = "false"; //public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix"; //public static final String DEFAULT_LINK_PREFIX = "file:///"; @@ -103,16 +126,24 @@ public class SnarkManager implements CompleteListener { public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers"; public static final String PROP_PRIVATETRACKERS = "i2psnark.privatetrackers"; private static final String PROP_USE_DHT = "i2psnark.enableDHT"; + private static final String PROP_SMART_SORT = "i2psnark.smartSort"; - public static final int MIN_UP_BW = 2; - public static final int DEFAULT_MAX_UP_BW = 10; + public static final int MIN_UP_BW = 10; + public static final int DEFAULT_MAX_UP_BW = 25; public static final int DEFAULT_STARTUP_DELAY = 3; public static final int DEFAULT_REFRESH_DELAY_SECS = 60; private static final int DEFAULT_PAGE_SIZE = 50; + public static final int DEFAULT_TUNNEL_QUANTITY = 3; + public static final String CONFIG_DIR_SUFFIX = ".d"; + private static final String SUBDIR_PREFIX = "s"; + private static final String B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"; /** * "name", "announceURL=websiteURL" pairs * '=' in announceURL must be escaped as , + * + * Please use host name, not b32 or full dest, in announce URL. Ensure in default hosts.txt. + * Please use host name, not b32 or full dest, in website URL. Ensure in default hosts.txt. */ private static final String DEFAULT_TRACKERS[] = { // "Postman", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php=http://tracker.postman.i2p/" @@ -125,18 +156,41 @@ public class SnarkManager implements CompleteListener { // , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/" // , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/" "Postman", "http://tracker2.postman.i2p/announce.php=http://tracker2.postman.i2p/" - ,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5" +// ,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5" ,"Diftracker", "http://diftracker.i2p/announce.php=http://diftracker.i2p/" // , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/" // ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/" + ,"DgTrack", "http://w7tpbzncbcocrqtwwm3nezhnnsw4ozadvi2hmvzdhrqzfxfum7wa.b32.i2p/a=http://opentracker.dg2.i2p/" + // The following is ECDSA_SHA256_P256 + ,"TheBland", "http://s5ikrdyjwbcgxmqetxb3nyheizftms7euacuub2hic7defkh3xhq.b32.i2p/a=http://tracker.thebland.i2p/stats?mode=peer" }; + /** URL. This is our equivalent to router.utorrent.com for bootstrap */ + public static final String DEFAULT_BACKUP_TRACKER = "http://opentracker.dg2.i2p/a"; + + /** URLs, comma-separated. Used for "announce to open trackers also" */ + private static final String DEFAULT_OPENTRACKERS = DEFAULT_BACKUP_TRACKER + + (SigType.ECDSA_SHA256_P256.isAvailable() ? ",http://tracker.thebland.i2p/a" : ""); + public static final Set DEFAULT_TRACKER_ANNOUNCES; + /** host names for config form */ + public static final Set KNOWN_OPENTRACKERS = new HashSet(Arrays.asList(new String[] { + "tracker.welterde.i2p", "cfmqlafjfmgkzbt4r3jsfyhgsr5abgxryl6fnz3d3y5a365di5aa.b32.i2p", + "opentracker.dg2.i2p", "w7tpbzncbcocrqtwwm3nezhnnsw4ozadvi2hmvzdhrqzfxfum7wa.b32.i2p", + "tracker.thebland.i2p", "s5ikrdyjwbcgxmqetxb3nyheizftms7euacuub2hic7defkh3xhq.b32.i2p", + "psi.i2p", "avviiexdngd32ccoy4kuckvc3mkf53ycvzbz6vz75vzhv4tbpk5a.b32.i2p", + "opentracker.psi.i2p", "vmow3h54yljn7zvzbqepdddt5fmygijujycod2q6yznpy2rrzuwa.b32.i2p", + "tracker.killyourtv.i2p", "5mpvzxfbd4rtped3c7ln4ddw52e7i7t56s36ztky4ustxtxrjdpa.b32.i2p", + "opendiftracker.i2p", "bikpeyxci4zuyy36eau5ycw665dplun4yxamn7vmsastejdqtfoq.b32.i2p" + })); + static { - Set ann = new HashSet(); + Set ann = new HashSet(8); for (int i = 1; i < DEFAULT_TRACKERS.length; i += 2) { - String urls[] = DEFAULT_TRACKERS[i].split("=", 2); + if (DEFAULT_TRACKERS[i-1].equals("TheBland") && !SigType.ECDSA_SHA256_P256.isAvailable()) + continue; + String urls[] = DataHelper.split(DEFAULT_TRACKERS[i], "=", 2); ann.add(urls[0]); } DEFAULT_TRACKER_ANNOUNCES = Collections.unmodifiableSet(ann); @@ -169,9 +223,11 @@ public class SnarkManager implements CompleteListener { _messages = new LinkedBlockingQueue(); _util = new I2PSnarkUtil(_context, ctxName); String cfile = ctxName + CONFIG_FILE_SUFFIX; - _configFile = new File(cfile); - if (!_configFile.isAbsolute()) - _configFile = new File(_context.getConfigDir(), cfile); + File configFile = new File(cfile); + if (!configFile.isAbsolute()) + configFile = new File(_context.getConfigDir(), cfile); + _configDir = migrateConfig(configFile); + _configFile = new File(_configDir, CONFIG_FILE); _trackerMap = new ConcurrentHashMap(4); loadConfig(null); } @@ -188,7 +244,7 @@ public class SnarkManager implements CompleteListener { // only if default instance if ("i2psnark".equals(_contextName)) // delay until UpdateManager is there - _context.simpleScheduler().addEvent(new Register(), 4*60*1000); + _context.simpleTimer2().addEvent(new Register(), 4*60*1000); // Not required, Jetty has a shutdown hook //_context.addShutdownTask(new SnarkManagerShutdown()); _idleChecker = new IdleChecker(this, _peerCoordinatorSet); @@ -241,7 +297,20 @@ public class SnarkManager implements CompleteListener { private static final int MAX_MESSAGES = 100; + /** + * Use if it does not include a link. + * Escapes '<' and '>' before queueing + */ public void addMessage(String message) { + addMessageNoEscape(message.replace("<", "<").replace(">", ">")); + } + + /** + * Use if it includes a link. + * Does not escape '<' and '>' before queueing + * @since 0.9.14.1 + */ + public void addMessageNoEscape(String message) { _messages.offer(message); while (_messages.size() > MAX_MESSAGES) { _messages.poll(); @@ -273,6 +342,17 @@ public class SnarkManager implements CompleteListener { public boolean shouldAutoStart() { return Boolean.parseBoolean(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START)); } + + /** + * @return default true + * @since 0.9.23 + */ + public boolean isSmartSortEnabled() { + String val = _config.getProperty(PROP_SMART_SORT); + if (val == null) + return true; + return Boolean.parseBoolean(val); + } /**** public String linkPrefix() { @@ -328,20 +408,200 @@ public class SnarkManager implements CompleteListener { return f; } + /** + * Migrate the old flat config file to the new config dir + * containing the config file minus the per-torrent entries, + * the dht file, and 64 subdirs for per-torrent config files + * Caller must synch. + * + * @return the new config directory, non-null + * @throws RuntimeException on creation fail + * @since 0.9.15 + */ + private File migrateConfig(File oldFile) { + File dir = new SecureDirectory(oldFile + CONFIG_DIR_SUFFIX); + if ((!dir.exists()) && (!dir.mkdirs())) { + _log.error("Error creating I2PSnark config dir " + dir); + throw new RuntimeException("Error creating I2PSnark config dir " + dir); + } + // move the DHT file as-is + String oldName = oldFile.toString(); + if (oldName.endsWith(CONFIG_FILE_SUFFIX)) { + String oldDHT = oldName.replace(CONFIG_FILE_SUFFIX, KRPC.DHT_FILE_SUFFIX); + File oldDHTFile = new File(oldDHT); + if (oldDHTFile.exists()) { + File newDHTFile = new File(dir, "i2psnark" + KRPC.DHT_FILE_SUFFIX); + FileUtil.rename(oldDHTFile, newDHTFile); + } + } + if (!oldFile.exists()) + return dir; + Properties oldProps = new Properties(); + try { + DataHelper.loadProps(oldProps, oldFile); + // a good time to fix this ancient typo + String auto = (String) oldProps.remove(PROP_OLD_AUTO_START); + if (auto != null) + oldProps.setProperty(PROP_AUTO_START, auto); + } catch (IOException ioe) { + _log.error("Error loading I2PSnark config " + oldFile, ioe); + return dir; + } + // Gather the props for each torrent, removing them from config + // old b64 of hash as key + Map configs = new HashMap(16); + for (Iterator> iter = oldProps.entrySet().iterator(); iter.hasNext(); ) { + Map.Entry e = iter.next(); + String k = (String) e.getKey(); + if (k.startsWith(PROP_META_PREFIX)) { + iter.remove(); + String v = (String) e.getValue(); + try { + k = k.substring(PROP_META_PREFIX.length()); + String h = k.substring(0, 28); // length of b64 of 160 bit infohash + k = k.substring(29); // skip '.' + Properties tprops = configs.get(h); + if (tprops == null) { + tprops = new OrderedProperties(); + configs.put(h, tprops); + } + if (k.equals(PROP_META_BITFIELD)) { + // old config was timestamp,bitfield; split them + int comma = v.indexOf(','); + if (comma > 0 && v.length() > comma + 1) { + tprops.put(PROP_META_STAMP, v.substring(0, comma)); + tprops.put(PROP_META_BITFIELD, v.substring(comma + 1)); + } else { + // timestamp only?? + tprops.put(PROP_META_STAMP, v); + } + } else { + tprops.put(k, v); + } + } catch (IndexOutOfBoundsException ioobe) { + continue; + } + } + } + // Now make a config file for each torrent + for (Map.Entry e : configs.entrySet()) { + String b64 = e.getKey(); + Properties props = e.getValue(); + if (props.isEmpty()) + continue; + b64 = b64.replace('$', '='); + byte[] ih = Base64.decode(b64); + if (ih == null || ih.length != 20) + continue; + File cfg = configFile(dir, ih); + if (!cfg.exists()) { + File subdir = cfg.getParentFile(); + if (!subdir.exists()) + subdir.mkdirs(); + try { + DataHelper.storeProps(props, cfg); + } catch (IOException ioe) { + _log.error("Error storing I2PSnark config " + cfg, ioe); + } + } + } + // now store in new location, minus the zmeta entries + File newFile = new File(dir, CONFIG_FILE); + Properties newProps = new OrderedProperties(); + newProps.putAll(oldProps); + try { + DataHelper.storeProps(newProps, newFile); + } catch (IOException ioe) { + _log.error("Error storing I2PSnark config " + newFile, ioe); + return dir; + } + oldFile.delete(); + if (_log.shouldLog(Log.WARN)) + _log.warn("Config migrated from " + oldFile + " to " + dir); + return dir; + } + + /** + * The config for a torrent + * @return non-null, possibly empty + * @since 0.9.15 + */ + private Properties getConfig(Snark snark) { + return getConfig(snark.getInfoHash()); + } + + /** + * The config for a torrent + * @param ih 20-byte infohash + * @return non-null, possibly empty + * @since 0.9.15 + */ + private Properties getConfig(byte[] ih) { + Properties rv = new OrderedProperties(); + File conf = configFile(_configDir, ih); + synchronized(_configLock) { // one lock for all + try { + DataHelper.loadProps(rv, conf); + } catch (IOException ioe) {} + } + return rv; + } + + /** + * The config file for a torrent + * @param confDir the config directory + * @param ih 20-byte infohash + * @since 0.9.15 + */ + private static File configFile(File confDir, byte[] ih) { + String hex = I2PSnarkUtil.toHex(ih); + File subdir = new SecureDirectory(confDir, SUBDIR_PREFIX + B64.charAt((ih[0] >> 2) & 0x3f)); + return new File(subdir, hex + CONFIG_FILE_SUFFIX); + } + + /** + * Extract the info hash from a config file name + * @return null for invalid name + * @since 0.9.20 + */ + private static SHA1Hash configFileToInfoHash(File file) { + String name = file.getName(); + if (name.length() != 40 + CONFIG_FILE_SUFFIX.length() || !name.endsWith(CONFIG_FILE_SUFFIX)) + return null; + String hex = name.substring(0, 40); + byte[] ih = new byte[20]; + try { + for (int i = 0; i < 20; i++) { + ih[i] = (byte) (Integer.parseInt(hex.substring(i*2, (i*2) + 2), 16) & 0xff); + } + } catch (NumberFormatException nfe) { + return null; + } + return new SHA1Hash(ih); + } + /** null to set initial defaults */ public void loadConfig(String filename) { + synchronized(_configLock) { + locked_loadConfig(filename); + } + } + + /** null to set initial defaults */ + private void locked_loadConfig(String filename) { if (_config == null) _config = new OrderedProperties(); if (filename != null) { File cfg = new File(filename); if (!cfg.isAbsolute()) cfg = new File(_context.getConfigDir(), filename); - _configFile = cfg; - if (cfg.exists()) { + _configDir = migrateConfig(cfg); + _configFile = new File(_configDir, CONFIG_FILE); + if (_configFile.exists()) { try { - DataHelper.loadProps(_config, cfg); + DataHelper.loadProps(_config, _configFile); } catch (IOException ioe) { - _log.error("Error loading I2PSnark config '" + filename + "'", ioe); + _log.error("Error loading I2PSnark config " + _configFile, ioe); } } } @@ -351,7 +611,9 @@ public class SnarkManager implements CompleteListener { if (!_config.containsKey(PROP_I2CP_PORT)) _config.setProperty(PROP_I2CP_PORT, "7654"); if (!_config.containsKey(PROP_I2CP_OPTS)) - _config.setProperty(PROP_I2CP_OPTS, "inbound.length=2 inbound.lengthVariance=0 outbound.length=2 outbound.lengthVariance=0 inbound.quantity=3 outbound.quantity=3"); + _config.setProperty(PROP_I2CP_OPTS, "inbound.length=3 outbound.length=3" + + " inbound.quantity=" + DEFAULT_TUNNEL_QUANTITY + + " outbound.quantity=" + DEFAULT_TUNNEL_QUANTITY); //if (!_config.containsKey(PROP_EEP_HOST)) // _config.setProperty(PROP_EEP_HOST, "127.0.0.1"); //if (!_config.containsKey(PROP_EEP_PORT)) @@ -375,6 +637,7 @@ public class SnarkManager implements CompleteListener { // _config.setProperty(PROP_USE_DHT, Boolean.toString(I2PSnarkUtil.DEFAULT_USE_DHT)); updateConfig(); } + /** * Get current theme. * @return String -- the current theme @@ -406,10 +669,10 @@ public class SnarkManager implements CompleteListener { /** * Get all themes - * @return String[] -- Array of all the themes found. + * @return String[] -- Array of all the themes found, non-null, unsorted */ public String[] getThemes() { - String[] themes = null; + String[] themes; // "docs/themes/snark/" File dir = new File(_context.getBaseDir(), "docs/themes/snark"); FileFilter fileFilter = new FileFilter() { public boolean accept(File file) { return file.isDirectory(); } }; @@ -420,6 +683,8 @@ public class SnarkManager implements CompleteListener { for(int i = 0; i < dirnames.length; i++) { themes[i] = dirnames[i].getName(); } + } else { + themes = new String[0]; } // return the map. return themes; @@ -461,9 +726,7 @@ public class SnarkManager implements CompleteListener { _util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW)); _util.setStartupDelay(getInt(PROP_STARTUP_DELAY, DEFAULT_STARTUP_DELAY)); _util.setFilesPublic(areFilesPublic()); - String ot = _config.getProperty(PROP_OPENTRACKERS); - if (ot != null) - _util.setOpenTrackers(getOpenTrackers()); + _util.setOpenTrackers(getListConfig(PROP_OPENTRACKERS, DEFAULT_OPENTRACKERS)); String useOT = _config.getProperty(PROP_USE_OPENTRACKERS); boolean bOT = useOT == null || Boolean.parseBoolean(useOT); _util.setUseOpenTrackers(bOT); @@ -488,7 +751,19 @@ public class SnarkManager implements CompleteListener { /** * all params may be null or need trimming */ - public void updateConfig(String dataDir, boolean filesPublic, boolean autoStart, String refreshDelay, + public void updateConfig(String dataDir, boolean filesPublic, boolean autoStart, boolean smartSort, String refreshDelay, + String startDelay, String pageSize, String seedPct, String eepHost, + String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts, + String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme) { + synchronized(_configLock) { + locked_updateConfig(dataDir, filesPublic, autoStart, smartSort,refreshDelay, + startDelay, pageSize, seedPct, eepHost, + eepPort, i2cpHost, i2cpPort, i2cpOpts, + upLimit, upBW, useOpenTrackers, useDHT, theme); + } + } + + private void locked_updateConfig(String dataDir, boolean filesPublic, boolean autoStart, boolean smartSort, String refreshDelay, String startDelay, String pageSize, String seedPct, String eepHost, String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts, String upLimit, String upBW, boolean useOpenTrackers, boolean useDHT, String theme) { @@ -516,9 +791,9 @@ public class SnarkManager implements CompleteListener { _util.setMaxUploaders(limit); changed = true; _config.setProperty(PROP_UPLOADERS_TOTAL, Integer.toString(limit)); - addMessage(_("Total uploaders limit changed to {0}", limit)); + addMessage(_t("Total uploaders limit changed to {0}", limit)); } else { - addMessage(_("Minimum total uploaders limit is {0}", Snark.MIN_TOTAL_UPLOADERS)); + addMessage(_t("Minimum total uploaders limit is {0}", Snark.MIN_TOTAL_UPLOADERS)); } } } @@ -530,9 +805,9 @@ public class SnarkManager implements CompleteListener { _util.setMaxUpBW(limit); changed = true; _config.setProperty(PROP_UPBW_MAX, Integer.toString(limit)); - addMessage(_("Up BW limit changed to {0}KBps", limit)); + addMessage(_t("Up BW limit changed to {0}KBps", limit)); } else { - addMessage(_("Minimum up bandwidth limit is {0}KBps", MIN_UP_BW)); + addMessage(_t("Minimum up bandwidth limit is {0}KBps", MIN_UP_BW)); } } } @@ -544,7 +819,7 @@ public class SnarkManager implements CompleteListener { _util.setStartupDelay(minutes); changed = true; _config.setProperty(PROP_STARTUP_DELAY, Integer.toString(minutes)); - addMessage(_("Startup delay changed to {0}", DataHelper.formatDuration2(minutes * (60L * 1000)))); + addMessage(_t("Startup delay changed to {0}", DataHelper.formatDuration2(minutes * (60L * 1000)))); } } @@ -555,9 +830,9 @@ public class SnarkManager implements CompleteListener { changed = true; _config.setProperty(PROP_REFRESH_DELAY, Integer.toString(secs)); if (secs >= 0) - addMessage(_("Refresh time changed to {0}", DataHelper.formatDuration2(secs * 1000))); + addMessage(_t("Refresh time changed to {0}", DataHelper.formatDuration2(secs * 1000))); else - addMessage(_("Refresh disabled")); + addMessage(_t("Refresh disabled")); } } catch (NumberFormatException nfe) {} } @@ -573,27 +848,27 @@ public class SnarkManager implements CompleteListener { changed = true; pageSize = Integer.toString(size); _config.setProperty(PROP_PAGE_SIZE, pageSize); - addMessage(_("Page size changed to {0}", pageSize)); + addMessage(_t("Page size changed to {0}", pageSize)); } } catch (NumberFormatException nfe) {} } if (dataDir != null && !dataDir.equals(getDataDir().getAbsolutePath())) { - dataDir = dataDir.trim(); + dataDir = DataHelper.stripHTML(dataDir.trim()); File dd = new File(dataDir); if (!dd.isAbsolute()) { - addMessage(_("Data directory must be an absolute path") + ": " + dataDir); + addMessage(_t("Data directory must be an absolute path") + ": " + dataDir); } else if (!dd.exists()) { - addMessage(_("Data directory does not exist") + ": " + dataDir); + addMessage(_t("Data directory does not exist") + ": " + dataDir); } else if (!dd.isDirectory()) { - addMessage(_("Not a directory") + ": " + dataDir); + addMessage(_t("Not a directory") + ": " + dataDir); } else if (!dd.canRead()) { - addMessage(_("Unreadable") + ": " + dataDir); + addMessage(_t("Unreadable") + ": " + dataDir); } else { changed = true; interruptMonitor = true; _config.setProperty(PROP_DIR, dataDir); - addMessage(_("Data directory changed to {0}", dataDir)); + addMessage(_t("Data directory changed to {0}", dataDir)); } } @@ -609,7 +884,7 @@ public class SnarkManager implements CompleteListener { } Map opts = new HashMap(); - if (i2cpOpts == null) i2cpOpts = ""; + i2cpOpts = DataHelper.stripHTML(i2cpOpts); StringTokenizer tok = new StringTokenizer(i2cpOpts, " \t\n"); while (tok.hasMoreTokens()) { String pair = tok.nextToken(); @@ -648,37 +923,37 @@ public class SnarkManager implements CompleteListener { p.putAll(opts); _util.setI2CPConfig(i2cpHost, port, p); _util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW)); - addMessage(_("I2CP and tunnel changes will take effect after stopping all torrents")); + addMessage(_t("I2CP and tunnel changes will take effect after stopping all torrents")); } else if (!reconnect) { // The usual case, the other two are if not in router context _config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim()); - addMessage(_("I2CP options changed to {0}", i2cpOpts)); + addMessage(_t("I2CP options changed to {0}", i2cpOpts)); _util.setI2CPConfig(oldI2CPHost, oldI2CPPort, opts); } else { // Won't happen, I2CP host/port, are hidden in the GUI if in router context if (_util.connected()) { _util.disconnect(); - addMessage(_("Disconnecting old I2CP destination")); + addMessage(_t("Disconnecting old I2CP destination")); } - addMessage(_("I2CP settings changed to {0}", i2cpHost + ':' + port + ' ' + i2cpOpts)); + addMessage(_t("I2CP settings changed to {0}", i2cpHost + ':' + port + ' ' + i2cpOpts)); _util.setI2CPConfig(i2cpHost, port, opts); _util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW)); boolean ok = _util.connect(); if (!ok) { - addMessage(_("Unable to connect with the new settings, reverting to the old I2CP settings")); + addMessage(_t("Unable to connect with the new settings, reverting to the old I2CP settings")); _util.setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts); ok = _util.connect(); if (!ok) - addMessage(_("Unable to reconnect with the old settings!")); + addMessage(_t("Unable to reconnect with the old settings!")); } else { - addMessage(_("Reconnected on the new I2CP destination")); + addMessage(_t("Reconnected on the new I2CP destination")); _config.setProperty(PROP_I2CP_HOST, i2cpHost.trim()); _config.setProperty(PROP_I2CP_PORT, "" + port); _config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim()); // no PeerAcceptors/I2PServerSockets to deal with, since all snarks are inactive for (Snark snark : _snarks.values()) { if (snark.restartAcceptor()) { - addMessage(_("I2CP listener restarted for \"{0}\"", snark.getBaseName())); + addMessage(_t("I2CP listener restarted for \"{0}\"", snark.getBaseName())); // this is the common ConnectionAcceptor, so we only need to do it once break; } @@ -692,44 +967,54 @@ public class SnarkManager implements CompleteListener { _config.setProperty(PROP_FILES_PUBLIC, Boolean.toString(filesPublic)); _util.setFilesPublic(filesPublic); if (filesPublic) - addMessage(_("New files will be publicly readable")); + addMessage(_t("New files will be publicly readable")); else - addMessage(_("New files will not be publicly readable")); + addMessage(_t("New files will not be publicly readable")); changed = true; } if (shouldAutoStart() != autoStart) { _config.setProperty(PROP_AUTO_START, Boolean.toString(autoStart)); if (autoStart) - addMessage(_("Enabled autostart")); + addMessage(_t("Enabled autostart")); else - addMessage(_("Disabled autostart")); + addMessage(_t("Disabled autostart")); changed = true; } + + if (isSmartSortEnabled() != smartSort) { + _config.setProperty(PROP_SMART_SORT, Boolean.toString(smartSort)); + if (smartSort) + addMessage(_t("Enabled smart sort")); + else + addMessage(_t("Disabled smart sort")); + changed = true; + } + if (_util.shouldUseOpenTrackers() != useOpenTrackers) { _config.setProperty(PROP_USE_OPENTRACKERS, useOpenTrackers + ""); if (useOpenTrackers) - addMessage(_("Enabled open trackers - torrent restart required to take effect.")); + addMessage(_t("Enabled open trackers - torrent restart required to take effect.")); else - addMessage(_("Disabled open trackers - torrent restart required to take effect.")); + addMessage(_t("Disabled open trackers - torrent restart required to take effect.")); _util.setUseOpenTrackers(useOpenTrackers); changed = true; } if (_util.shouldUseDHT() != useDHT) { _config.setProperty(PROP_USE_DHT, Boolean.toString(useDHT)); if (useDHT) - addMessage(_("Enabled DHT.")); + addMessage(_t("Enabled DHT.")); else - addMessage(_("Disabled DHT.")); + addMessage(_t("Disabled DHT.")); if (_util.connected()) - addMessage(_("DHT change requires tunnel shutdown and reopen")); + addMessage(_t("DHT change requires tunnel shutdown and reopen")); _util.setUseDHT(useDHT); changed = true; } if (theme != null) { if(!theme.equals(_config.getProperty(PROP_THEME))) { _config.setProperty(PROP_THEME, theme); - addMessage(_("{0} theme loaded, return to main i2psnark page to view.", theme)); + addMessage(_t("{0} theme loaded, return to main i2psnark page to view.", theme)); changed = true; } } @@ -739,7 +1024,7 @@ public class SnarkManager implements CompleteListener { // Data dir changed. this will stop and remove all old torrents, and add the new ones _monitor.interrupt(); } else { - addMessage(_("Configuration unchanged.")); + addMessage(_t("Configuration unchanged.")); } } @@ -751,7 +1036,7 @@ public class SnarkManager implements CompleteListener { private List getOpenTrackers() { if (!_util.shouldUseOpenTrackers()) return Collections.emptyList(); - return getListConfig(PROP_OPENTRACKERS, I2PSnarkUtil.DEFAULT_OPENTRACKERS); + return getListConfig(PROP_OPENTRACKERS, DEFAULT_OPENTRACKERS); } /** @@ -769,9 +1054,9 @@ public class SnarkManager implements CompleteListener { public void saveOpenTrackers(List ot) { setListConfig(PROP_OPENTRACKERS, ot); if (ot == null) - ot = Collections.singletonList(I2PSnarkUtil.DEFAULT_OPENTRACKERS); + ot = getListConfig(PROP_OPENTRACKERS, DEFAULT_OPENTRACKERS); _util.setOpenTrackers(ot); - addMessage(_("Open Tracker list changed - torrent restart required to take effect.")); + addMessage(_t("Open Tracker list changed - torrent restart required to take effect.")); saveConfig(); } @@ -781,7 +1066,7 @@ public class SnarkManager implements CompleteListener { */ public void savePrivateTrackers(List pt) { setListConfig(PROP_PRIVATETRACKERS, pt); - addMessage(_("Private tracker list changed - affects newly created torrents only.")); + addMessage(_t("Private tracker list changed - affects newly created torrents only.")); saveConfig(); } @@ -796,7 +1081,7 @@ public class SnarkManager implements CompleteListener { val = dflt; if (val == null) return Collections.emptyList(); - return Arrays.asList(val.split(",")); + return Arrays.asList(DataHelper.split(val, ",")); } /** @@ -823,23 +1108,16 @@ public class SnarkManager implements CompleteListener { public void saveConfig() { try { - synchronized (_configFile) { + synchronized (_configLock) { DataHelper.storeProps(_config, _configFile); } } catch (IOException ioe) { - addMessage(_("Unable to save the config to {0}", _configFile.getAbsolutePath())); + addMessage(_t("Unable to save the config to {0}", _configFile.getAbsolutePath())); } } - public Properties getConfig() { return _config; } - - /** @since Jetty 7 */ - public String getConfigFilename() { - return _configFile.getAbsolutePath(); - } - /** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */ - public static final int MAX_FILES_PER_TORRENT = 512; + public static final int MAX_FILES_PER_TORRENT = 999; /** * Set of canonical .torrent filenames that we are dealing with. @@ -895,20 +1173,30 @@ public class SnarkManager implements CompleteListener { /** * Caller must verify this torrent is not already added. + * + * @param filename the absolute path to save the metainfo to, generally ending in ".torrent" + * @param baseFile may be null, if so look in dataDir * @throws RuntimeException via Snark.fatal() */ - private void addTorrent(String filename) { addTorrent(filename, false); } + private void addTorrent(String filename, File baseFile, boolean dontAutoStart) { + addTorrent(filename, baseFile, dontAutoStart, null); + } /** * Caller must verify this torrent is not already added. + * + * @param filename the absolute path to save the metainfo to, generally ending in ".torrent" + * @param baseFile may be null, if so look in dataDir + * @param dataDir must exist, or null to default to snark data directory * @throws RuntimeException via Snark.fatal() + * @since 0.9.17 */ - private void addTorrent(String filename, boolean dontAutoStart) { + private void addTorrent(String filename, File baseFile, boolean dontAutoStart, File dataDir) { if ((!dontAutoStart) && !_util.connected()) { - addMessage(_("Connecting to I2P")); + addMessage(_t("Connecting to I2P")); boolean ok = _util.connect(); if (!ok) { - addMessage(_("Error connecting to I2P - check your I2CP settings!")); + addMessage(_t("Error connecting to I2P - check your I2CP settings!")); return; } } @@ -917,10 +1205,11 @@ public class SnarkManager implements CompleteListener { filename = sfile.getCanonicalPath(); } catch (IOException ioe) { _log.error("Unable to add the torrent " + filename, ioe); - addMessage(_("Error: Could not add the torrent {0}", filename) + ": " + ioe); + addMessage(_t("Error: Could not add the torrent {0}", filename) + ": " + ioe); return; } - File dataDir = getDataDir(); + if (dataDir == null) + dataDir = getDataDir(); Snark torrent = null; synchronized (_snarks) { torrent = _snarks.get(filename); @@ -939,7 +1228,7 @@ public class SnarkManager implements CompleteListener { fis = new FileInputStream(sfile); } catch (IOException ioe) { // catch this here so we don't try do delete it below - addMessage(_("Cannot open \"{0}\"", sfile.getName()) + ": " + ioe.getMessage()); + addMessage(_t("Cannot open \"{0}\"", sfile.getName()) + ": " + ioe.getMessage()); return; } @@ -958,49 +1247,59 @@ public class SnarkManager implements CompleteListener { Snark snark = getTorrentByInfoHash(info.getInfoHash()); if (snark != null) { // TODO - if the existing one is a magnet, delete it and add the metainfo instead? - addMessage(_("Torrent with this info hash is already running: {0}", snark.getBaseName())); + addMessage(_t("Torrent with this info hash is already running: {0}", snark.getBaseName())); return; } if (!TrackerClient.isValidAnnounce(info.getAnnounce())) { if (info.isPrivate()) { - addMessage(_("ERROR - No I2P trackers in private torrent \"{0}\"", info.getName())); + addMessage(_t("ERROR - No I2P trackers in private torrent \"{0}\"", info.getName())); } else if (!_util.getOpenTrackers().isEmpty()) { - addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName())); - //addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName())); + addMessage(_t("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName())); + //addMessage(_t("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName())); } else if (_util.shouldUseDHT()) { - addMessage(_("Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will announce to DHT only.", info.getName())); + addMessage(_t("Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will announce to DHT only.", info.getName())); } else { - addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName())); - //addMessage(_("Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is enabled before starting this torrent.", info.getName())); + addMessage(_t("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName())); + //addMessage(_t("Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is enabled before starting this torrent.", info.getName())); dontAutoStart = true; } } String rejectMessage = validateTorrent(info); if (rejectMessage != null) { - sfile.delete(); - addMessage(rejectMessage); - return; - } else { - // TODO load saved closest DHT nodes and pass to the Snark ? - // This may take a LONG time - torrent = new Snark(_util, filename, null, -1, null, null, this, - _peerCoordinatorSet, _connectionAcceptor, - false, dataDir.getPath()); - loadSavedFilePriorities(torrent); - synchronized (_snarks) { - _snarks.put(filename, torrent); - } + throw new IOException(rejectMessage); + } + + // TODO load saved closest DHT nodes and pass to the Snark ? + // This may take a LONG time + if (baseFile == null) + baseFile = getSavedBaseFile(info.getInfoHash()); + if (_log.shouldLog(Log.INFO)) + _log.info("New Snark, torrent: " + filename + " base: " + baseFile); + torrent = new Snark(_util, filename, null, -1, null, null, this, + _peerCoordinatorSet, _connectionAcceptor, + shouldAutoStart(), dataDir.getPath(), baseFile); + loadSavedFilePriorities(torrent); + synchronized (_snarks) { + _snarks.put(filename, torrent); } } catch (IOException ioe) { - String err = _("Torrent in \"{0}\" is invalid", sfile.getName()) + ": " + ioe.getMessage(); + // close before rename/delete for windows + if (fis != null) try { fis.close(); fis = null; } catch (IOException ioe2) {} + String err = _t("Torrent in \"{0}\" is invalid", sfile.toString()) + ": " + ioe.getMessage(); addMessage(err); _log.error(err, ioe); - if (sfile.exists()) - sfile.delete(); + File rename = new File(filename + ".BAD"); + if (rename.exists()) { + if (sfile.delete()) + addMessage(_t("Torrent file deleted: {0}", sfile.toString())); + } else { + if (FileUtil.rename(sfile, rename)) + addMessage(_t("Torrent file moved from {0} to {1}", sfile.toString(), rename.toString())); + } return; } catch (OutOfMemoryError oom) { - addMessage(_("ERROR - Out of memory, cannot create torrent from {0}", sfile.getName()) + ": " + oom.getMessage()); + addMessage(_t("ERROR - Out of memory, cannot create torrent from {0}", sfile.getName()) + ": " + oom.getMessage()); return; } finally { if (fis != null) try { fis.close(); } catch (IOException ioe) {} @@ -1010,11 +1309,21 @@ public class SnarkManager implements CompleteListener { return; } // ok, snark created, now lets start it up or configure it further - if (!dontAutoStart && shouldAutoStart()) { - torrent.startTorrent(); - addMessage(_("Torrent added and started: \"{0}\"", torrent.getBaseName())); + Properties config = getConfig(torrent); + boolean running; + String prop = config.getProperty(PROP_META_RUNNING); + if(prop == null || Boolean.parseBoolean(prop)) { + running = true; } else { - addMessage(_("Torrent added: \"{0}\"", torrent.getBaseName())); + running = false; + } + // Were we running last time? + String link = linkify(torrent); + if (!dontAutoStart && shouldAutoStart() && running) { + torrent.startTorrent(); + addMessageNoEscape(_t("Torrent added and started: {0}", link)); + } else { + addMessageNoEscape(_t("Torrent added: {0}", link)); } } @@ -1032,7 +1341,25 @@ public class SnarkManager implements CompleteListener { */ public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus) { // updateStatus is true from UI, false from config file bulk add - addMagnet(name, ih, trackerURL, updateStatus, updateStatus, this); + addMagnet(name, ih, trackerURL, updateStatus, updateStatus, null, this); + } + + /** + * Add a torrent with the info hash alone (magnet / maggot) + * + * @param name hex or b32 name from the magnet link + * @param ih 20 byte info hash + * @param trackerURL may be null + * @param updateStatus should we add this magnet to the config file, + * to save it across restarts, in case we don't get + * the metadata before shutdown? + * @param dataDir must exist, or null to default to snark data directory + * @throws RuntimeException via Snark.fatal() + * @since 0.9.17 + */ + public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus, File dataDir) { + // updateStatus is true from UI, false from config file bulk add + addMagnet(name, ih, trackerURL, updateStatus, updateStatus, dataDir, this); } /** @@ -1045,42 +1372,44 @@ public class SnarkManager implements CompleteListener { * @param updateStatus should we add this magnet to the config file, * to save it across restarts, in case we don't get * the metadata before shutdown? + * @param dataDir must exist, or null to default to snark data directory * @param listener to intercept callbacks, should pass through to this * @return the new Snark or null on failure * @throws RuntimeException via Snark.fatal() * @since 0.9.4 */ public Snark addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus, - boolean autoStart, CompleteListener listener) { + boolean autoStart, File dataDir, CompleteListener listener) { + String dirPath = dataDir != null ? dataDir.getAbsolutePath() : getDataDir().getPath(); Snark torrent = new Snark(_util, name, ih, trackerURL, listener, _peerCoordinatorSet, _connectionAcceptor, - false, getDataDir().getPath()); + false, dirPath); synchronized (_snarks) { Snark snark = getTorrentByInfoHash(ih); if (snark != null) { - addMessage(_("Torrent with this info hash is already running: {0}", snark.getBaseName())); + addMessage(_t("Torrent with this info hash is already running: {0}", snark.getBaseName())); return null; } // Tell the dir monitor not to delete us _magnets.add(name); if (updateStatus) - saveMagnetStatus(ih); + saveMagnetStatus(ih, dirPath, trackerURL, name); _snarks.put(name, torrent); } if (autoStart) { startTorrent(ih); - addMessage(_("Fetching {0}", name)); + addMessage(_t("Fetching {0}", name)); DHT dht = _util.getDHT(); boolean shouldWarn = _util.connected() && _util.getOpenTrackers().isEmpty() && ((!_util.shouldUseDHT()) || dht == null || dht.size() <= 0); if (shouldWarn) { - addMessage(_("Open trackers are disabled and we have no DHT peers. " + + addMessage(_t("Open trackers are disabled and we have no DHT peers. " + "Fetch of {0} may not succeed until you start another torrent, enable open trackers, or enable DHT.", name)); } } else { - addMessage(_("Adding {0}", name)); + addMessage(_t("Adding {0}", name)); } return torrent; } @@ -1098,6 +1427,7 @@ public class SnarkManager implements CompleteListener { snark.stopTorrent(); _magnets.remove(snark.getName()); removeMagnetStatus(snark.getInfoHash()); + removeTorrentStatus(snark); } /** @@ -1112,7 +1442,7 @@ public class SnarkManager implements CompleteListener { synchronized (_snarks) { Snark snark = getTorrentByInfoHash(torrent.getInfoHash()); if (snark != null) { - addMessage(_("Download already running: {0}", snark.getBaseName())); + addMessage(_t("Download already running: {0}", snark.getBaseName())); return; } String name = torrent.getName(); @@ -1129,32 +1459,40 @@ public class SnarkManager implements CompleteListener { * This verifies that a torrent with this infohash is not already added. * This may take a LONG time to create or check the storage. * + * Called from servlet. This is only for the 'create torrent' form. + * * @param metainfo the metainfo for the torrent * @param bitfield the current completion status of the torrent * @param filename the absolute path to save the metainfo to, generally ending in ".torrent", which is also the name of the torrent * Must be a filesystem-safe name. + * @param baseFile may be null, if so look in rootDataDir * @throws RuntimeException via Snark.fatal() + * @return success * @since 0.8.4 */ - public void addTorrent(MetaInfo metainfo, BitField bitfield, String filename, boolean dontAutoStart) throws IOException { + public boolean addTorrent(MetaInfo metainfo, BitField bitfield, String filename, + File baseFile, boolean dontAutoStart) throws IOException { // prevent interference by DirMonitor synchronized (_snarks) { Snark snark = getTorrentByInfoHash(metainfo.getInfoHash()); if (snark != null) { - addMessage(_("Torrent with this info hash is already running: {0}", snark.getBaseName())); - return; + addMessage(_t("Torrent with this info hash is already running: {0}", snark.getBaseName())); + return false; + } else { + saveTorrentStatus(metainfo, bitfield, null, baseFile, true, 0, true); // no file priorities } - // so addTorrent won't recheck - saveTorrentStatus(metainfo, bitfield, null); // no file priorities + // so addTorrent won't recheck try { locked_writeMetaInfo(metainfo, filename, areFilesPublic()); // hold the lock for a long time - addTorrent(filename, dontAutoStart); + addTorrent(filename, baseFile, dontAutoStart); } catch (IOException ioe) { - addMessage(_("Failed to copy torrent file to {0}", filename)); + addMessage(_t("Failed to copy torrent file to {0}", filename)); _log.error("Failed to write torrent file", ioe); + return false; } } + return true; } /** @@ -1166,22 +1504,23 @@ public class SnarkManager implements CompleteListener { * @param fromfile where the file is now, presumably in a temp directory somewhere * @param filename the absolute path to save the metainfo to, generally ending in ".torrent", which is also the name of the torrent * Must be a filesystem-safe name. + * @param dataDir must exist, or null to default to snark data directory * @throws RuntimeException via Snark.fatal() * @since 0.8.4 */ - public void copyAndAddTorrent(File fromfile, String filename) throws IOException { + public void copyAndAddTorrent(File fromfile, String filename, File dataDir) throws IOException { // prevent interference by DirMonitor synchronized (_snarks) { boolean success = FileUtil.copy(fromfile.getAbsolutePath(), filename, false); if (!success) { - addMessage(_("Failed to copy torrent file to {0}", filename)); + addMessage(_t("Failed to copy torrent file to {0}", filename)); _log.error("Failed to write torrent file to " + filename); return; } if (!areFilesPublic()) SecureFileOutputStream.setPerms(new File(filename)); // hold the lock for a long time - addTorrent(filename); + addTorrent(filename, null, false, dataDir); } } @@ -1222,16 +1561,10 @@ public class SnarkManager implements CompleteListener { * A Snark.CompleteListener method. */ public long getSavedTorrentTime(Snark snark) { - byte[] ih = snark.getInfoHash(); - String infohash = Base64.encode(ih); - infohash = infohash.replace('=', '$'); - String time = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX); + Properties config = getConfig(snark); + String time = config.getProperty(PROP_META_STAMP); if (time == null) return 0; - int comma = time.indexOf(','); - if (comma <= 0) - return 0; - time = time.substring(0, comma); try { return Long.parseLong(time); } catch (NumberFormatException nfe) {} return 0; } @@ -1245,16 +1578,10 @@ public class SnarkManager implements CompleteListener { MetaInfo metainfo = snark.getMetaInfo(); if (metainfo == null) return null; - byte[] ih = snark.getInfoHash(); - String infohash = Base64.encode(ih); - infohash = infohash.replace('=', '$'); - String bf = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX); + Properties config = getConfig(snark); + String bf = config.getProperty(PROP_META_BITFIELD); if (bf == null) return null; - int comma = bf.indexOf(','); - if (comma <= 0) - return null; - bf = bf.substring(comma + 1).trim(); int len = metainfo.getPieces(); if (bf.equals(".")) { BitField bitfield = new BitField(len); @@ -1281,15 +1608,13 @@ public class SnarkManager implements CompleteListener { return; if (metainfo.getFiles() == null) return; - byte[] ih = snark.getInfoHash(); - String infohash = Base64.encode(ih); - infohash = infohash.replace('=', '$'); - String pri = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_PRIORITY_SUFFIX); + Properties config = getConfig(snark); + String pri = config.getProperty(PROP_META_PRIORITY); if (pri == null) return; int filecount = metainfo.getFiles().size(); int[] rv = new int[filecount]; - String[] arr = pri.split(","); + String[] arr = DataHelper.split(pri, ","); for (int i = 0; i < filecount && i < arr.length; i++) { if (arr[i].length() > 0) { try { @@ -1299,35 +1624,126 @@ public class SnarkManager implements CompleteListener { } storage.setFilePriorities(rv); } + + /** + * Get the base location for a torrent from the config file. + * @return File or null, doesn't necessarily exist + * @since 0.9.15 + */ + private File getSavedBaseFile(byte[] ih) { + Properties config = getConfig(ih); + String base = config.getProperty(PROP_META_BASE); + if (base == null) + return null; + return new File(base); + } + + /** + * Get setting for a torrent from the config file. + * @return setting, false if not found + * @since 0.9.15 + */ + public boolean getSavedPreserveNamesSetting(Snark snark) { + Properties config = getConfig(snark); + return Boolean.parseBoolean(config.getProperty(PROP_META_PRESERVE_NAMES)); + } + + /** + * Get setting for a torrent from the config file. + * @return setting, 0 if not found + * @since 0.9.15 + */ + public long getSavedUploaded(Snark snark) { + Properties config = getConfig(snark); + if (config != null) { + try { + return Long.parseLong(config.getProperty(PROP_META_UPLOADED)); + } catch (NumberFormatException nfe) {} + } + return 0; + } + + /** + * Get setting for a torrent from the config file. + * @return non-null, rv[0] is added time or 0; rv[1] is completed time or 0 + * @since 0.9.23 + */ + public long[] getSavedAddedAndCompleted(Snark snark) { + long[] rv = new long[2]; + Properties config = getConfig(snark); + if (config != null) { + try { + rv[0] = Long.parseLong(config.getProperty(PROP_META_ADDED)); + } catch (NumberFormatException nfe) {} + try { + rv[1] = Long.parseLong(config.getProperty(PROP_META_COMPLETED)); + } catch (NumberFormatException nfe) {} + } + return rv; + } + /** + * Save the completion status of a torrent and other data in the config file + * for that torrent. Does nothing for magnets. + * + * @since 0.9.15 + */ + public void saveTorrentStatus(Snark snark) { + MetaInfo meta = snark.getMetaInfo(); + Storage storage = snark.getStorage(); + if (meta == null || storage == null) + return; + saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities(), + storage.getBase(), storage.getPreserveFileNames(), + snark.getUploaded(), snark.isStopped()); + } + /** * Save the completion status of a torrent and the current time in the config file - * in the form "i2psnark.zmeta.$base64infohash=$time,$base64bitfield". - * The config file property key is appended with the Base64 of the infohash, - * with the '=' changed to '$' since a key can't contain '='. + * for that torrent. * The time is a standard long converted to string. * The status is either a bitfield converted to Base64 or "." for a completed * torrent to save space in the config file and in memory. * + * @param metainfo non-null * @param bitfield non-null * @param priorities may be null + * @param base may be null */ - public void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities) { + private void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, + File base, boolean preserveNames, long uploaded, boolean stopped) { + synchronized (_configLock) { + locked_saveTorrentStatus(metainfo, bitfield, priorities, base, preserveNames, uploaded, stopped); + } + } + + private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, + File base, boolean preserveNames, long uploaded, boolean stopped) { byte[] ih = metainfo.getInfoHash(); - String infohash = Base64.encode(ih); - infohash = infohash.replace('=', '$'); - String now = "" + System.currentTimeMillis(); + Properties config = getConfig(ih); + String now = Long.toString(System.currentTimeMillis()); + config.setProperty(PROP_META_STAMP, now); + if (config.getProperty(PROP_META_ADDED) == null) + config.setProperty(PROP_META_ADDED, now); String bfs; if (bitfield.complete()) { bfs = "."; + if (config.getProperty(PROP_META_COMPLETED) == null) + config.setProperty(PROP_META_COMPLETED, now); } else { byte[] bf = bitfield.getFieldBytes(); bfs = Base64.encode(bf); + config.remove(PROP_META_COMPLETED); } - _config.setProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX, now + "," + bfs); + config.setProperty(PROP_META_BITFIELD, bfs); + config.setProperty(PROP_META_PRESERVE_NAMES, Boolean.toString(preserveNames)); + config.setProperty(PROP_META_UPLOADED, Long.toString(uploaded)); + boolean running = !stopped; + config.setProperty(PROP_META_RUNNING, Boolean.toString(running)); + if (base != null) + config.setProperty(PROP_META_BASE, base.getAbsolutePath()); // now the file priorities - String prop = PROP_META_PREFIX + infohash + PROP_META_PRIORITY_SUFFIX; if (priorities != null) { boolean nonzero = false; for (int i = 0; i < priorities.length; i++) { @@ -1345,41 +1761,151 @@ public class SnarkManager implements CompleteListener { if (i != priorities.length - 1) buf.append(','); } - _config.setProperty(prop, buf.toString()); + config.setProperty(PROP_META_PRIORITY, buf.toString()); } else { - _config.remove(prop); + config.remove(PROP_META_PRIORITY); } } else { - _config.remove(prop); + config.remove(PROP_META_PRIORITY); } + // magnet properties, no longer apply, we have the metainfo + config.remove(PROP_META_MAGNET); + config.remove(PROP_META_MAGNET_DIR); + config.remove(PROP_META_MAGNET_DN); + config.remove(PROP_META_MAGNET_TR); // TODO save closest DHT nodes too + locked_saveTorrentStatus(ih, config); + } - saveConfig(); - } - /** - * Remove the status of a torrent from the config file. - * This may help the config file from growing too big. + * @since 0.9.23 */ - public void removeTorrentStatus(MetaInfo metainfo) { - byte[] ih = metainfo.getInfoHash(); - String infohash = Base64.encode(ih); - infohash = infohash.replace('=', '$'); - _config.remove(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX); - _config.remove(PROP_META_PREFIX + infohash + PROP_META_PRIORITY_SUFFIX); - saveConfig(); + private void locked_saveTorrentStatus(byte[] ih, Properties config) { + File conf = configFile(_configDir, ih); + File subdir = conf.getParentFile(); + if (!subdir.exists()) + subdir.mkdirs(); + try { + DataHelper.storeProps(config, conf); + if (_log.shouldInfo()) + _log.info("Saved config to " + conf); + } catch (IOException ioe) { + _log.error("Unable to save the config to " + conf); + } } /** - * Just remember we have it + * Remove the status of a torrent by removing the config file. + */ + private void removeTorrentStatus(Snark snark) { + byte[] ih = snark.getInfoHash(); + File conf = configFile(_configDir, ih); + synchronized (_configLock) { + boolean ok = conf.delete(); + if (ok) { + if (_log.shouldInfo()) + _log.info("Deleted " + conf + " for " + snark.getName()); + } else { + if (_log.shouldWarn()) + _log.warn("Failed to delete " + conf + " for " + snark.getName()); + } + File subdir = conf.getParentFile(); + String[] files = subdir.list(); + if (files != null && files.length == 0) + subdir.delete(); + } + } + + /** + * Remove all orphaned torrent status files, which weren't removed + * before 0.9.20, and could be left around after a manual delete also. + * Run this once at startup. + * @since 0.9.20 + */ + private void cleanupTorrentStatus() { + Set torrents = new HashSet(32); + int found = 0; + int totalDeleted = 0; + synchronized (_snarks) { + for (Snark snark : _snarks.values()) { + torrents.add(new SHA1Hash(snark.getInfoHash())); + } + synchronized (_configLock) { + for (int i = 0; i < B64.length(); i++) { + File subdir = new File(_configDir, SUBDIR_PREFIX + B64.charAt(i)); + File[] configs = subdir.listFiles(); + if (configs == null) + continue; + int deleted = 0; + for (int j = 0; j < configs.length; j++) { + File config = configs[j]; + SHA1Hash ih = configFileToInfoHash(config); + if (ih == null) + continue; + found++; + if (torrents.contains(ih)) { + if (_log.shouldInfo()) + _log.info("Torrent for " + config + " exists"); + } else { + boolean ok = config.delete(); + if (ok) { + if (_log.shouldInfo()) + _log.info("Deleted " + config + " for " + ih); + deleted++; + } else { + if (_log.shouldWarn()) + _log.warn("Failed to delete " + config + " for " + ih); + } + } + } + if (deleted == configs.length) { + if (_log.shouldInfo()) + _log.info("Deleting " + subdir); + subdir.delete(); + } + totalDeleted += deleted; + } + } + } + if (_log.shouldInfo()) + _log.info("Cleanup found " + torrents.size() + " torrents and " + found + + " configs, deleted " + totalDeleted + " old configs"); + } + + /** + * Just remember we have it. + * This used to simply store a line in the config file, + * but now we also save it in its own config file, + * just like other torrents, so we can remember the directory, tracker, etc. + * + * @param dir may be null + * @param trackerURL may be null + * @param dn may be null * @since 0.8.4 */ - public void saveMagnetStatus(byte[] ih) { + public void saveMagnetStatus(byte[] ih, String dir, String trackerURL, String dn) { + // i2psnark.config file String infohash = Base64.encode(ih); infohash = infohash.replace('=', '$'); _config.setProperty(PROP_META_MAGNET_PREFIX + infohash, "."); - saveConfig(); + // its own config file + Properties config = new OrderedProperties(); + config.setProperty(PROP_META_MAGNET, "true"); + if (dir != null) + config.setProperty(PROP_META_MAGNET_DIR, dir); + if (trackerURL != null) + config.setProperty(PROP_META_MAGNET_TR, trackerURL); + if (dn != null) + config.setProperty(PROP_META_MAGNET_DN, dn); + String now = Long.toString(System.currentTimeMillis()); + config.setProperty(PROP_META_ADDED, now); + config.setProperty(PROP_META_STAMP, now); + // save + synchronized (_configLock) { + saveConfig(); + locked_saveTorrentStatus(ih, config); + } } /** @@ -1389,8 +1915,8 @@ public class SnarkManager implements CompleteListener { public void removeMagnetStatus(byte[] ih) { String infohash = Base64.encode(ih); infohash = infohash.replace('=', '$'); - _config.remove(PROP_META_MAGNET_PREFIX + infohash); - saveConfig(); + if (_config.remove(PROP_META_MAGNET_PREFIX + infohash) != null) + saveConfig(); } /** @@ -1401,18 +1927,18 @@ public class SnarkManager implements CompleteListener { private String validateTorrent(MetaInfo info) { List> files = info.getFiles(); if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) { - return _("Too many files in \"{0}\" ({1}), deleting it!", info.getName(), files.size()); + return _t("Too many files in \"{0}\" ({1})!", info.getName(), files.size()); } else if ( (files == null) && (info.getName().endsWith(".torrent")) ) { - return _("Torrent file \"{0}\" cannot end in \".torrent\", deleting it!", info.getName()); + return _t("Torrent file \"{0}\" cannot end in \".torrent\"!", info.getName()); } else if (info.getPieces() <= 0) { - return _("No pieces in \"{0}\", deleting it!", info.getName()); + return _t("No pieces in \"{0}\"!", info.getName()); } else if (info.getPieces() > Storage.MAX_PIECES) { - return _("Too many pieces in \"{0}\", limit is {1}, deleting it!", info.getName(), Storage.MAX_PIECES); + return _t("Too many pieces in \"{0}\", limit is {1}!", info.getName(), Storage.MAX_PIECES); } else if (info.getPieceLength(0) > Storage.MAX_PIECE_SIZE) { - return _("Pieces are too large in \"{0}\" ({1}B), deleting it.", info.getName(), DataHelper.formatSize2(info.getPieceLength(0))) + ' ' + - _("Limit is {0}B", DataHelper.formatSize2(Storage.MAX_PIECE_SIZE)); + return _t("Pieces are too large in \"{0}\" ({1}B)!", info.getName(), DataHelper.formatSize2(info.getPieceLength(0))) + ' ' + + _t("Limit is {0}B", DataHelper.formatSize2(Storage.MAX_PIECE_SIZE)); } else if (info.getTotalLength() <= 0) { - return _("Torrent \"{0}\" has no data, deleting it!", info.getName()); + return _t("Torrent \"{0}\" has no data!", info.getName()); } else if (info.getTotalLength() > Storage.MAX_TOTAL_SIZE) { System.out.println("torrent info: " + info.toString()); List lengths = info.getLengths(); @@ -1420,7 +1946,7 @@ public class SnarkManager implements CompleteListener { for (int i = 0; i < lengths.size(); i++) System.out.println("File " + i + " is " + lengths.get(i) + " long."); - return _("Torrents larger than {0}B are not supported yet, deleting \"{1}\"", Storage.MAX_TOTAL_SIZE, info.getName()); + return _t("Torrents larger than {0}B are not supported yet \"{1}\"!", Storage.MAX_TOTAL_SIZE, info.getName()); } else { // ok return null; @@ -1428,7 +1954,8 @@ public class SnarkManager implements CompleteListener { } /** - * Stop the torrent, leaving it on the list of torrents unless told to remove it + * Stop the torrent, leaving it on the list of torrents unless told to remove it. + * If shouldRemove is true, removes the config file also. */ public Snark stopTorrent(String filename, boolean shouldRemove) { File sfile = new File(filename); @@ -1436,7 +1963,7 @@ public class SnarkManager implements CompleteListener { filename = sfile.getCanonicalPath(); } catch (IOException ioe) { _log.error("Unable to remove the torrent " + filename, ioe); - addMessage(_("Error: Could not remove the torrent {0}", filename) + ": " + ioe.getMessage()); + addMessage(_t("Error: Could not remove the torrent {0}", filename) + ": " + ioe.getMessage()); return null; } int remaining = 0; @@ -1456,14 +1983,17 @@ public class SnarkManager implements CompleteListener { // I2PServerSocket.accept() call properly?) ////_util. } + if (shouldRemove) + removeTorrentStatus(torrent); if (!wasStopped) - addMessage(_("Torrent stopped: \"{0}\"", torrent.getBaseName())); + addMessageNoEscape(_t("Torrent stopped: {0}", linkify(torrent))); } return torrent; } /** - * Stop the torrent, leaving it on the list of torrents unless told to remove it + * Stop the torrent, leaving it on the list of torrents unless told to remove it. + * If shouldRemove is true, removes the config file also. * @since 0.8.4 */ public void stopTorrent(Snark torrent, boolean shouldRemove) { @@ -1475,12 +2005,14 @@ public class SnarkManager implements CompleteListener { boolean wasStopped = torrent.isStopped(); torrent.stopTorrent(); if (!wasStopped) - addMessage(_("Torrent stopped: \"{0}\"", torrent.getBaseName())); + addMessageNoEscape(_t("Torrent stopped: {0}", linkify(torrent))); + if (shouldRemove) + removeTorrentStatus(torrent); } /** * Stop the torrent and delete the torrent file itself, but leaving the data - * behind. + * behind. Removes saved config file also. * Holds the snarks lock to prevent interference from the DirMonitor. */ public void removeTorrent(String filename) { @@ -1493,10 +2025,7 @@ public class SnarkManager implements CompleteListener { File torrentFile = new File(filename); torrentFile.delete(); } - Storage storage = torrent.getStorage(); - if (storage != null) - removeTorrentStatus(storage.getMetaInfo()); - addMessage(_("Torrent removed: \"{0}\"", torrent.getBaseName())); + addMessage(_t("Torrent removed: \"{0}\"", torrent.getBaseName())); } private class DirMonitor implements Runnable { @@ -1504,7 +2033,7 @@ public class SnarkManager implements CompleteListener { // don't bother delaying if auto start is false long delay = (60L * 1000) * getStartupDelayMinutes(); if (delay > 0 && shouldAutoStart()) { - addMessage(_("Adding torrents in {0}", DataHelper.formatDuration2(delay))); + addMessage(_t("Adding torrents in {0}", DataHelper.formatDuration2(delay))); try { Thread.sleep(delay); } catch (InterruptedException ie) {} // Remove that first message if (_messages.size() == 1) @@ -1519,23 +2048,33 @@ public class SnarkManager implements CompleteListener { File dir = getDataDir(); if (_log.shouldLog(Log.DEBUG)) _log.debug("Directory Monitor loop over " + dir.getAbsolutePath()); + boolean ok; try { // Don't let this interfere with .torrent files being added or deleted synchronized (_snarks) { - monitorTorrents(dir); + ok = monitorTorrents(dir); } - } catch (Exception e) { + } catch (RuntimeException e) { _log.error("Error in the DirectoryMonitor", e); + ok = false; } if (doMagnets) { + // first run only try { addMagnets(); doMagnets = false; - } catch (Exception e) { + } catch (RuntimeException e) { _log.error("Error in the DirectoryMonitor", e); } if (!_snarks.isEmpty()) - addMessage(_("Up bandwidth limit is {0} KBps", _util.getMaxUpBW())); + addMessage(_t("Up bandwidth limit is {0} KBps", _util.getMaxUpBW())); + // To fix bug where files were left behind, + // but also good for when user removes snarks when i2p is not running + // Don't run if there was an error, as we would delete the torrent config + // file(s) and we don't want to do that. We'll do the cleanup the next + // time i2psnark starts. See ticket #1658. + if (ok) + cleanupTorrentStatus(); } try { Thread.sleep(60*1000); } catch (InterruptedException ie) {} } @@ -1552,12 +2091,8 @@ public class SnarkManager implements CompleteListener { Storage storage = snark.getStorage(); if (meta == null || storage == null) return; - StringBuilder buf = new StringBuilder(256); - buf.append("").append(storage.getBaseName()).append(""); - addMessage(_("Download finished: {0}", buf.toString())); // + " (" + _("size: {0}B", DataHelper.formatSize2(len)) + ')'); + if (snark.getDownloaded() > 0) + addMessageNoEscape(_t("Download finished: {0}", linkify(snark))); updateStatus(snark); } @@ -1568,7 +2103,9 @@ public class SnarkManager implements CompleteListener { MetaInfo meta = snark.getMetaInfo(); Storage storage = snark.getStorage(); if (meta != null && storage != null) - saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities()); + saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities(), + storage.getBase(), storage.getPreserveFileNames(), snark.getUploaded(), + snark.isStopped()); } /** @@ -1590,7 +2127,9 @@ public class SnarkManager implements CompleteListener { snark.stopTorrent(); return null; } - saveTorrentStatus(meta, storage.getBitField(), null); // no file priorities + saveTorrentStatus(meta, storage.getBitField(), null, + storage.getBase(), storage.getPreserveFileNames(), 0, + snark.isStopped()); // temp for addMessage() in case canonical throws String name = storage.getBaseName(); try { @@ -1608,11 +2147,11 @@ public class SnarkManager implements CompleteListener { } _magnets.remove(snark.getName()); removeMagnetStatus(snark.getInfoHash()); - addMessage(_("Metainfo received for {0}", snark.getName())); - addMessage(_("Starting up torrent {0}", storage.getBaseName())); + addMessage(_t("Metainfo received for {0}", snark.getName())); + addMessageNoEscape(_t("Starting up torrent {0}", linkify(snark))); return name; } catch (IOException ioe) { - addMessage(_("Failed to copy torrent file to {0}", name)); + addMessage(_t("Failed to copy torrent file to {0}", name)); _log.error("Failed to write torrent file", ioe); } } @@ -1624,7 +2163,7 @@ public class SnarkManager implements CompleteListener { * @since 0.9 */ public void fatal(Snark snark, String error) { - addMessage(_("Error on torrent {0}", snark.getName()) + ": " + error); + addMessage(_t("Error on torrent {0}", snark.getName()) + ": " + error); } /** @@ -1643,29 +2182,67 @@ public class SnarkManager implements CompleteListener { // End Snark.CompleteListeners + /** + * An HTML link to the file if complete and a single file, + * to the directory if not complete or not a single file, + * or simply the unlinkified name of the snark if a magnet + * + * @since 0.9.23 + */ + private String linkify(Snark snark) { + MetaInfo meta = snark.getMetaInfo(); + Storage storage = snark.getStorage(); + if (meta == null || storage == null) + return DataHelper.escapeHTML(snark.getBaseName()); + StringBuilder buf = new StringBuilder(256); + String base = DataHelper.escapeHTML(storage.getBaseName()); + buf.append("").append(base).append(""); + return buf.toString(); + } + /** * Add all magnets from the config file + * * @since 0.8.4 */ private void addMagnets() { - for (Object o : _config.keySet()) { - String k = (String) o; + boolean changed = false; + for (Iterator iter = _config.keySet().iterator(); iter.hasNext(); ) { + String k = (String) iter.next(); if (k.startsWith(PROP_META_MAGNET_PREFIX)) { String b64 = k.substring(PROP_META_MAGNET_PREFIX.length()); b64 = b64.replace('$', '='); byte[] ih = Base64.decode(b64); // ignore value - TODO put tracker URL in value - if (ih != null && ih.length == 20) - addMagnet(_("Magnet") + ' ' + I2PSnarkUtil.toHex(ih), ih, null, false); - // else remove from config? + if (ih != null && ih.length == 20) { + Properties config = getConfig(ih); + String name = config.getProperty(PROP_META_MAGNET_DN); + if (name == null) + name = _t("Magnet") + ' ' + I2PSnarkUtil.toHex(ih); + String tracker = config.getProperty(PROP_META_MAGNET_TR); + String dir = config.getProperty(PROP_META_MAGNET_DIR); + File dirf = (dir != null) ? (new File(dir)) : null; + addMagnet(name, ih, tracker, false, dirf); + } else { + iter.remove(); + changed = true; + } } } + if (changed) + saveConfig(); } /** * caller must synchronize on _snarks + * + * @return success, false if an error adding any torrent. */ - private void monitorTorrents(File dir) { + private boolean monitorTorrents(File dir) { + boolean rv = true; String fileNames[] = dir.list(TorrentFilenameFilter.instance()); List foundNames = new ArrayList(0); if (fileNames != null) { @@ -1687,14 +2264,15 @@ public class SnarkManager implements CompleteListener { // already known. noop } else { if (shouldAutoStart() && !_util.connect()) - addMessage(_("Unable to connect to I2P!")); + addMessage(_t("Unable to connect to I2P!")); try { // Snark.fatal() throws a RuntimeException // don't let one bad torrent kill the whole loop - addTorrent(name, !shouldAutoStart()); - } catch (Exception e) { - addMessage(_("Error: Could not add the torrent {0}", name) + ": " + e); + addTorrent(name, null, !shouldAutoStart()); + } catch (RuntimeException e) { + addMessage(_t("Error: Could not add the torrent {0}", name) + ": " + e); _log.error("Unable to add the torrent " + name, e); + rv = false; } } } @@ -1710,25 +2288,26 @@ public class SnarkManager implements CompleteListener { // Snark.fatal() throws a RuntimeException // don't let one bad torrent kill the whole loop stopTorrent(name, true); - } catch (Exception e) { + } catch (RuntimeException e) { // don't bother with message } } } + return rv; } /** translate */ - private String _(String s) { + private String _t(String s) { return _util.getString(s); } /** translate */ - private String _(String s, Object o) { + private String _t(String s, Object o) { return _util.getString(s, o); } /** translate */ - private String _(String s, Object o, Object o2) { + private String _t(String s, Object o, Object o2) { return _util.getString(s, o, o2); } @@ -1766,12 +2345,12 @@ public class SnarkManager implements CompleteListener { if ( (trackers == null) || (trackers.trim().length() <= 0) ) { setDefaultTrackerMap(true); } else { - String[] toks = trackers.split(","); + String[] toks = DataHelper.split(trackers, ","); for (int i = 0; i < toks.length; i += 2) { String name = toks[i].trim().replace(",", ","); String url = toks[i+1].trim().replace(",", ","); if ( (name.length() > 0) && (url.length() > 0) ) { - String urls[] = url.split("=", 2); + String urls[] = DataHelper.split(url, "=", 2); String url2 = urls.length > 1 ? urls[1] : ""; _trackerMap.put(name, new Tracker(name, urls[0], url2)); } @@ -1789,7 +2368,9 @@ public class SnarkManager implements CompleteListener { _trackerMap.clear(); for (int i = 0; i < DEFAULT_TRACKERS.length; i += 2) { String name = DEFAULT_TRACKERS[i]; - String urls[] = DEFAULT_TRACKERS[i+1].split("=", 2); + if (name.equals("TheBland") && !SigType.ECDSA_SHA256_P256.isAvailable()) + continue; + String urls[] = DataHelper.split(DEFAULT_TRACKERS[i+1], "=", 2); String url2 = urls.length > 1 ? urls[1] : null; _trackerMap.put(name, new Tracker(name, urls[0], url2)); } @@ -1831,28 +2412,36 @@ public class SnarkManager implements CompleteListener { public void startTorrent(byte[] infoHash) { for (Snark snark : _snarks.values()) { if (DataHelper.eq(infoHash, snark.getInfoHash())) { - if (snark.isStarting() || !snark.isStopped()) { - addMessage("Torrent already started"); - return; - } - boolean connected = _util.connected(); - if ((!connected) && !_util.isConnecting()) - addMessage(_("Opening the I2P tunnel")); - addMessage(_("Starting up torrent {0}", snark.getBaseName())); - if (connected) { - snark.startTorrent(); - } else { - // mark it for the UI - snark.setStarting(); - (new I2PAppThread(new ThreadedStarter(snark), "TorrentStarter", true)).start(); - try { Thread.sleep(200); } catch (InterruptedException ie) {} - } + startTorrent(snark); return; } } addMessage("Torrent not found?"); } + /** + * If not connected, thread it, otherwise inline + * @since 0.9.23 + */ + public void startTorrent(Snark snark) { + if (snark.isStarting() || !snark.isStopped()) { + addMessage("Torrent already started"); + return; + } + boolean connected = _util.connected(); + if ((!connected) && !_util.isConnecting()) + addMessage(_t("Opening the I2P tunnel")); + addMessageNoEscape(_t("Starting up torrent {0}", linkify(snark))); + if (connected) { + snark.startTorrent(); + } else { + // mark it for the UI + snark.setStarting(); + (new I2PAppThread(new ThreadedStarter(snark), "TorrentStarter", true)).start(); + try { Thread.sleep(200); } catch (InterruptedException ie) {} + } + } + /** * If not connected, thread it, otherwise inline * @since 0.9.1 @@ -1861,7 +2450,7 @@ public class SnarkManager implements CompleteListener { if (_util.connected()) { startAll(); } else { - addMessage(_("Opening the I2P tunnel and starting all torrents.")); + addMessage(_t("Opening the I2P tunnel and starting all torrents.")); for (Snark snark : _snarks.values()) { // mark it for the UI snark.setStarting(); @@ -1881,7 +2470,7 @@ public class SnarkManager implements CompleteListener { public void run() { try { run2(); - } catch (Exception e) { + } catch (RuntimeException e) { _log.error("Error starting", e); } } @@ -1911,7 +2500,7 @@ public class SnarkManager implements CompleteListener { * Stop all running torrents, and close the tunnel after a delay * to allow for announces. * If called at router shutdown via Jetty shutdown hook -> webapp destroy() -> stop(), - * the tunnel won't actually be closed as the SimpleScheduler is already shutdown + * the tunnel won't actually be closed as the SimpleTimer2 is already shutdown * or will be soon, so we delay a few seconds inline. * @param finalShutdown if true, sleep at the end if any torrents were running * @since 0.9.1 @@ -1924,7 +2513,7 @@ public class SnarkManager implements CompleteListener { for (Snark snark : _snarks.values()) { if (!snark.isStopped()) { if (count == 0) - addMessage(_("Stopping all torrents and closing the I2P tunnel.")); + addMessage(_t("Stopping all torrents and closing the I2P tunnel.")); count++; if (finalShutdown) snark.stopTorrent(true); @@ -1942,15 +2531,15 @@ public class SnarkManager implements CompleteListener { dht.stop(); // Schedule this even for final shutdown, as there's a chance // that it's just this webapp that is stopping. - _context.simpleScheduler().addEvent(new Disconnector(), 60*1000); - addMessage(_("Closing I2P tunnel after notifying trackers.")); + _context.simpleTimer2().addEvent(new Disconnector(), 60*1000); + addMessage(_t("Closing I2P tunnel after notifying trackers.")); if (finalShutdown) { try { Thread.sleep(5*1000); } catch (InterruptedException ie) {} } } else { _util.disconnect(); _stopping = false; - addMessage(_("I2P tunnel closed.")); + addMessage(_t("I2P tunnel closed.")); } } } @@ -1961,7 +2550,57 @@ public class SnarkManager implements CompleteListener { if (_util.connected()) { _util.disconnect(); _stopping = false; - addMessage(_("I2P tunnel closed.")); + addMessage(_t("I2P tunnel closed.")); + } + } + } + + /** + * Threaded. Torrent must be stopped. + * @since 0.9.23 + */ + public void recheckTorrent(Snark snark) { + if (snark.isStarting() || !snark.isStopped()) { + addMessage("Cannot check " + snark.getBaseName() + ", torrent already started"); + return; + } + Storage storage = snark.getStorage(); + if (storage == null) { + addMessage("Cannot check " + snark.getBaseName() + ", no storage"); + return; + } + (new I2PAppThread(new ThreadedRechecker(snark), "TorrentRechecker", true)).start(); + try { Thread.sleep(200); } catch (InterruptedException ie) {} + } + + /** + * @since 0.9.23 + */ + private class ThreadedRechecker implements Runnable { + private final Snark snark; + /** must have non-null storage */ + public ThreadedRechecker(Snark s) { snark = s; } + public void run() { + try { + if (_log.shouldWarn()) + _log.warn("Starting recheck of " + snark.getBaseName()); + boolean changed = snark.getStorage().recheck(); + if (changed) + updateStatus(snark); + if (_log.shouldWarn()) + _log.warn("Finished recheck of " + snark.getBaseName() + " changed? " + changed); + String link = linkify(snark); + if (changed) { + int pieces = snark.getPieces(); + double completion = (pieces - snark.getNeeded()) / (double) pieces; + String complete = (new DecimalFormat("0.00%")).format(completion); + addMessageNoEscape(_t("Finished recheck of torrent {0}, now {1} complete", link, complete)); + } else { + addMessageNoEscape(_t("Finished recheck of torrent {0}, unchanged", link)); + } + } catch (IOException e) { + _log.error("Error rechecking " + snark.getBaseName(), e); + addMessage(_t("Error checking the torrent {0}", snark.getBaseName()) + ": " + e); } } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 5b7aa962f..1a8349f5f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -20,6 +20,7 @@ package org.klomp.snark; +import java.io.Closeable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -32,10 +33,14 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.SortedSet; import java.util.StringTokenizer; +import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import gnu.getopt.Getopt; + import net.i2p.I2PAppContext; import net.i2p.crypto.SHA1; import net.i2p.data.ByteArray; @@ -48,10 +53,11 @@ import net.i2p.util.SystemVersion; /** * Maintains pieces on disk. Can be used to store and retrieve pieces. */ -public class Storage +public class Storage implements Closeable { private final MetaInfo metainfo; private final List _torrentFiles; + private final File _base; private final StorageListener listener; private final I2PSnarkUtil _util; private final Log _log; @@ -63,35 +69,42 @@ public class Storage private final int piece_size; private final int pieces; private final long total_length; + private final boolean _preserveFileNames; private boolean changed; private volatile boolean _isChecking; private final AtomicInteger _allocateCount = new AtomicInteger(); + private final AtomicInteger _checkProgress = new AtomicInteger(); /** The default piece size. */ private static final int DEFAULT_PIECE_SIZE = 256*1024; /** bigger than this will be rejected */ - public static final int MAX_PIECE_SIZE = 4*1024*1024; + public static final int MAX_PIECE_SIZE = 16*1024*1024; /** The maximum number of pieces in a torrent. */ - public static final int MAX_PIECES = 10*1024; + public static final int MAX_PIECES = 32*1024; public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES; private static final Map _filterNameCache = new ConcurrentHashMap(); private static final boolean _isWindows = SystemVersion.isWindows(); + private static final boolean _isARM = SystemVersion.isARM(); private static final int BUFSIZE = PeerState.PARTSIZE; private static final ByteCache _cache = ByteCache.getInstance(16, BUFSIZE); /** - * Creates a new storage based on the supplied MetaInfo. This will + * Creates a new storage based on the supplied MetaInfo. + * + * Does not check storage. Caller MUST call check(), which will * try to create and/or check all needed files in the MetaInfo. * - * Does not check storage. Caller MUST call check() + * @param baseFile the torrent data file or dir + * @param preserveFileNames if true, do not remap names to a 'safe' charset */ - public Storage(I2PSnarkUtil util, MetaInfo metainfo, StorageListener listener) + public Storage(I2PSnarkUtil util, File baseFile, MetaInfo metainfo, StorageListener listener, boolean preserveFileNames) { _util = util; _log = util.getContext().logManager().getLog(Storage.class); + _base = baseFile; this.metainfo = metainfo; this.listener = listener; needed = metainfo.getPieces(); @@ -102,6 +115,7 @@ public class Storage List> files = metainfo.getFiles(); int sz = files != null ? files.size() : 1; _torrentFiles = new ArrayList(sz); + _preserveFileNames = preserveFileNames; } /** @@ -113,16 +127,20 @@ public class Storage * * @param announce may be null * @param listener may be null + * @param created_by may be null * @throws IOException when creating and/or checking files fails. */ public Storage(I2PSnarkUtil util, File baseFile, String announce, List> announce_list, + String created_by, boolean privateTorrent, StorageListener listener) throws IOException { _util = util; + _base = baseFile; _log = util.getContext().logManager().getLog(Storage.class); this.listener = listener; + _preserveFileNames = true; // Create names, rafs and lengths arrays. _torrentFiles = getFiles(baseFile); @@ -148,7 +166,7 @@ public class Storage else pc_size = DEFAULT_PIECE_SIZE; int pcs = (int) ((total - 1)/pc_size) + 1; - while (pcs > (MAX_PIECES * 2 / 3) && pc_size < MAX_PIECE_SIZE) + while (pcs > (MAX_PIECES / 3) && pc_size < MAX_PIECE_SIZE) { pc_size *= 2; pcs = (int) ((total - 1)/pc_size) +1; @@ -183,7 +201,7 @@ public class Storage byte[] piece_hashes = fast_digestCreate(); metainfo = new MetaInfo(announce, baseFile.getName(), null, files, lengthsList, piece_size, piece_hashes, total, privateTorrent, - announce_list); + announce_list, created_by); } @@ -295,6 +313,18 @@ public class Storage return _isChecking; } + /** + * If checking is in progress, return completion 0.0 ... 1.0, + * else return 1.0. + * @since 0.9.23 + */ + public double getCheckingProgress() { + if (_isChecking) + return _checkProgress.get() / (double) pieces; + else + return 1.0d; + } + /** * Disk allocation (ballooning) in progress. * Always false on Windows. @@ -305,39 +335,48 @@ public class Storage } /** - * @param file canonical path (non-directory) + * Get index to pass to remaining(), getPriority(), setPriority() + * + * @param file non-canonical path (non-directory) + * @return internal index of file; -1 if unknown file + * @since 0.9.15 + */ + public int indexOf(File file) { + for (int i = 0; i < _torrentFiles.size(); i++) { + File f = _torrentFiles.get(i).RAFfile; + if (f.equals(file)) + return i; + } + return -1; + } + + /** + * @param fileIndex as obtained from indexOf * @return number of bytes remaining; -1 if unknown file * @since 0.7.14 */ - public long remaining(String file) { +/**** + public long remaining(int fileIndex) { + if (fileIndex < 0 || fileIndex >= _torrentFiles.size()) + return -1; + if (complete()) + return 0; long bytes = 0; - for (TorrentFile tf : _torrentFiles) { - File f = tf.RAFfile; - // use canonical in case snark dir or sub dirs are symlinked - String canonical = null; - if (f != null) { - try { - canonical = f.getCanonicalPath(); - } catch (IOException ioe) { - f = null; - } - } - if (f != null && canonical.equals(file)) { - if (complete()) - return 0; - int psz = piece_size; + for (int i = 0; i < _torrentFiles.size(); i++) { + TorrentFile tf = _torrentFiles.get(i); + if (i == fileIndex) { long start = bytes; long end = start + tf.length; - int pc = (int) (bytes / psz); + int pc = (int) (bytes / piece_size); long rv = 0; if (!bitfield.get(pc)) - rv = Math.min(psz - (start % psz), tf.length); - for (int j = pc + 1; (((long)j) * psz) < end && j < pieces; j++) { + rv = Math.min(piece_size - (start % piece_size), tf.length); + for (int j = pc + 1; (((long)j) * piece_size) < end && j < pieces; j++) { if (!bitfield.get(j)) { - if (((long)(j+1))*psz < end) - rv += psz; + if (((long)(j+1))*piece_size < end) + rv += piece_size; else - rv += end - (((long)j) * psz); + rv += end - (((long)j) * piece_size); } } return rv; @@ -346,51 +385,66 @@ public class Storage } return -1; } +****/ /** - * @param file canonical path (non-directory) + * For efficiency, calculate remaining bytes for all files at once + * + * @return number of bytes remaining for each file, use indexOf() to get index for a file + * @since 0.9.23 + */ + public long[] remaining() { + long[] rv = new long[_torrentFiles.size()]; + if (complete()) + return rv; + long bytes = 0; + for (int i = 0; i < _torrentFiles.size(); i++) { + TorrentFile tf = _torrentFiles.get(i); + long start = bytes; + long end = start + tf.length; + int pc = (int) (bytes / piece_size); + long rvi = 0; + if (!bitfield.get(pc)) + rvi = Math.min(piece_size - (start % piece_size), tf.length); + for (int j = pc + 1; (((long)j) * piece_size) < end && j < pieces; j++) { + if (!bitfield.get(j)) { + if (((long)(j+1))*piece_size < end) + rvi += piece_size; + else + rvi += end - (((long)j) * piece_size); + } + } + rv[i] = rvi; + bytes += tf.length; + } + return rv; + } + + /** + * @param fileIndex as obtained from indexOf * @since 0.8.1 */ - public int getPriority(String file) { + public int getPriority(int fileIndex) { if (complete() || metainfo.getFiles() == null) return 0; - for (TorrentFile tf : _torrentFiles) { - File f = tf.RAFfile; - // use canonical in case snark dir or sub dirs are symlinked - if (f != null) { - try { - String canonical = f.getCanonicalPath(); - if (canonical.equals(file)) - return tf.priority; - } catch (IOException ioe) {} - } - } - return 0; + if (fileIndex < 0 || fileIndex >= _torrentFiles.size()) + return 0; + return _torrentFiles.get(fileIndex).priority; } /** * Must call Snark.updatePiecePriorities() * (which calls getPiecePriorities()) after calling this. - * @param file canonical path (non-directory) + * @param fileIndex as obtained from indexOf * @param pri default 0; <0 to disable * @since 0.8.1 */ - public void setPriority(String file, int pri) { + public void setPriority(int fileIndex, int pri) { if (complete() || metainfo.getFiles() == null) return; - for (TorrentFile tf : _torrentFiles) { - File f = tf.RAFfile; - // use canonical in case snark dir or sub dirs are symlinked - if (f != null) { - try { - String canonical = f.getCanonicalPath(); - if (canonical.equals(file)) { - tf.priority = pri; - return; - } - } catch (IOException ioe) {} - } - } + if (fileIndex < 0 || fileIndex >= _torrentFiles.size()) + return; + _torrentFiles.get(fileIndex).priority = pri; } /** @@ -448,9 +502,8 @@ public class Storage int file = 0; long pcEnd = -1; long fileEnd = _torrentFiles.get(0).length - 1; - int psz = piece_size; for (int i = 0; i < rv.length; i++) { - pcEnd += psz; + pcEnd += piece_size; int pri = _torrentFiles.get(file).priority; while (fileEnd <= pcEnd && file < _torrentFiles.size() - 1) { file++; @@ -465,6 +518,31 @@ public class Storage return rv; } + /** + * Call setPriority() for all changed files first, + * then call this. + * The length of all the pieces that are not yet downloaded, + * and are set to skipped. + * This is not the same as the total of all skipped files, + * since pieces may span multiple files. + * + * @return 0 on error, if complete, or if only one file + * @since 0.9.24 + */ + public long getSkippedLength() { + int[] pri = getPiecePriorities(); + if (pri == null) + return 0; + long rv = 0; + final int end = pri.length - 1; + for (int i = 0; i <= end; i++) { + if (pri[i] <= -9 && !bitfield.get(i)) { + rv += (i != end) ? piece_size : metainfo.getPieceLength(i); + } + } + return rv; + } + /** * The BitField that tells which pieces this storage contains. * Do not change this since this is the current state of the storage. @@ -483,31 +561,37 @@ public class Storage * @since 0.7.14 */ public String getBaseName() { - return filterName(metainfo.getName()); + return optFilterName(metainfo.getName()); + } + + /** @since 0.9.15 */ + public boolean getPreserveFileNames() { + return _preserveFileNames; } /** * Creates (and/or checks) all files from the metainfo file list. * Only call this once, and only after the constructor with the metainfo. + * Use recheck() to check again later. + * + * @throws IllegalStateException if called more than once */ - public void check(String rootDir) throws IOException + public void check() throws IOException { - check(rootDir, 0, null); + check(0, null); } /** * Creates (and/or checks) all files from the metainfo file list. * Use a saved bitfield and timestamp from a config file. * Only call this once, and only after the constructor with the metainfo. + * Use recheck() to check again later. + * + * @throws IllegalStateException if called more than once */ - public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException + public void check(long savedTime, BitField savedBitField) throws IOException { - File base; boolean areFilesPublic = _util.getFilesPublic(); - if (areFilesPublic) - base = new File(rootDir, filterName(metainfo.getName())); - else - base = new SecureFile(rootDir, filterName(metainfo.getName())); boolean useSavedBitField = savedTime > 0 && savedBitField != null; if (!_torrentFiles.isEmpty()) @@ -517,18 +601,18 @@ public class Storage { // Create base as file. if (_log.shouldLog(Log.INFO)) - _log.info("Creating/Checking file: " + base); + _log.info("Creating/Checking file: " + _base); // createNewFile() can throw a "Permission denied" IOE even if the file exists??? // so do it second - if (!base.exists() && !base.createNewFile()) - throw new IOException("Could not create file " + base); + if (!_base.exists() && !_base.createNewFile()) + throw new IOException("Could not create file " + _base); - _torrentFiles.add(new TorrentFile(base, base, metainfo.getTotalLength())); + _torrentFiles.add(new TorrentFile(_base, _base, metainfo.getTotalLength())); if (useSavedBitField) { - long lm = base.lastModified(); + long lm = _base.lastModified(); if (lm <= 0 || lm > savedTime) useSavedBitField = false; - else if (base.length() != metainfo.getTotalLength()) + else if (_base.length() != metainfo.getTotalLength()) useSavedBitField = false; } } @@ -536,9 +620,9 @@ public class Storage { // Create base as dir. if (_log.shouldLog(Log.INFO)) - _log.info("Creating/Checking directory: " + base); - if (!base.mkdir() && !base.isDirectory()) - throw new IOException("Could not create directory " + base); + _log.info("Creating/Checking directory: " + _base); + if (!_base.mkdir() && !_base.isDirectory()) + throw new IOException("Could not create directory " + _base); List ls = metainfo.getLengths(); int size = files.size(); @@ -546,7 +630,7 @@ public class Storage for (int i = 0; i < size; i++) { List path = files.get(i); - File f = createFileFromNames(base, path, areFilesPublic); + File f = createFileFromNames(_base, path, areFilesPublic); // dup file name check after filtering for (int j = 0; j < i; j++) { if (f.equals(_torrentFiles.get(j).RAFfile)) { @@ -562,12 +646,12 @@ public class Storage else lastPath = '_' + lastPath; path.set(last, lastPath); - f = createFileFromNames(base, path, areFilesPublic); + f = createFileFromNames(_base, path, areFilesPublic); j = 0; } } long len = ls.get(i).longValue(); - _torrentFiles.add(new TorrentFile(base, f, len)); + _torrentFiles.add(new TorrentFile(_base, f, len)); total += len; if (useSavedBitField) { long lm = f.lastModified(); @@ -611,10 +695,9 @@ public class Storage * Doesn't really reopen the file descriptors for a restart. * Just does an existence check but no length check or data reverification * - * @param rootDir ignored * @throws IOE on fail */ - public void reopen(String rootDir) throws IOException + public void reopen() throws IOException { if (_torrentFiles.isEmpty()) throw new IOException("Storage not checked yet"); @@ -637,6 +720,19 @@ public class Storage 0x2028, 0x2029 }; + /** + * Filter the name, but only if configured to do so. + * We will do so on torrents received from others, but not + * on those we created ourselves, so we do not lose track of files. + * + * @since 0.9.15 + */ + private String optFilterName(String name) { + if (_preserveFileNames) + return name; + return filterName(name); + } + /** * Removes 'suspicious' characters from the given file name. * http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx @@ -677,7 +773,7 @@ public class Storage } rv = repl; } - } catch (Exception ex) { + } catch (RuntimeException ex) { ex.printStackTrace(); } } @@ -690,14 +786,16 @@ public class Storage * Note that filtering each path element individually may lead to * things going in the wrong place if there are duplicates * in intermediate path elements after filtering. + * + * @param names path elements */ - private static File createFileFromNames(File base, List names, boolean areFilesPublic) throws IOException + private File createFileFromNames(File base, List names, boolean areFilesPublic) throws IOException { File f = null; Iterator it = names.iterator(); while (it.hasNext()) { - String name = filterName(it.next()); + String name = optFilterName(it.next()); if (it.hasNext()) { // Another dir in the hierarchy. @@ -725,15 +823,73 @@ public class Storage return f; } - public static File getFileFromNames(File base, List names) - { - Iterator it = names.iterator(); - while (it.hasNext()) - { - String name = filterName(it.next()); - base = new File(base, name); + /** + * The base file or directory. + * @return the File + * @since 0.9.15 + */ + public File getBase() { + return _base; + } + + /** + * Does not include directories. Unsorted. + * @return a new List + * @since 0.9.15 + */ + public List getFiles() { + List rv = new ArrayList(_torrentFiles.size()); + for (TorrentFile tf : _torrentFiles) { + rv.add(tf.RAFfile); } - return base; + return rv; + } + + /** + * Does not include directories. + * @since 0.9.23 + */ + public int getFileCount() { + return _torrentFiles.size(); + } + + /** + * Includes the base for a multi-file torrent. + * Sorted bottom-up for easy deletion. + * Slow. Use for deletion only. + * @return a new Set or null for a single-file torrent + * @since 0.9.15 + */ + public SortedSet getDirectories() { + if (!_base.isDirectory()) + return null; + SortedSet rv = new TreeSet(Collections.reverseOrder()); + rv.add(_base); + for (TorrentFile tf : _torrentFiles) { + File f = tf.RAFfile; + do { + f = f.getParentFile(); + } while (f != null && rv.add(f)); + } + return rv; + } + + /** + * Blocking. Holds lock. + * Recommend running only when stopped. + * Caller should thread. + * Calls listener.setWantedPieces() on completion if anything changed. + * + * @return true if anything changed, false otherwise + * @since 0.9.23 + */ + public boolean recheck() throws IOException { + int previousNeeded = needed; + checkCreateFiles(true); + boolean changed = previousNeeded != needed; + if (listener != null && changed) + listener.setWantedPieces(this); + return changed; } /** @@ -760,6 +916,7 @@ public class Storage private void locked_checkCreateFiles(boolean recheck) throws IOException { + _checkProgress.set(0); // Whether we are resuming or not, // if any of the files already exists we assume we are resuming. boolean resume = false; @@ -776,13 +933,16 @@ public class Storage // Make sure all files are available and of correct length // The files should all exist as they have been created with zero length by createFilesFromNames() + long lengthProgress = 0; for (TorrentFile tf : _torrentFiles) { long length = tf.RAFfile.length(); + lengthProgress += tf.length; if(tf.RAFfile.exists() && length == tf.length) { if (listener != null) listener.storageAllocated(this, length); + _checkProgress.set(0); resume = true; // XXX Could dynamicly check } else if (length == 0) { @@ -794,6 +954,8 @@ public class Storage tf.closeRAF(); } catch (IOException ioe) {} } + if (!resume) + _checkProgress.set((int) (pieces * lengthProgress / total_length)); } else { String msg = "File '" + tf.name + "' exists, but has wrong length (expected " + tf.length + " but found " + length + ") - repairing corruption"; @@ -802,6 +964,7 @@ public class Storage _log.error(msg); changed = true; resume = true; + _checkProgress.set(0); _probablyComplete = false; // to force RW synchronized(tf) { RandomAccessFile raf = tf.checkRAF(); @@ -822,17 +985,16 @@ public class Storage long pieceEnd = 0; for (int i = 0; i < pieces; i++) { + _checkProgress.set(i); int length = getUncheckedPiece(i, piece); boolean correctHash = metainfo.checkPiece(i, piece, 0, length); // close as we go so we don't run out of file descriptors pieceEnd += length; while (fileEnd <= pieceEnd) { TorrentFile tf = _torrentFiles.get(file); - synchronized(tf) { - try { - tf.closeRAF(); - } catch (IOException ioe) {} - } + try { + tf.closeRAF(); + } catch (IOException ioe) {} if (++file >= _torrentFiles.size()) break; fileEnd += _torrentFiles.get(file).length; @@ -848,6 +1010,7 @@ public class Storage } } + _checkProgress.set(pieces); _probablyComplete = complete(); // close all the files so we don't end up with a zillion open ones; // we will reopen as needed @@ -904,9 +1067,7 @@ public class Storage for (TorrentFile tf : _torrentFiles) { try { - synchronized(tf) { tf.closeRAF(); - } } catch (IOException ioe) { _log.error("Error closing " + tf, ioe); // gobble gobble @@ -1131,17 +1292,15 @@ public class Storage return length; } - private static final long RAFCloseDelay = 4*60*1000; + private static final long RAF_CLOSE_DELAY = 4*60*1000; /** * Close unused RAFs - call periodically */ public void cleanRAFs() { - long cutoff = System.currentTimeMillis() - RAFCloseDelay; + long cutoff = System.currentTimeMillis() - RAF_CLOSE_DELAY; for (TorrentFile tf : _torrentFiles) { - synchronized(tf) { tf.closeRAF(cutoff); - } } } @@ -1267,7 +1426,9 @@ public class Storage // Windows will zero-fill up to the point of the write, which // will make the file fairly unfragmented, on average, at least until // near the end where it will get exponentially more fragmented. - if (!_isWindows) + // Also don't ballon on ARM, as a proxy for solid state disk, where fragmentation doesn't matter too much. + // Actual detection of SSD is almost impossible. + if (!_isWindows && !_isARM) isSparse = true; } @@ -1324,18 +1485,44 @@ public class Storage * @since 0.9.4 */ public static void main(String[] args) { - if (args.length < 1 || args.length > 2) { - System.err.println("Usage: Storage file-or-dir [announceURL]"); + boolean error = false; + String created_by = null; + String announce = null; + Getopt g = new Getopt("Storage", args, "a:c:"); + try { + int c; + while ((c = g.getopt()) != -1) { + switch (c) { + case 'a': + announce = g.getOptarg(); + break; + + case 'c': + created_by = g.getOptarg(); + break; + + case '?': + case ':': + default: + error = true; + break; + } // switch + } // while + } catch (RuntimeException e) { + e.printStackTrace(); + error = true; + } + if (error || args.length - g.getOptind() != 1) { + System.err.println("Usage: Storage [-a announceURL] [-c created-by] file-or-dir"); System.exit(1); } - File base = new File(args[0]); - String announce = args.length == 2 ? args[1] : null; + File base = new File(args[g.getOptind()]); I2PAppContext ctx = I2PAppContext.getGlobalContext(); I2PSnarkUtil util = new I2PSnarkUtil(ctx); File file = null; FileOutputStream out = null; try { - Storage storage = new Storage(util, base, announce, null, false, null); + Storage storage = new Storage(util, base, announce, null, created_by, false, null); MetaInfo meta = storage.getMetaInfo(); file = new File(storage.getBaseName() + ".torrent"); out = new FileOutputStream(file); diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index c30ccb0cc..5397cd757 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -23,8 +23,8 @@ package org.klomp.snark; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -36,7 +36,9 @@ import java.util.Locale; import java.util.Random; import java.util.Set; +import net.i2p.crypto.SigType; import net.i2p.data.DataHelper; +import net.i2p.data.Destination; import net.i2p.data.Hash; import net.i2p.util.ConvertToHash; import net.i2p.util.I2PAppThread; @@ -72,8 +74,8 @@ public class TrackerClient implements Runnable { private static final String STOPPED_EVENT = "stopped"; private static final String NOT_REGISTERED = "torrent not registered"; //bytemonsoon private static final String NOT_REGISTERED_2 = "torrent not found"; // diftracker - /** this is our equivalent to router.utorrent.com for bootstrap */ - private static final String DEFAULT_BACKUP_TRACKER = "http://tracker.welterde.i2p/a"; + private static final String NOT_REGISTERED_3 = "torrent unauthorised"; // vuze + private static final String ERROR_GOT_HTML = "received html"; // fake return private final static int SLEEP = 5; // 5 minutes. private final static int DELAY_MIN = 2000; // 2 secs. @@ -88,6 +90,8 @@ public class TrackerClient implements Runnable { private static final int DHT_ANNOUNCE_PEERS = 4; public static final int PORT = 6881; private static final int MAX_TRACKERS = 12; + // tracker.welterde.i2p + private static final Hash DSA_ONLY_TRACKER = ConvertToHash.getHash("cfmqlafjfmgkzbt4r3jsfyhgsr5abgxryl6fnz3d3y5a365di5aa.b32.i2p"); private final I2PSnarkUtil _util; private final MetaInfo meta; @@ -156,6 +160,7 @@ public class TrackerClient implements Runnable { consecutiveFails = 0; runStarted = false; _fastUnannounce = false; + snark.setTrackerProblems(null); _thread = new I2PAppThread(this, _threadName + " #" + (++_runCount), true); _thread.start(); started = true; @@ -342,7 +347,9 @@ public class TrackerClient implements Runnable { _log.debug("Backup announce: [" + url + "] for infoHash: " + infoHash); } if (backupTrackers.isEmpty()) { - backupTrackers.add(new TCTracker(DEFAULT_BACKUP_TRACKER, false)); + backupTrackers.add(new TCTracker(SnarkManager.DEFAULT_BACKUP_TRACKER, false)); + } else if (trackers.size() > 1) { + Collections.shuffle(backupTrackers, _util.getContext().random()); } } this.completed = coordinator.getLeft() == 0; @@ -360,12 +367,21 @@ public class TrackerClient implements Runnable { if (h == null) { if (_log.shouldLog(Log.WARN)) _log.warn("Bad announce URL: [" + ann + ']'); - return false; + return false; + } + // comment this out if tracker.welterde.i2p upgrades + if (h.equals(DSA_ONLY_TRACKER)) { + Destination dest = _util.getMyDestination(); + if (dest != null && dest.getSigType() != SigType.DSA_SHA1) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Skipping incompatible tracker: " + ann); + return false; + } } if (existing.size() >= MAX_TRACKERS) { if (_log.shouldLog(Log.INFO)) _log.info("Not using announce URL, we have enough: [" + ann + ']'); - return false; + return false; } boolean rv = existing.add(h); if (!rv) { @@ -526,9 +542,9 @@ public class TrackerClient implements Runnable { !snark.isChecking() && info.getSeedCount() > 100 && coordinator.getPeerCount() <= 0 && - _util.getContext().clock().now() > _startedOn + 2*60*60*1000 && + _util.getContext().clock().now() > _startedOn + 30*60*1000 && snark.getTotalLength() > 0 && - uploaded >= snark.getTotalLength() * 3 / 2) { + uploaded >= snark.getTotalLength() / 2) { if (_log.shouldLog(Log.WARN)) _log.warn("Auto stopping " + snark.getBaseName()); snark.setAutoStoppable(false); @@ -577,14 +593,20 @@ public class TrackerClient implements Runnable { if (tr.isPrimary) snark.setTrackerProblems(tr.trackerProblems); String tplc = tr.trackerProblems.toLowerCase(Locale.US); - if (tplc.startsWith(NOT_REGISTERED) || tplc.startsWith(NOT_REGISTERED_2)) { + if (tplc.startsWith(NOT_REGISTERED) || tplc.startsWith(NOT_REGISTERED_2) || + tplc.startsWith(NOT_REGISTERED_3) || tplc.startsWith(ERROR_GOT_HTML)) { // Give a guy some time to register it if using opentrackers too //if (trckrs.size() == 1) { // stop = true; // snark.stopTorrent(); //} else { // hopefully each on the opentrackers list is really open if (tr.registerFails++ > MAX_REGISTER_FAILS || + !completed || // no use retrying if we aren't seeding + tplc.startsWith(ERROR_GOT_HTML) || // fake msg from doRequest() (!tr.isPrimary && tr.registerFails > MAX_REGISTER_FAILS / 2)) + if (_log.shouldLog(Log.WARN)) + _log.warn("Not longer announcing to " + tr.announce + " : " + + tr.trackerProblems + " after " + tr.registerFails + " failures"); tr.stop = true; // } @@ -797,10 +819,15 @@ public class TrackerClient implements Runnable { tr.lastRequestTime = System.currentTimeMillis(); // Don't wait for a response to stopped when shutting down boolean fast = _fastUnannounce && event.equals(STOPPED_EVENT); - byte[] fetched = _util.get(s, true, fast ? -1 : 0, small ? 128 : 1024, small ? 1024 : 8*1024); - if (fetched == null) { - throw new IOException("Error fetching " + s); - } + byte[] fetched = _util.get(s, true, fast ? -1 : 0, small ? 128 : 1024, small ? 1024 : 32*1024); + if (fetched == null) + throw new IOException("Error fetching"); + if (fetched.length == 0) + throw new IOException("No data"); + // The HTML check only works if we didn't exceed the maxium fetch size specified in get(), + // otherwise we already threw an IOE. + if (fetched[0] == '<') + throw new IOException(ERROR_GOT_HTML); InputStream in = new ByteArrayInputStream(fetched); @@ -848,18 +875,20 @@ public class TrackerClient implements Runnable { } /** - * @param ann an announce URL + * @param ann an announce URL, may be null, returns false if null * @return true for i2p hosts only * @since 0.7.12 */ public static boolean isValidAnnounce(String ann) { - URL url; + if (ann == null) + return false; + URI url; try { - url = new URL(ann); - } catch (MalformedURLException mue) { - return false; + url = new URI(ann); + } catch (URISyntaxException use) { + return false; } - return url.getProtocol().equals("http") && + return "http".equals(url.getScheme()) && url.getHost() != null && (url.getHost().endsWith(".i2p") || url.getHost().equals("i2p")); } @@ -869,15 +898,17 @@ public class TrackerClient implements Runnable { * @since 0.9.5 */ private static Hash getHostHash(String ann) { - URL url; + URI url; try { - url = new URL(ann); - } catch (MalformedURLException mue) { + url = new URI(ann); + } catch (URISyntaxException use) { return null; } - if (!url.getProtocol().equals("http")) + if (!"http".equals(url.getScheme())) return null; String host = url.getHost(); + if (host == null) + return null; if (host.endsWith(".i2p")) return ConvertToHash.getHash(host); if (host.equals("i2p")) { @@ -885,7 +916,7 @@ public class TrackerClient implements Runnable { if (path == null || path.length() < 517 || !path.startsWith("/")) return null; - String[] parts = path.substring(1).split("/?&;", 2); + String[] parts = DataHelper.split(path.substring(1), "[/\\?&;]", 2); return ConvertToHash.getHash(parts[0]); } return null; diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerInfo.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerInfo.java index 0de45da06..9c39fa4d6 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerInfo.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerInfo.java @@ -196,6 +196,9 @@ class TrackerInfo return complete; } + /** + * Not HTML escaped. + */ public String getFailureReason() { return failure_reason; diff --git a/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java b/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java index 5812fb49c..4f9dff55a 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java +++ b/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java @@ -6,6 +6,7 @@ import java.util.List; import net.i2p.I2PAppContext; import net.i2p.crypto.TrustedUpdate; +import net.i2p.data.DataHelper; import net.i2p.update.*; import net.i2p.util.Log; import net.i2p.util.SimpleTimer2; @@ -109,7 +110,7 @@ class UpdateRunner implements UpdateTask, CompleteListener { _umgr.notifyAttemptFailed(this, "No tracker, no DHT, no OT", null); continue; } - _snark = _smgr.addMagnet(name, ih, trackerURL, true, true, this); + _snark = _smgr.addMagnet(name, ih, trackerURL, true, true, null, this); if (_snark != null) { updateStatus("" + _smgr.util().getString("Updating from {0}", linkify(updateURL)) + ""); new Timeout(); @@ -290,12 +291,21 @@ class UpdateRunner implements UpdateTask, CompleteListener { return _smgr.getSavedTorrentBitField(snark); } + public boolean getSavedPreserveNamesSetting(Snark snark) { + return _smgr.getSavedPreserveNamesSetting(snark); + } + + public long getSavedUploaded(Snark snark) { + return _smgr.getSavedUploaded(snark); + } + //////// end CompleteListener methods private static String linkify(String url) { - String durl = url.length() <= 28 ? url : - url.substring(0, 25) + "…"; - return "" + durl + ""; + String durl = url.length() <= 28 ? DataHelper.escapeHTML(url) : + DataHelper.escapeHTML(url.substring(0, 25)) + "…"; + // TODO urlEncode instead + return "" + durl + ""; } private void updateStatus(String s) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/bencode/BEValue.java b/apps/i2psnark/java/src/org/klomp/snark/bencode/BEValue.java index 0664065fb..4fd943c89 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/bencode/BEValue.java +++ b/apps/i2psnark/java/src/org/klomp/snark/bencode/BEValue.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import net.i2p.data.Base64; +import net.i2p.data.DataHelper; /** * Holds different types that a bencoded byte array can represent. @@ -208,7 +209,7 @@ public class BEValue } else if (bin) { buf.append(bs.length).append(" bytes: ").append(Base64.encode(bs)); } else { - buf.append('"').append(new String(bs)).append('"'); + buf.append('"').append(DataHelper.getUTF8(bs)).append('"'); } valueString = buf.toString(); } else diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTTracker.java b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTTracker.java index 3b7b1d99c..784d8e6bf 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTTracker.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTTracker.java @@ -106,6 +106,7 @@ class DHTTracker { * @param noSeeds true if we do not want seeds in the result * @return list or empty list (never null) */ + @SuppressWarnings({"unchecked", "rawtypes"}) List getPeers(InfoHash ih, int max, boolean noSeeds) { Peers peers = _torrents.get(ih); if (peers == null || max <= 0) diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java index 50c3a0a00..27325ee6f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java @@ -40,6 +40,8 @@ import net.i2p.util.I2PAppThread; import net.i2p.util.Log; import net.i2p.util.SimpleTimer2; +import org.klomp.snark.I2PSnarkUtil; +import org.klomp.snark.SnarkManager; import org.klomp.snark.TrackerClient; import org.klomp.snark.bencode.BDecoder; import org.klomp.snark.bencode.BEncoder; @@ -127,8 +129,10 @@ public class KRPC implements I2PSessionMuxedListener, DHT { /** Max number of nodes to return. BEP 5 says 8 */ private static final int K = 8; - /** Max number of peers to return. BEP 5 doesn't say. We'll use the same as I2PSnarkUtil.MAX_CONNECTIONS */ - private static final int MAX_WANT = 16; + /** Max number of peers to return. BEP 5 doesn't say. + * We'll use more than I2PSnarkUtil.MAX_CONNECTIONS since lots could be old. + */ + private static final int MAX_WANT = I2PSnarkUtil.MAX_CONNECTIONS * 3 / 2; /** overloads error codes which start with 201 */ private static final int REPLY_NONE = 0; @@ -152,7 +156,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { private static final long CLEAN_TIME = 63*1000; private static final long EXPLORE_TIME = 877*1000; private static final long BLACKLIST_CLEAN_TIME = 17*60*1000; - private static final String DHT_FILE_SUFFIX = ".dht.dat"; + public static final String DHT_FILE_SUFFIX = ".dht.dat"; private static final int SEND_CRYPTO_TAGS = 8; private static final int LOW_CRYPTO_TAGS = 4; @@ -185,8 +189,14 @@ public class KRPC implements I2PSessionMuxedListener, DHT { _myNID = new NID(_myID); } _myNodeInfo = new NodeInfo(_myNID, session.getMyDestination(), _qPort); - _dhtFile = new File(ctx.getConfigDir(), baseName + DHT_FILE_SUFFIX); - _backupDhtFile = baseName.equals("i2psnark") ? null : new File(ctx.getConfigDir(), "i2psnark" + DHT_FILE_SUFFIX); + File conf = new File(ctx.getConfigDir(), baseName + ".config" + SnarkManager.CONFIG_DIR_SUFFIX); + _dhtFile = new File(conf, "i2psnark" + DHT_FILE_SUFFIX); + if (baseName.equals("i2psnark")) { + _backupDhtFile = null; + } else { + File bconf = new File(ctx.getConfigDir(), "i2psnark.config" + SnarkManager.CONFIG_DIR_SUFFIX); + _backupDhtFile = new File(bconf, "i2psnark" + DHT_FILE_SUFFIX); + } _knownNodes = new DHTNodes(ctx, _myNID); start(); @@ -236,6 +246,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { * @param maxWait how long to wait for each to reply (not total) must be > 0 * @param parallel how many outstanding at once (unimplemented, always 1) */ + @SuppressWarnings("unchecked") private void explore(NID target, int maxNodes, long maxWait, int parallel) { List nodes = _knownNodes.findClosest(target, maxNodes); if (nodes.isEmpty()) { @@ -320,6 +331,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { * @param noSeeds true if we do not want seeds in the result * @return possibly empty (never null) */ + @SuppressWarnings("unchecked") public Collection getPeersAndAnnounce(byte[] ih, int max, long maxWait, int annMax, long annMaxWait, boolean isSeed, boolean noSeeds) { @@ -835,7 +847,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { if (_log.shouldLog(Log.INFO)) _log.info("Sending error " + msg + " to: " + nInfo); Map map = new HashMap(4); - List error = new ArrayList(2); + List error = new ArrayList(2); error.add(Integer.valueOf(err)); error.add(msg); map.put("e", error); @@ -851,6 +863,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { * @param repliable true for all but announce * @return null on error */ + @SuppressWarnings("unchecked") private ReplyWaiter sendQuery(NodeInfo nInfo, Map map, boolean repliable) { if (nInfo.equals(_myNodeInfo)) throw new IllegalArgumentException("wtf don't send to ourselves"); @@ -900,6 +913,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { * @param toPort the query port, we will increment here * @return success */ + @SuppressWarnings("unchecked") private boolean sendResponse(NodeInfo nInfo, MsgID msgID, Map map) { if (nInfo.equals(_myNodeInfo)) throw new IllegalArgumentException("wtf don't send to ourselves"); @@ -1287,7 +1301,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { } else { List hashes; if (peers.isEmpty()) { - hashes = Collections.EMPTY_LIST; + hashes = Collections.emptyList(); } else { hashes = new ArrayList(peers.size()); for (Hash peer : peers) { @@ -1401,7 +1415,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT { private List receivePeers(NodeInfo nInfo, List peers) throws InvalidBEncodingException { if (_log.shouldLog(Log.INFO)) _log.info("Rcvd peers from: " + nInfo); - int max = Math.min(MAX_WANT, peers.size()); + int max = Math.min(MAX_WANT * 2, peers.size()); List rv = new ArrayList(max); for (BEValue bev : peers) { byte[] b = bev.getBytes(); diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/NodeInfo.java b/apps/i2psnark/java/src/org/klomp/snark/dht/NodeInfo.java index c6fce8f14..708d2d276 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/NodeInfo.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/NodeInfo.java @@ -102,7 +102,7 @@ class NodeInfo extends SimpleDataStructure { */ public NodeInfo(String s) throws DataFormatException { super(); - String[] parts = s.split(":", 4); + String[] parts = DataHelper.split(s, ":", 4); if (parts.length != 4) throw new DataFormatException("Bad format"); byte[] nid = Base64.decode(parts[0]); @@ -225,7 +225,7 @@ class NodeInfo extends SimpleDataStructure { NodeInfo ni = (NodeInfo) o; // assume dest matches, ignore it return this.hash.equals(ni.hash) && nID.equals(ni.nID) && port == ni.port; - } catch (Exception e) { + } catch (RuntimeException e) { return false; } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/PersistDHT.java b/apps/i2psnark/java/src/org/klomp/snark/dht/PersistDHT.java index 8ecd111ef..2848b0090 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/PersistDHT.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/PersistDHT.java @@ -87,6 +87,8 @@ abstract class PersistDHT { out.println(ni.toPersistentString()); count++; } + if (out.checkError()) + throw new IOException("Failed write to " + file); } catch (IOException ioe) { if (log.shouldLog(Log.WARN)) log.warn("Error writing the DHT File", ioe); diff --git a/apps/i2psnark/java/src/org/klomp/snark/package.html b/apps/i2psnark/java/src/org/klomp/snark/package.html new file mode 100644 index 000000000..a617ebef6 --- /dev/null +++ b/apps/i2psnark/java/src/org/klomp/snark/package.html @@ -0,0 +1,8 @@ + + +

+I2P version of the snark bittorrent client, imported in 2005 and heavily enhanced +to add a web UI, DHT support, and other features. +

+ + diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java index 53a501af3..95e012b49 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java @@ -181,11 +181,10 @@ class BasicServlet extends HttpServlet HttpContent r = null; if (_warBase != null && pathInContext.startsWith(_warBase)) { r = new JarContent(pathInContext); - } else if (!pathInContext.contains("..") && - !pathInContext.endsWith("/")) { - File f = new File(_resourceBase, pathInContext); + } else { + File f = getResource(pathInContext); // exists && !directory - if (f.isFile()) + if (f != null && f.isFile()) r = new FileContent(f); } return r; @@ -283,7 +282,12 @@ class BasicServlet extends HttpServlet { if (content.getLastModified()/1000 <= ifmsl/1000) { - response.reset(); + try { + response.reset(); + } catch (IllegalStateException ise) { + // committed + return true; + } response.setStatus(304); response.flushBuffer(); return false; @@ -354,6 +358,7 @@ class BasicServlet extends HttpServlet writeHeaders(response, content, content_length); response.setStatus(416); response.setHeader("Content-Range", InclusiveByteRange.to416HeaderRangeString(content_length)); + in.close(); return; } @@ -555,14 +560,17 @@ class BasicServlet extends HttpServlet /** * Simple version of URIUtil.encodePath() */ - protected static String encodePath(String path) throws MalformedURLException { - try { - URI uri = new URI(null, null, path, null); - return uri.toString(); - } catch (URISyntaxException use) { - // for ease of use, since a USE is not an IOE but a MUE is... - throw new MalformedURLException(use.getMessage()); - } + protected static String encodePath(String path) /* throws MalformedURLException */ { + // Does NOT handle a ':' correctly, throws MUE. + // Can't convert to %3a before hand or the % gets escaped + //try { + // URI uri = new URI(null, null, path, null); + // return uri.toString(); + //} catch (URISyntaxException use) { + // // for ease of use, since a USE is not an IOE but a MUE is... + // throw new MalformedURLException(use.getMessage()); + //} + return URIUtil.encodePath(path); } /** diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/FetchAndAdd.java b/apps/i2psnark/java/src/org/klomp/snark/web/FetchAndAdd.java index 1a1d2b2d2..5537b33f1 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/FetchAndAdd.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/FetchAndAdd.java @@ -50,6 +50,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl private final String _url; private final byte[] _fakeHash; private final String _name; + private final File _dataDir; private volatile long _remaining = -1; private volatile long _total = -1; private volatile long _transferred; @@ -65,8 +66,10 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl /** * Caller should call _mgr.addDownloader(this), which * will start things off. + * + * @param dataDir null to default to snark data directory */ - public FetchAndAdd(I2PAppContext ctx, SnarkManager mgr, String url) { + public FetchAndAdd(I2PAppContext ctx, SnarkManager mgr, String url, File dataDir) { // magnet constructor super(mgr.util(), "Torrent download", null, null, null, null, null, false, null); @@ -74,7 +77,8 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl _log = ctx.logManager().getLog(FetchAndAdd.class); _mgr = mgr; _url = url; - _name = _("Download torrent file from {0}", url); + _name = _t("Download torrent file from {0}", url); + _dataDir = dataDir; byte[] fake = null; try { fake = SHA1.getInstance().digest(url.getBytes("ISO-8859-1")); @@ -86,7 +90,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl * Set off by startTorrent() */ public void run() { - _mgr.addMessage(_("Fetching {0}", urlify(_url))); + _mgr.addMessageNoEscape(_t("Fetching {0}", urlify(_url))); File file = get(); if (!_isRunning) // stopped? return; @@ -96,7 +100,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl _mgr.deleteMagnet(this); add(file); } else { - _mgr.addMessage(_("Torrent was not retrieved from {0}", urlify(_url)) + + _mgr.addMessageNoEscape(_t("Torrent was not retrieved from {0}", urlify(_url)) + ((_failCause != null) ? (": " + DataHelper.stripHTML(_failCause)) : "")); } if (file != null) @@ -123,7 +127,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl out.deleteOnExit(); if (!_mgr.util().connected()) { - _mgr.addMessage(_("Opening the I2P tunnel")); + _mgr.addMessage(_t("Opening the I2P tunnel")); if (!_mgr.util().connect()) return null; } @@ -150,7 +154,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl * This Snark may then be deleted. */ private void add(File file) { - _mgr.addMessage(_("Torrent fetched from {0}", urlify(_url))); + _mgr.addMessageNoEscape(_t("Torrent fetched from {0}", urlify(_url))); FileInputStream in = null; try { in = new FileInputStream(file); @@ -159,7 +163,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl try { in.close(); } catch (IOException ioe) {} Snark snark = _mgr.getTorrentByInfoHash(fileInfoHash); if (snark != null) { - _mgr.addMessage(_("Torrent with this info hash is already running: {0}", snark.getBaseName())); + _mgr.addMessage(_t("Torrent with this info hash is already running: {0}", snark.getBaseName())); return; } @@ -171,12 +175,12 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl if (torrentFile.exists()) { if (_mgr.getTorrent(canonical) != null) - _mgr.addMessage(_("Torrent already running: {0}", name)); + _mgr.addMessage(_t("Torrent already running: {0}", name)); else - _mgr.addMessage(_("Torrent already in the queue: {0}", name)); + _mgr.addMessage(_t("Torrent already in the queue: {0}", name)); } else { // This may take a LONG time to create the storage. - _mgr.copyAndAddTorrent(file, canonical); + _mgr.copyAndAddTorrent(file, canonical, _dataDir); snark = _mgr.getTorrentByBaseName(originalName); if (snark != null) snark.startTorrent(); @@ -184,9 +188,9 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl throw new IOException("Unknown error - check logs"); } } catch (IOException ioe) { - _mgr.addMessage(_("Torrent at {0} was not valid", urlify(_url)) + ": " + ioe.getMessage()); + _mgr.addMessageNoEscape(_t("Torrent at {0} was not valid", urlify(_url)) + ": " + DataHelper.stripHTML(ioe.getMessage())); } catch (OutOfMemoryError oom) { - _mgr.addMessage(_("ERROR - Out of memory, cannot create torrent from {0}", urlify(_url)) + ": " + oom.getMessage()); + _mgr.addMessageNoEscape(_t("ERROR - Out of memory, cannot create torrent from {0}", urlify(_url)) + ": " + DataHelper.stripHTML(oom.getMessage())); } finally { try { if (in != null) in.close(); } catch (IOException ioe) {} } @@ -341,11 +345,11 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl // End of EepGet status listeners - private String _(String s) { + private String _t(String s) { return _mgr.util().getString(s); } - private String _(String s, String o) { + private String _t(String s, String o) { return _mgr.util().getString(s, o); } diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index db5ec397f..754ea8148 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -9,6 +9,7 @@ import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -18,16 +19,20 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; -import java.util.TreeSet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import net.i2p.data.Base32; import net.i2p.data.Base64; import net.i2p.data.DataHelper; +import net.i2p.data.Hash; import net.i2p.util.Log; +import net.i2p.util.SecureFile; +import net.i2p.util.SystemVersion; +import net.i2p.util.Translate; import org.klomp.snark.I2PSnarkUtil; import org.klomp.snark.MagnetURI; @@ -59,6 +64,8 @@ public class I2PSnarkServlet extends BasicServlet { private static final String DEFAULT_NAME = "i2psnark"; public static final String PROP_CONFIG_FILE = "i2psnark.configFile"; + private static final String WARBASE = "/.resources/"; + private static final char HELLIP = '\u2026'; public I2PSnarkServlet() { super(); @@ -73,6 +80,7 @@ public class I2PSnarkServlet extends BasicServlet { _nonce = _context.random().nextLong(); // limited protection against overwriting other config files or directories // in case you named your war "router.war" + // We don't handle bad characters in the context path. Don't do that. String configName = _contextName; if (!configName.equals(DEFAULT_NAME)) configName = DEFAULT_NAME + '_' + _contextName; @@ -84,7 +92,7 @@ public class I2PSnarkServlet extends BasicServlet { _manager.start(); loadMimeMap("org/klomp/snark/web/mime"); setResourceBase(_manager.getDataDir()); - setWarBase("/.icons/"); + setWarBase(WARBASE); } @Override @@ -95,17 +103,35 @@ public class I2PSnarkServlet extends BasicServlet { } /** - * We override this instead of passing a resource base to super(), because - * if a resource base is set, super.getResource() always uses that base, - * and we can't get any resources (like icons) out of the .war + * We override this to set the file relative to the storage dirctory + * for the torrent. + * + * @param pathInContext should always start with / */ @Override public File getResource(String pathInContext) { if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") || - pathInContext.equals("/index.html") || pathInContext.startsWith("/.icons/")) + !pathInContext.startsWith("/") || pathInContext.length() == 0 || + pathInContext.equals("/index.html") || pathInContext.startsWith(WARBASE)) return super.getResource(pathInContext); // files in the i2psnark/ directory + // get top level + pathInContext = pathInContext.substring(1); + File top = new File(pathInContext); + File parent; + while ((parent = top.getParentFile()) != null) { + top = parent; + } + Snark snark = _manager.getTorrentByBaseName(top.getPath()); + if (snark != null) { + Storage storage = snark.getStorage(); + if (storage != null) { + File sbase = storage.getBase(); + String child = pathInContext.substring(top.getPath().length()); + return new File(sbase, child); + } + } return new File(_resourceBase, pathInContext); } @@ -154,32 +180,28 @@ public class I2PSnarkServlet extends BasicServlet { // _log.debug("Service " + req.getMethod() + " \"" + req.getContextPath() + "\" \"" + req.getServletPath() + "\" \"" + req.getPathInfo() + '"'); // since we are not overriding handle*(), do this here String method = req.getMethod(); - _themePath = "/themes/snark/" + _manager.getTheme() + '/'; - _imgPath = _themePath + "images/"; // this is the part after /i2psnark String path = req.getServletPath(); - resp.setHeader("X-Frame-Options", "SAMEORIGIN"); - String peerParam = req.getParameter("p"); - String stParam = req.getParameter("st"); - String peerString; - if (peerParam == null || (!_manager.util().connected()) || - peerParam.replaceAll("[a-zA-Z0-9~=-]", "").length() > 0) { // XSS - peerString = ""; - } else { - peerString = "?p=" + peerParam; - } - if (stParam != null && !stParam.equals("0")) { - if (peerString.length() > 0) - peerString += "&st=" + stParam; - else - peerString = "?st="+ stParam; + // in-war icons etc. + if (path != null && path.startsWith(WARBASE)) { + if (method.equals("GET") || method.equals("HEAD")) + super.doGet(req, resp); + else // no POST either + resp.sendError(405); + return; } + _themePath = "/themes/snark/" + _manager.getTheme() + '/'; + _imgPath = _themePath + "images/"; + req.setCharacterEncoding("UTF-8"); + + String pOverride = _manager.util().connected() ? null : ""; + String peerString = getQueryString(req, pOverride, null, null); + // AJAX for mainsection if ("/.ajax/xhr1.html".equals(path)) { - resp.setCharacterEncoding("UTF-8"); - resp.setContentType("text/html; charset=UTF-8"); + setHTMLHeaders(resp); PrintWriter out = resp.getWriter(); //if (_log.shouldLog(Log.DEBUG)) // _manager.addMessage((_context.clock().now() / 1000) + " xhr1 p=" + req.getParameter("p")); @@ -190,25 +212,25 @@ public class I2PSnarkServlet extends BasicServlet { boolean isConfigure = "/configure".equals(path); // index.jsp doesn't work, it is grabbed by the war handler before here - if (!(path == null || path.equals("/") || path.equals("/index.jsp") || path.equals("/index.html") || path.equals("/_post") || isConfigure)) { + if (!(path == null || path.equals("/") || path.equals("/index.jsp") || + path.equals("/index.html") || path.equals("/_post") || isConfigure)) { if (path.endsWith("/")) { // Listing of a torrent (torrent detail page) // bypass the horrid Resource.getListHTML() String pathInfo = req.getPathInfo(); String pathInContext = addPaths(path, pathInfo); - req.setCharacterEncoding("UTF-8"); - resp.setCharacterEncoding("UTF-8"); - resp.setContentType("text/html; charset=UTF-8"); File resource = getResource(pathInContext); if (resource == null) { resp.sendError(404); } else { String base = addPaths(req.getRequestURI(), "/"); - String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null); + String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null, + req.getParameter("sort")); if (method.equals("POST")) { // P-R-G sendRedirect(req, resp, ""); } else if (listing != null) { + setHTMLHeaders(resp); resp.getWriter().write(listing); } else { // shouldn't happen resp.sendError(404); @@ -228,10 +250,6 @@ public class I2PSnarkServlet extends BasicServlet { // Either the main page or /configure - req.setCharacterEncoding("UTF-8"); - resp.setCharacterEncoding("UTF-8"); - resp.setContentType("text/html; charset=UTF-8"); - String nonce = req.getParameter("nonce"); if (nonce != null) { if (nonce.equals(String.valueOf(_nonce))) @@ -243,19 +261,21 @@ public class I2PSnarkServlet extends BasicServlet { return; } + setHTMLHeaders(resp); PrintWriter out = resp.getWriter(); out.write(DOCTYPE + "\n" + "\n" + ""); if (_contextName.equals(DEFAULT_NAME)) - out.write(_("I2PSnark")); + out.write(_t("I2PSnark")); else out.write(_contextName); out.write(" - "); if (isConfigure) - out.write(_("Configuration")); + out.write(_t("Configuration")); else - out.write(_("Anonymous BitTorrent Client")); + out.write(_t("Anonymous BitTorrent Client")); + String peerParam = req.getParameter("p"); if ("2".equals(peerParam)) out.write(" | Debug Mode"); out.write("\n"); @@ -268,7 +288,7 @@ public class I2PSnarkServlet extends BasicServlet { //out.write("\n"); out.write("\n" + "\n"); + buf.append("\n
\n"); if (parent) // always true buf.append("
"); - boolean showPriority = ls != null && snark != null && snark.getStorage() != null && !snark.getStorage().complete(); - if (showPriority) + // for stop/start/check + if (showStopStart || showPriority) { buf.append("
\n"); + buf.append("\n"); + if (sortParam != null) { + buf.append("\n"); + } + } if (snark != null) { // first table - torrent info buf.append("\n"); - buf.append("\n"); String fullPath = snark.getName(); - String baseName = urlEncode((new File(fullPath)).getName()); - buf.append("\n"); + if (snark.getStorage() != null) { + buf.append("\n"); + } + String hex = I2PSnarkUtil.toHex(snark.getInfoHash()); + buf.append("\n"); String announce = null; MetaInfo meta = snark.getMetaInfo(); @@ -2337,17 +2760,19 @@ public class I2PSnarkServlet extends BasicServlet { buf.append(""); } List> alist = meta.getAnnounceList(); - if (alist != null) { - buf.append(""); + buf.append("\n"); } } if (meta != null) { String com = meta.getComment(); - if (com != null) { + if (com != null && com.length() > 0) { if (com.length() > 1024) com = com.substring(0, 1024); - buf.append("\n"); } long dat = meta.getCreationDate(); + SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + fmt.setTimeZone(SystemVersion.getSystemTimeZone(_context)); if (dat > 0) { - String date = (new SimpleDateFormat("yyyy-MM-dd HH:mm")).format(new Date(dat)); - buf.append("\n"); } String cby = meta.getCreatedBy(); - if (cby != null) { + if (cby != null && cby.length() > 0) { if (cby.length() > 128) cby = com.substring(0, 128); - buf.append("\n"); } + long[] dates = _manager.getSavedAddedAndCompleted(snark); + if (dates[0] > 0) { + String date = fmt.format(new Date(dates[0])); + buf.append("\n"); + } + if (dates[1] > 0) { + String date = fmt.format(new Date(dates[1])); + buf.append("\n"); + } } - String hex = I2PSnarkUtil.toHex(snark.getInfoHash()); if (meta == null || !meta.isPrivate()) { buf.append("\n"); } else { - buf.append("\n"); } // We don't have the hash of the torrent file - //buf.append(""); - buf.append("\n"); + + // buttons + if (showStopStart) { + buf.append("\n"); + } } else { + // snark == null // shouldn't happen buf.append("\n"); } buf.append("
") - .append(_("Torrent")) + buf.append("
") + .append(_t("Torrent")) .append(": ") - .append(snark.getBaseName()) + .append(DataHelper.escapeHTML(snark.getBaseName())) .append("
") - .append("\"\" ") - .append(_("Torrent file")) + String baseName = encodePath((new File(fullPath)).getName()); + buf.append("
"); + toThemeImg(buf, "file"); + buf.append("") + .append(_t("Torrent file")) .append(": ") - .append(fullPath) + .append(DataHelper.escapeHTML(fullPath)) .append("
"); + toThemeImg(buf, "file"); + buf.append("") + .append(_t("Data location")) + .append(": ") + .append(DataHelper.escapeHTML(snark.getStorage().getBase().getPath())) + .append("
"); + toThemeImg(buf, "details"); + buf.append("") + .append(_t("Info hash")) + .append(": ") + .append(hex.toUpperCase(Locale.US)) + .append("
"); String trackerLink = getTrackerLink(announce, snark.getInfoHash()); if (trackerLink != null) - buf.append(trackerLink).append(' '); - buf.append("").append(_("Primary Tracker")).append(": "); + buf.append(trackerLink); + else + toThemeImg(buf, "details"); + buf.append("").append(_t("Primary Tracker")).append(": "); buf.append(getShortTrackerLink(announce, snark.getInfoHash())); buf.append("
" + - "\"\" "); - buf.append(_("Tracker List")).append(": "); + if (alist != null && !alist.isEmpty()) { + buf.append("
"); + toThemeImg(buf, "details"); + buf.append("") + .append(_t("Tracker List")).append(": "); for (List alist2 : alist) { buf.append('['); boolean more = false; @@ -2360,51 +2785,74 @@ public class I2PSnarkServlet extends BasicServlet { } buf.append("] "); } - buf.append("
\"\" ") - .append(_("Comment")).append(": ") + buf.append("
"); + toThemeImg(buf, "details"); + buf.append("") + .append(_t("Comment")).append(": ") .append(DataHelper.stripHTML(com)) .append("
\"\" ") - .append(_("Created")).append(": ") - .append(date).append(" UTC") + String date = fmt.format(new Date(dat)); + buf.append("
"); + toThemeImg(buf, "details"); + buf.append("") + .append(_t("Created")).append(": ") + .append(date) .append("
\"\" ") - .append(_("Created By")).append(": ") + buf.append("
"); + toThemeImg(buf, "details"); + buf.append("") + .append(_t("Created By")).append(": ") .append(DataHelper.stripHTML(cby)) .append("
"); + toThemeImg(buf, "details"); + buf.append("") + .append(_t("Added")).append(": ") + .append(date) + .append("
"); + toThemeImg(buf, "details"); + buf.append("") + .append(_t("Completed")).append(": ") + .append(date) + .append("
") - .append(toImg("magnet", _("Magnet link"))) - .append(" Magnet: Magnet: ") .append("
") - .append(_("Private torrent")) + buf.append("
"); + toThemeImg(buf, "details"); + buf.append("") + .append(_t("Private torrent")) .append("
").append(_("Maggot link")).append(": ") + //buf.append("
").append(_t("Maggot link")).append(": ") // .append(MAGGOT).append(hex).append(':').append(hex).append("
") - .append("\"\" ") - .append(_("Size")) + buf.append("
"); + toThemeImg(buf, "size"); + buf.append("") + .append(_t("Size")) .append(": ") .append(formatSize(snark.getTotalLength())); int pieces = snark.getPieces(); double completion = (pieces - snark.getNeeded()) / (double) pieces; + buf.append(" "); + toThemeImg(buf, "head_rx"); + buf.append(" "); if (completion < 1.0) - buf.append(" \"\" ") - .append(_("Completion")) + buf.append(_t("Completion")) .append(": ") .append((new DecimalFormat("0.00%")).format(completion)); else - buf.append(" \"\" ") - .append(_("Complete")); - // else unknown + buf.append(_t("Complete")).append(""); + // up ratio + buf.append(" "); + toThemeImg(buf, "head_tx"); + buf.append(" ") + .append(_t("Upload ratio")) + .append(": "); + long uploaded = snark.getUploaded(); + if (uploaded > 0) { + double ratio = uploaded / ((double) snark.getTotalLength()); + buf.append((new DecimalFormat("0.000")).format(ratio)); + buf.append(" x"); + } else { + buf.append('0'); + } + // not including skipped files, but -1 when not running long needed = snark.getNeededLength(); - if (needed > 0) - buf.append(" \"\" ") - .append(_("Remaining")) + if (needed < 0) { + // including skipped files, valid when not running + needed = snark.getRemainingLength(); + } + if (needed > 0) { + buf.append(" "); + toThemeImg(buf, "head_rx"); + buf.append(" ") + .append(_t("Remaining")) .append(": ") .append(formatSize(needed)); + } + long skipped = snark.getSkippedLength(); + if (skipped > 0) { + buf.append(" "); + toThemeImg(buf, "head_rx"); + buf.append(" ") + .append(_t("Skipped")) + .append(": ") + .append(formatSize(skipped)); + } if (meta != null) { List> files = meta.getFiles(); int fileCount = files != null ? files.size() : 1; - buf.append(" \"\" ") - .append(_("Files")) + buf.append(" "); + toThemeImg(buf, "file"); + buf.append(" ") + .append(_t("Files")) .append(": ") .append(fileCount); } - buf.append(" \"\" ") - .append(_("Pieces")) + buf.append(" "); + toThemeImg(buf, "file"); + buf.append(" ") + .append(_t("Pieces")) .append(": ") .append(pieces); - buf.append(" \"\" ") - .append(_("Piece size")) + buf.append(" "); + toThemeImg(buf, "file"); + buf.append(" ") + .append(_t("Piece size")) .append(": ") .append(formatSize(snark.getPieceLength(0))) .append("
"); + if (snark.isChecking()) { + buf.append("").append(_t("Checking")).append("… ") + .append((new DecimalFormat("0.00%")).format(snark.getCheckingProgress())) + .append("   ") + .append(_t("Refresh page for results")).append(""); + } else if (snark.isStarting()) { + buf.append("").append(_t("Starting")).append("…"); + } else if (snark.isAllocating()) { + buf.append("").append(_t("Allocating")).append("…"); + } else { + boolean isRunning = !snark.isStopped(); + buf.append("\n"); + else + buf.append(_t("Start")).append("\" name=\"start\" class=\"starttorrent\">\n"); + buf.append("   \n"); + else + buf.append("\" class=\"reload\">\n"); + } + buf.append("
Not found
resource=\"").append(r.toString()) .append("\"
base=\"").append(base) @@ -2471,90 +2988,167 @@ public class I2PSnarkServlet extends BasicServlet { .append("\"
\n"); + + if (snark != null && !r.exists()) { + // fixup TODO + buf.append("

Does not exist
resource=\"").append(r.toString()) + .append("\"
base=\"").append(base) + .append("\"
torrent=\"").append(torrentName) + .append("\"

"); + return buf.toString(); + } + + File[] ls = null; + if (r.isDirectory()) { + ls = r.listFiles(); + } // if r is not a directory, we are only showing torrent info section + if (ls == null) { // We are only showing the torrent info section buf.append(""); return buf.toString(); } + Storage storage = snark != null ? snark.getStorage() : null; + List fileList = new ArrayList(ls.length); + // precompute remaining for all files for efficiency + long[] remainingArray = (storage != null) ? storage.remaining() : null; + for (int i = 0; i < ls.length; i++) { + fileList.add(new Sorters.FileAndIndex(ls[i], storage, remainingArray)); + } + + boolean showSort = fileList.size() > 1; + if (showSort) { + int sort = 0; + if (sortParam != null) { + try { + sort = Integer.parseInt(sortParam); + } catch (NumberFormatException nfe) {} + } + Collections.sort(fileList, Sorters.getFileComparator(sort, this)); + } + // second table - dir info buf.append("\n"); buf.append("\n") - .append("\n"); - buf.append("\n"); - buf.append("\n"); - if (showPriority) - buf.append("\n"); - buf.append("\n\n"); + .append("\n\n\n\n\n\n"); buf.append("\n"); //DateFormat dfmt=DateFormat.getDateTimeInstance(DateFormat.MEDIUM, // DateFormat.MEDIUM); boolean showSaveButton = false; - for (int i=0 ; i< ls.length ; i++) + boolean rowEven = true; + for (Sorters.FileAndIndex fai : fileList) { - String encoded = encodePath(ls[i].getName()); + //String encoded = encodePath(ls[i].getName()); // bugfix for I2P - Backport from Jetty 6 (zero file lengths and last-modified times) // http://jira.codehaus.org/browse/JETTY-361?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel#issue-tabs // See resource.diff attachment //Resource item = addPath(encoded); - File item = ls[i]; + File item = fai.file; - String rowClass = (i % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd"); + String rowClass = (rowEven ? "snarkTorrentEven" : "snarkTorrentOdd"); + rowEven = !rowEven; buf.append(""); // Get completeness and status string boolean complete = false; String status = ""; long length = item.length(); - if (item.isDirectory()) { + int fileIndex = fai.index; + int priority = 0; + if (fai.isDirectory) { complete = true; - //status = toImg("tick") + ' ' + _("Directory"); + //status = toImg("tick") + ' ' + _t("Directory"); } else { if (snark == null || snark.getStorage() == null) { // Assume complete, perhaps he removed a completed torrent but kept a bookmark complete = true; - status = toImg("cancel") + ' ' + _("Torrent not found?"); + status = toImg("cancel") + ' ' + _t("Torrent not found?"); } else { - Storage storage = snark.getStorage(); - try { - File f = item; - long remaining = storage.remaining(f.getCanonicalPath()); + + long remaining = fai.remaining; if (remaining < 0) { complete = true; - status = toImg("cancel") + ' ' + _("File not found in torrent?"); + status = toImg("cancel") + ' ' + _t("File not found in torrent?"); } else if (remaining == 0 || length <= 0) { complete = true; - status = toImg("tick") + ' ' + _("Complete"); + status = toImg("tick") + ' ' + _t("Complete"); } else { - int priority = storage.getPriority(f.getCanonicalPath()); + priority = fai.priority; if (priority < 0) status = toImg("cancel"); else if (priority == 0) @@ -2562,19 +3156,17 @@ public class I2PSnarkServlet extends BasicServlet { else status = toImg("clock_red"); status += " " + - (100 * (length - remaining) / length) + "% " + _("complete") + - " (" + DataHelper.formatSize2(remaining) + "B " + _("remaining") + ")"; + (100 * (length - remaining) / length) + "% " + _t("complete") + + " (" + DataHelper.formatSize2(remaining) + "B " + _t("remaining") + ")"; } - } catch (IOException ioe) { - status = "Not a file? " + ioe; - } + } } - String path=addPaths(base,encoded); + String path = addPaths(decodedBase, item.getName()); if (item.isDirectory() && !path.endsWith("/")) path=addPaths(path,"/"); - path = urlEncode(path); + path = encodePath(path); String icon = toIcon(item); buf.append(""); if (showPriority) { buf.append(""); @@ -2631,19 +3221,43 @@ public class I2PSnarkServlet extends BasicServlet { buf.append("\n"); } if (showSaveButton) { - buf.append("\n"); + buf.append("\n"); } buf.append("
") - .append("\"")") - .append("\"")") - .append("\"")") - .append("\"")
"); + String tx = _t("Directory"); + // cycle through sort by name or type + String sort; + boolean isTypeSort = false; + if (showSort) { + if (sortParam == null || "0".equals(sortParam) || "1".equals(sortParam)) { + sort = "-1"; + } else if ("-1".equals(sortParam)) { + sort = "12"; + isTypeSort = true; + } else if ("12".equals(sortParam)) { + sort = "-12"; + isTypeSort = true; + } else { + sort = ""; + } + buf.append(""); + } + toThemeImg(buf, "file", tx, + showSort ? _t("Sort by {0}", (isTypeSort ? _t("File type") : _t("Name"))) + : tx + ": " + directory); + if (showSort) + buf.append(""); + int dirSlash = directory.indexOf("/"); + if (dirSlash > 0) { + buf.append(" "); + buf.append(DataHelper.escapeHTML(directory.substring(dirSlash + 1))); + } + buf.append(""); + if (showSort) { + sort = ("5".equals(sortParam)) ? "-5" : "5"; + buf.append(""); + } + tx = _t("Size"); + toThemeImg(buf, "size", tx, + showSort ? _t("Sort by {0}", tx) : tx); + if (showSort) + buf.append(""); + buf.append(""); + boolean showRemainingSort = showSort && showPriority; + if (showRemainingSort) { + sort = ("10".equals(sortParam)) ? "-10" : "10"; + buf.append(""); + } + tx = _t("Status"); + toThemeImg(buf, "status", tx, + showRemainingSort ? _t("Sort by {0}", _t("Remaining")) : tx); + if (showRemainingSort) + buf.append(""); + if (showPriority) { + buf.append(""); + if (showSort) { + sort = ("13".equals(sortParam)) ? "-13" : "13"; + buf.append(""); + } + tx = _t("Priority"); + toThemeImg(buf, "priority", tx, + showSort ? _t("Sort by {0}", tx) : tx); + if (showSort) + buf.append(""); + } + buf.append("
\"\" ") - .append(_("Up to higher level directory")) + URIUtil.encodePath(buf, addPaths(decodedBase,"../")); + buf.append("\">"); + toThemeImg(buf, "up"); + buf.append(' ') + .append(_t("Up to higher level directory")) .append("
"); @@ -2587,7 +3179,7 @@ public class I2PSnarkServlet extends BasicServlet { buf.append("\"\""); } else { - buf.append(toImg(icon, _("Open"))).append(""); + buf.append(toImg(icon, _t("Open"))).append(""); } } else { buf.append(toImg(icon)); @@ -2595,7 +3187,7 @@ public class I2PSnarkServlet extends BasicServlet { buf.append(""); if (complete) buf.append(""); - buf.append(item.getName().replace("&", "&")); + buf.append(DataHelper.escapeHTML(item.getName())); if (complete) buf.append(""); buf.append(""); @@ -2607,23 +3199,21 @@ public class I2PSnarkServlet extends BasicServlet { buf.append(""); - File f = item; if ((!complete) && (!item.isDirectory())) { - int pri = snark.getStorage().getPriority(f.getCanonicalPath()); - buf.append(" 0) - buf.append("checked=\"true\""); - buf.append('>').append(_("High")); + buf.append("\n 0) + buf.append("checked=\"checked\""); + buf.append('>').append(_t("High")); - buf.append("').append(_("Normal")); + buf.append("\n').append(_t("Normal")); - buf.append("').append(_("Skip")); + buf.append("\n').append(_t("Skip")); showSaveButton = true; } buf.append("
 
 " + + "") + .append(toImg("clock_red")).append(_t("Set all high")).append("\n" + + "") + .append(toImg("clock")).append(_t("Set all normal")).append("\n" + + "") + .append(toImg("cancel")).append(_t("Skip all")).append("\n" + + "

\n" + + "
\n"); - if (showPriority) + // for stop/start/check + if (showStopStart || showPriority) buf.append(""); buf.append("\n"); return buf.toString(); } - /** @since 0.7.14 */ + /** + * @param so null ok + * @return query string or "" + * @since 0.9.16 + */ + private static String getQueryString(String so) { + if (so != null && !so.equals("")) + return "?sort=" + DataHelper.stripHTML(so); + return ""; + } + + /** + * Pick an icon; try to catch the common types in an i2p environment. + * + * @return file name not including ".png" + * @since 0.7.14 + */ private String toIcon(File item) { if (item.isDirectory()) return "folder"; @@ -2652,10 +3266,12 @@ public class I2PSnarkServlet extends BasicServlet { /** * Pick an icon; try to catch the common types in an i2p environment + * Pkg private for FileTypeSorter. + * * @return file name not including ".png" * @since 0.7.14 */ - private String toIcon(String path) { + String toIcon(String path) { String icon; // Note that for this to work well, our custom mime.properties file must be loaded. String plc = path.toLowerCase(Locale.US); @@ -2684,7 +3300,12 @@ public class I2PSnarkServlet extends BasicServlet { icon = "music"; else if (mime.startsWith("video/")) icon = "film"; - else if (mime.equals("application/zip") || mime.equals("application/x-gtar") || + else if (mime.equals("application/zip")) { + if (plc.endsWith(".su3") || plc.endsWith(".su2") || plc.endsWith(".sud")) + icon = "itoopie_xxsm"; + else + icon = "compress"; + } else if (mime.equals("application/x-gtar") || mime.equals("application/x-xz") || mime.equals("application/compress") || mime.equals("application/gzip") || mime.equals("application/x-7z-compressed") || mime.equals("application/x-rar-compressed") || mime.equals("application/x-tar") || mime.equals("application/x-bzip2")) @@ -2693,19 +3314,80 @@ public class I2PSnarkServlet extends BasicServlet { icon = "application"; else if (plc.endsWith(".iso")) icon = "cd"; + else if (mime.equals("application/x-bittorrent")) + icon = "magnet"; else icon = "page_white"; return icon; } - /** @since 0.7.14 */ + /** + * Icon file in the .war. Always 16x16. + * + * @param icon name without the ".png" + * @since 0.7.14 + */ private String toImg(String icon) { - return "\"\""; + return toImg(icon, ""); } - /** @since 0.8.2 */ + /** + * Icon file in the .war. Always 16x16. + * + * @param icon name without the ".png" + * @since 0.8.2 + */ private String toImg(String icon, String altText) { - return "\"""; + return "\"""; + } + + /** + * Image file in the theme. + * + * @param image name without the ".png" + * @since 0.9.16 + */ + private String toThemeImg(String image) { + return toThemeImg(image, "", ""); + } + + /** + * Image file in the theme. + * + * @param image name without the ".png" + * @since 0.9.16 + */ + private void toThemeImg(StringBuilder buf, String image) { + toThemeImg(buf, image, "", ""); + } + + /** + * Image file in the theme. + * + * @param image name without the ".png" + * @param altText non-null + * @param titleText non-null + * @since 0.9.16 + */ + private String toThemeImg(String image, String altText, String titleText) { + StringBuilder buf = new StringBuilder(128); + toThemeImg(buf, image, altText, titleText); + return buf.toString(); + } + + /** + * Image file in the theme. + * + * @param image name without the ".png" + * @param altText non-null + * @param titleText non-null + * @since 0.9.16 + */ + private void toThemeImg(StringBuilder buf, String image, String altText, String titleText) { + buf.append("\"").append(altText).append("\" 0) + buf.append(" title=\"").append(titleText).append('"'); + buf.append('>'); } /** @since 0.8.1 */ @@ -2717,15 +3399,45 @@ public class I2PSnarkServlet extends BasicServlet { String key = entry.getKey(); if (key.startsWith("pri.")) { try { - String file = key.substring(4); + int fileIndex = Integer.parseInt(key.substring(4)); String val = entry.getValue()[0]; // jetty arrays int pri = Integer.parseInt(val); - storage.setPriority(file, pri); + storage.setPriority(fileIndex, pri); //System.err.println("Priority now " + pri + " for " + file); } catch (Throwable t) { t.printStackTrace(); } } } snark.updatePiecePriorities(); - _manager.saveTorrentStatus(snark.getMetaInfo(), storage.getBitField(), storage.getFilePriorities()); + _manager.saveTorrentStatus(snark); + } + + /** + * Is "a" equal to "b", + * or is "a" a directory and a parent of file or directory "b", + * canonically speaking? + * + * @since 0.9.15 + */ + private static boolean isParentOf(File a, File b) { + try { + a = a.getCanonicalFile(); + b = b.getCanonicalFile(); + } catch (IOException ioe) { + return false; + } + if (a.equals(b)) + return true; + if (!a.isDirectory()) + return false; + // easy case + if (!b.getPath().startsWith(a.getPath())) + return false; + // dir by dir + while (!a.equals(b)) { + b = b.getParentFile(); + if (b == null) + return false; + } + return true; } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/Sorters.java b/apps/i2psnark/java/src/org/klomp/snark/web/Sorters.java new file mode 100644 index 000000000..964e6d80d --- /dev/null +++ b/apps/i2psnark/java/src/org/klomp/snark/web/Sorters.java @@ -0,0 +1,643 @@ +package org.klomp.snark.web; + +import java.io.File; +import java.io.Serializable; +import java.text.Collator; +import java.util.Collections; +import java.util.Comparator; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.klomp.snark.MetaInfo; +import org.klomp.snark.Snark; +import org.klomp.snark.Storage; + +/** + * Comparators for various columns + * + * @since 0.9.16 from TorrentNameComparator, moved from I2PSnarkservlet + */ +class Sorters { + + /** + * See below + */ + private static final Pattern PATTERN_DE, PATTERN_EN, PATTERN_ES, PATTERN_FR, + PATTERN_IT, PATTERN_NL, PATTERN_PT; + private static Pattern _pattern; + + /** + * Negative is reverse + * + *
    + *
  • 0, 1: Name + *
  • 2: Status + *
  • 3: Peers + *
  • 4: ETA + *
  • 5: Size + *
  • 6: Downloaded + *
  • 7: Uploaded + *
  • 8: Down rate + *
  • 9: Up rate + *
  • 10: Remaining (needed) + *
  • 11: Upload ratio + *
  • 12: File type + *
+ * + * @param servlet for file type callback only + */ + public static Comparator getComparator(int type, I2PSnarkServlet servlet) { + boolean rev = type < 0; + Comparator rv; + switch (type) { + + case -1: + case 0: + case 1: + default: + rv = new TorrentNameComparator(); + if (rev) + rv = Collections.reverseOrder(rv); + break; + + case -2: + case 2: + rv = new StatusComparator(rev); + break; + + case -3: + case 3: + rv = new PeersComparator(rev); + break; + + case -4: + case 4: + rv = new ETAComparator(rev); + break; + + case -5: + case 5: + rv = new SizeComparator(rev); + break; + + case -6: + case 6: + rv = new DownloadedComparator(rev); + break; + + case -7: + case 7: + rv = new UploadedComparator(rev); + break; + + case -8: + case 8: + rv = new DownRateComparator(rev); + break; + + case -9: + case 9: + rv = new UpRateComparator(rev); + break; + + case -10: + case 10: + rv = new RemainingComparator(rev); + break; + + case -11: + case 11: + rv = new RatioComparator(rev); + break; + + case -12: + case 12: + rv = new FileTypeComparator(rev, servlet); + break; + + } + return rv; + } + + + /** + * Sort alphabetically in current locale, ignore case, ignore leading + * articles such as "the" if the pattern is set by setPattern() + * @since 0.7.14 + */ + private static class TorrentNameComparator implements Comparator, Serializable { + + public int compare(Snark l, Snark r) { + return comp(l, r); + } + + public static int comp(Snark l, Snark r) { + // put downloads and magnets first + if (l.getStorage() == null && r.getStorage() != null) + return -1; + if (l.getStorage() != null && r.getStorage() == null) + return 1; + String ls = l.getBaseName(); + String rs = r.getBaseName(); + Pattern p = _pattern; + if (p != null) { + Matcher m = p.matcher(ls); + if (m.matches()) + ls = ls.substring(m.group(1).length()); + m = p.matcher(rs); + if (m.matches()) + rs = rs.substring(m.group(1).length()); + } + return Collator.getInstance().compare(ls, rs); + } + } + + /** + * Forward or reverse sort, but the fallback is always forward + */ + private static abstract class Sort implements Comparator, Serializable { + + private final boolean _rev; + + public Sort(boolean rev) { + _rev = rev; + } + + public int compare(Snark l, Snark r) { + int rv = compareIt(l, r); + if (rv != 0) + return _rev ? 0 - rv : rv; + return TorrentNameComparator.comp(l, r); + } + + protected abstract int compareIt(Snark l, Snark r); + + protected static int compLong(long l, long r) { + if (l < r) + return -1; + if (l > r) + return 1; + return 0; + } + } + + + private static class StatusComparator extends Sort { + + private StatusComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + int rv = getStatus(l) - getStatus(r); + if (rv != 0) + return rv; + // use reverse remaining as first tie break + return compLong(r.getNeededLength(), l.getNeededLength()); + } + + private static int getStatus(Snark snark) { + long remaining = snark.getRemainingLength(); + if (snark.isStopped()) { + if (remaining < 0) + return 0; + if (remaining > 0) + return 5; + return 10; + } + if (snark.isStarting()) + return 15; + if (snark.isAllocating()) + return 20; + if (remaining < 0) + return 15; // magnet + if (remaining == 0) + return 100; + if (snark.isChecking()) + return 95; + if (snark.getNeededLength() <= 0) + return 90; + if (snark.getPeerCount() <= 0) + return 40; + if (snark.getDownloadRate() <= 0) + return 50; + return 60; + } + } + + private static class PeersComparator extends Sort { + + public PeersComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + return l.getPeerCount() - r.getPeerCount(); + } + } + + private static class RemainingComparator extends Sort { + + public RemainingComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + return compLong(l.getNeededLength(), r.getNeededLength()); + } + } + + private static class ETAComparator extends Sort { + + public ETAComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + return compLong(eta(l), eta(r)); + } + + private static long eta(Snark snark) { + long needed = snark.getNeededLength(); + if (needed <= 0) + return 0; + long total = snark.getTotalLength(); + if (needed > total) + needed = total; + long downBps = snark.getDownloadRate(); + if (downBps > 0) + return needed / downBps; + return Long.MAX_VALUE; + } + } + + private static class SizeComparator extends Sort { + + public SizeComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + return compLong(l.getTotalLength(), r.getTotalLength()); + } + } + + private static class DownloadedComparator extends Sort { + + public DownloadedComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + long ld = l.getTotalLength() - l.getRemainingLength(); + long rd = r.getTotalLength() - r.getRemainingLength(); + return compLong(ld, rd); + } + } + + private static class UploadedComparator extends Sort { + + public UploadedComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + return compLong(l.getUploaded(), r.getUploaded()); + } + } + + private static class DownRateComparator extends Sort { + + public DownRateComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + return compLong(l.getDownloadRate(), r.getDownloadRate()); + } + } + + private static class UpRateComparator extends Sort { + + public UpRateComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + return compLong(l.getUploadRate(), r.getUploadRate()); + } + } + + private static class RatioComparator extends Sort { + + private static final long M = 128 * 1024 * 1024; + + public RatioComparator(boolean rev) { super(rev); } + + public int compareIt(Snark l, Snark r) { + long lt = l.getTotalLength(); + long ld = lt > 0 ? ((M * l.getUploaded()) / lt) : 0; + long rt = r.getTotalLength(); + long rd = rt > 0 ? ((M * r.getUploaded()) / rt) : 0; + return compLong(ld, rd); + } + } + + private static class FileTypeComparator extends Sort { + + private final I2PSnarkServlet servlet; + + public FileTypeComparator(boolean rev, I2PSnarkServlet servlet) { + super(rev); + this.servlet = servlet; + } + + public int compareIt(Snark l, Snark r) { + String ls = toName(l); + String rs = toName(r); + return ls.compareTo(rs); + } + + private String toName(Snark snark) { + MetaInfo meta = snark.getMetaInfo(); + if (meta == null) + return "0"; + if (meta.getFiles() != null) + return "1"; + // arbitrary sort based on icon name + return servlet.toIcon(meta.getName()); + } + } + + ////////////// Comparators for details page below + + /** + * Class to precompute and efficiently sort data + * on a torrent file entry. + */ + public static class FileAndIndex { + public final File file; + public final boolean isDirectory; + public final long length; + public final long remaining; + public final int priority; + public final int index; + + /** + * @param storage may be null + * @param remainingArray precomputed, non-null iff storage is non-null + */ + public FileAndIndex(File file, Storage storage, long[] remainingArray) { + this.file = file; + index = storage != null ? storage.indexOf(file) : -1; + if (index >= 0) { + isDirectory = false; + remaining = remainingArray[index]; + priority = storage.getPriority(index); + } else { + isDirectory = file.isDirectory(); + remaining = -1; + priority = -999; + } + length = isDirectory ? 0 : file.length(); + } + } + + + /** + * Negative is reverse + * + *
    + *
  • 0, 1: Name + *
  • 5: Size + *
  • 10: Remaining (needed) + *
  • 12: File type + *
  • 13: Priority + *
+ * + * @param servlet for file type callback only + */ + public static Comparator getFileComparator(int type, I2PSnarkServlet servlet) { + boolean rev = type < 0; + Comparator rv; + + switch (type) { + + case -1: + case 0: + case 1: + default: + rv = new FileNameComparator(); + if (rev) + rv = Collections.reverseOrder(rv); + break; + + case -5: + case 5: + rv = new FAISizeComparator(rev); + break; + + case -10: + case 10: + rv = new FAIRemainingComparator(rev); + break; + + case -12: + case 12: + rv = new FAITypeComparator(rev, servlet); + break; + + case -13: + case 13: + rv = new FAIPriorityComparator(rev); + break; + + } + return rv; + } + + /** + * Sort alphabetically in current locale, ignore case, + * directories first + * @since 0.9.6 moved from I2PSnarkServlet in 0.9.16 + */ + private static class FileNameComparator implements Comparator, Serializable { + + public int compare(FileAndIndex l, FileAndIndex r) { + return comp(l, r); + } + + public static int comp(FileAndIndex l, FileAndIndex r) { + boolean ld = l.isDirectory; + boolean rd = r.isDirectory; + if (ld && !rd) + return -1; + if (rd && !ld) + return 1; + return Collator.getInstance().compare(l.file.getName(), r.file.getName()); + } + } + + /** + * Forward or reverse sort, but the fallback is always forward + */ + private static abstract class FAISort implements Comparator, Serializable { + + private final boolean _rev; + + public FAISort(boolean rev) { + _rev = rev; + } + + public int compare(FileAndIndex l, FileAndIndex r) { + int rv = compareIt(l, r); + if (rv != 0) + return _rev ? 0 - rv : rv; + return FileNameComparator.comp(l, r); + } + + protected abstract int compareIt(FileAndIndex l, FileAndIndex r); + + protected static int compLong(long l, long r) { + if (l < r) + return -1; + if (l > r) + return 1; + return 0; + } + } + + private static class FAIRemainingComparator extends FAISort { + + public FAIRemainingComparator(boolean rev) { super(rev); } + + public int compareIt(FileAndIndex l, FileAndIndex r) { + return compLong(l.remaining, r.remaining); + } + } + + private static class FAISizeComparator extends FAISort { + + public FAISizeComparator(boolean rev) { super(rev); } + + public int compareIt(FileAndIndex l, FileAndIndex r) { + return compLong(l.length, r.length); + } + } + + private static class FAITypeComparator extends FAISort { + + private final I2PSnarkServlet servlet; + + public FAITypeComparator(boolean rev, I2PSnarkServlet servlet) { + super(rev); + this.servlet = servlet; + } + + public int compareIt(FileAndIndex l, FileAndIndex r) { + String ls = toName(l); + String rs = toName(r); + return ls.compareTo(rs); + } + + private String toName(FileAndIndex fai) { + if (fai.isDirectory) + return "0"; + // arbitrary sort based on icon name + return servlet.toIcon(fai.file.getName()); + } + } + + private static class FAIPriorityComparator extends FAISort { + + public FAIPriorityComparator(boolean rev) { super(rev); } + + /** highest first */ + public int compareIt(FileAndIndex l, FileAndIndex r) { + return r.priority - l.priority; + } + } + + /* + * Match an indefinite or definite article in the language, + * followed by one or more whitespace, '.', or '_'. + * Does not match "partitive" articles. + * + * https://en.wikipedia.org/wiki/Article_%28grammar%29 + * http://www.loc.gov/marc/bibliographic/bdapndxf.html + */ + static { + PATTERN_DE = Pattern.compile( + // can't make the non-capturing innner group work + //"^((?:" + + "^((" + + "der|die|das|des|dem|den|ein|eine|einer|eines|einem|einen" + + ")[\\s\\._]+).*", + Pattern.CASE_INSENSITIVE); + PATTERN_EN = Pattern.compile( + "^((" + + "a|an|the" + + ")[\\s\\._]+).*", + Pattern.CASE_INSENSITIVE); + PATTERN_ES = Pattern.compile( + "^((" + + "el|la|lo|los|las|un|una|unos|unas" + + ")[\\s\\._]+).*", + Pattern.CASE_INSENSITIVE); + PATTERN_FR = Pattern.compile( + // note l' doesn't require whitespace after + "^(l'|((" + + "le|la|les|un|une|des" + + ")[\\s\\._]+)).*", + Pattern.CASE_INSENSITIVE); + PATTERN_IT = Pattern.compile( + // note l' and un' don't require whitespace after + "^(l'|un'|((" + + "il|lo|la|i|gli|le|uno|una|un" + + ")[\\s\\._]+)).*", + Pattern.CASE_INSENSITIVE); + PATTERN_NL = Pattern.compile( + "^((" + + "de|het|het'n|een|een'n" + + ")[\\s\\._]+).*", + Pattern.CASE_INSENSITIVE); + PATTERN_PT = Pattern.compile( + "^((" + + "o|a|os|as|um|uma|uns|umas" + + ")[\\s\\._]+).*", + Pattern.CASE_INSENSITIVE); + } + + /** + * Sets static field, oh well + * @param lang null for none + * @since 0.9.23 + */ + public static void setPattern(String lang) { + Pattern p; + if (lang == null) + p = null; + else if (lang.equals("de")) + p = PATTERN_DE; + else if (lang.equals("en")) + p = PATTERN_EN; + else if (lang.equals("es")) + p = PATTERN_ES; + else if (lang.equals("fr")) + p = PATTERN_FR; + else if (lang.equals("it")) + p = PATTERN_IT; + else if (lang.equals("nl")) + p = PATTERN_NL; + else if (lang.equals("pt")) + p = PATTERN_PT; + else + p = null; + _pattern = p; + } + +/**** + public static final void main(String[] args) { + if (args.length != 2) { + System.out.println("Usage: Sorters lang 'string'"); + System.exit(1); + } + String lang = args[0]; + setPattern(lang); + if (_pattern == null) { + System.out.println("Unsupported " + lang); + System.exit(1); + } + String s = args[1]; + Matcher m = _pattern.matcher(s); + if (m.matches()) { + System.out.println("Match is \"" + m.group(1) + '"'); + } else { + System.out.println("No match for \"" + s + '"'); + } + } +****/ +} diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/URIUtil.java b/apps/i2psnark/java/src/org/klomp/snark/web/URIUtil.java new file mode 100644 index 000000000..858b9aec8 --- /dev/null +++ b/apps/i2psnark/java/src/org/klomp/snark/web/URIUtil.java @@ -0,0 +1,250 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.klomp.snark.web; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; + +import net.i2p.data.DataHelper; + + +/** URI Holder. + * This class assists with the decoding and encoding or HTTP URI's. + * It differs from the java.net.URL class as it does not provide + * communications ability, but it does assist with query string + * formatting. + *

UTF-8 encoding is used by default for % encoded characters. This + * may be overridden with the org.eclipse.jetty.util.URI.charset system property. + * see UrlEncoded + * + * I2P modded from Jetty 8.1.15 + * @since 0.9.15 + */ +class URIUtil +{ + + /** Encode a URI path. + * This is the same encoding offered by URLEncoder, except that + * the '/' character is not encoded. + * @param path The path the encode + * @return The encoded path + */ + public static String encodePath(String path) + { + if (path==null || path.length()==0) + return path; + + StringBuilder buf = encodePath(null,path); + return buf==null?path:buf.toString(); + } + + /** Encode a URI path. + * + * Somewhat oddly, this encodes all chars >= 0x80 if buf is null, (strict RFC 2396) + * but only the control, space, and special chars if buf is non-null. + * + * @param path The path the encode + * @param buf StringBuilder to encode path into (or null) + * @return The StringBuilder or null if no substitutions required. + */ + public static StringBuilder encodePath(StringBuilder buf, String path) + { + byte[] bytes=null; + if (buf==null) + { + loop: + for (int i=0;i': + case ' ': + case ':': + case '[': + case ']': + buf=new StringBuilder(path.length()*2); + break loop; + default: + if (c >= 0x7f || c <= 0x1f) + { + bytes = DataHelper.getUTF8(path); + buf=new StringBuilder(path.length()*2); + break loop; + } + + } + } + if (buf==null) + return null; + } + + //synchronized(buf) + //{ + if (bytes!=null) + { + for (int i=0;i': + buf.append("%3E"); + continue; + case ' ': + buf.append("%20"); + continue; + case 0x7f: + buf.append("%7F"); + continue; + case ':': + buf.append("%3A"); + continue; + case '[': + buf.append("%5B"); + continue; + case ']': + buf.append("%5D"); + continue; + default: + if (c <= 0x1f) // includes negative + toHex(c,buf); + else + buf.append((char)c); + continue; + } + } + + } + else + { + for (int i=0;i': + buf.append("%3E"); + continue; + case ' ': + buf.append("%20"); + continue; + case ':': + buf.append("%3A"); + continue; + case '[': + buf.append("%5B"); + continue; + case ']': + buf.append("%5D"); + continue; + default: + if (c <= 0x1f || (c >= 0x7f && c <= 0x9f) || Character.isSpaceChar(c)) + toHex(c,buf); + else + buf.append(c); + continue; + } + } + } + //} + + return buf; + } + + /** + * Modded from Jetty TypeUtil + */ + private static void toHex(byte b, StringBuilder buf) + { + buf.append('%'); + int d=0xf&((0xF0&b)>>4); + buf.append((char)((d>9?('A'-10):'0')+d)); + d=0xf&b; + buf.append((char)((d>9?('A'-10):'0')+d)); + } + + /** + * UTF-8 + */ + private static void toHex(char c, StringBuilder buf) + { + if (c > 0x7f) { + byte[] b = DataHelper.getUTF8(Character.toString(c)); + for (int i = 0; i < b.length; i++) { + toHex(b[i], buf); + } + } else { + toHex((byte) c, buf); + } + } +} + + + diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/package.html b/apps/i2psnark/java/src/org/klomp/snark/web/package.html new file mode 100644 index 000000000..56fda906f --- /dev/null +++ b/apps/i2psnark/java/src/org/klomp/snark/web/package.html @@ -0,0 +1,7 @@ + + +

+The i2psnark user interface, implemented as a webapp in i2psnark.war. +

+ + diff --git a/apps/i2psnark/locale/messages_ar.po b/apps/i2psnark/locale/messages_ar.po index dcabe588c..48d1b1c4a 100644 --- a/apps/i2psnark/locale/messages_ar.po +++ b/apps/i2psnark/locale/messages_ar.po @@ -10,232 +10,245 @@ msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:06+0000\n" -"PO-Revision-Date: 2013-11-19 23:52+0000\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" "Last-Translator: kytv \n" -"Language-Team: Arabic (http://www.transifex.com/projects/p/I2P/language/ar/)\n" +"Language-Team: Arabic (http://www.transifex.com/otf/I2P/language/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ar\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "تم قفل النفق" #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "تم تغببر مجموع حد الرفع الى {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "اقل حد الرفع الى {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "حولت سرعة الرفع الى {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "اقل سرعة رفع هي{0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "تغير تأخير البداية الى {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "سيتم تفعيل التغيير بعد اعادة التشغيل" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "فك الاتصال" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr " تغيرت الاعدادات الى {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "فشل في الاتصال بالاعدادات الجديدة، سيتم الرجوع الى الاعدادات القديمة" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "فشل في اعادة الاتصال بالاعدادات القديمة!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "اتصال بوجهة جديدة" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "اعادة التشغيل \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "تشغيل عند البداية" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "الغاء التشغيل عند البداية" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "تفعيل open trackers - يجب اعادة تشغيل التورنت لتفعيل التغيير." -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "الغاء تفعيل open trackers - يجب اعادة تشغيل التورنت لتفعيل التغيير." -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} تم تحميل التيمة ارجع الى صفحة للمشاهدة i2psnark." -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "لم تتغير الاعدادات" -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "تغيير open trackers - يجب اعادة تشغيل التورنت لتفعيل التغيير." -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "فشل في حفظ الاعدادات {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "جاري الاتصال بشبكة I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "فشل في الاتصال ب I2P - تخقق من اعدادات I2CP !" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "خطأ: فشل في اضافة التورنت {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "فشل في فتح \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "تورنت بهذه المعلومات مشغل: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -243,34 +256,46 @@ msgid "" "torrent." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "تورنت في \"{0}\"غير صحيح" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "تم خذف ملف التورنت: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "خطأ - لا توجد ذاكرة كافية، لا يمكن انشاء تورنت {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "تم اضافة وتشغيل التورنت: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "تمت اضافة: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "يحمل {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -278,311 +303,363 @@ msgid "" "DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "اضافة {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "فشل في نسخ التورنت الى {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "ملفات كثيرة في \"{0}\" ({1}) تم حذف" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 -#, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "ملف التورنت \"{0}\" لا يمكنه الانتهاء ب \".torrent\", سيتم حذفه!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 -#, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "ﻻ أجزاء في \"{0}\", حذف!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 -#, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" +msgid "Too many files in \"{0}\" ({1})!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "الأجزاء كبيرة في \"{0}\" ({1}B), حذف." +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#, java-format +msgid "No pieces in \"{0}\"!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 +#, java-format +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 +#, java-format +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "حدود {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" +msgid "Torrent \"{0}\" has no data!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "تورنت أكبر من {0}B غير مدعومة سيحذف \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "خطأ: ﻻيمكن حذف التورنت {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "تورنت متوقف: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "تورنت محذوف: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "اضف تورنت في {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "انتهى التحميل: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "بداية التورنت {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "فشل في اضافة I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "فتح النفق واطلاق جميع التورنت" -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "توقيف جميع التورنت و قفل النفق I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "لم يتم تحميل التورنت من {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "تم تحميل الملف من {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "تورنت مفعل: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "تورنت في قائمة الانتظار: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "تورنت غير صحيح {0} " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - برنامج مشاركة ملفات التورنت المجهول" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "تورنت" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark برنامج تورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "اعدادات" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "تورنت" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "أنعش الصفحة" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "منتدى" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "الحالة" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "اخفاء النظائر" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "أظهر النظائر" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "تورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "تقدير للوقت الباقي" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "محمل" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "محمل" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "الحجم" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "رفع" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "معدل التحميل" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "توقيف جمبع التورنت و النفق I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "توقيف الجمبع" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "شغل الجمبع" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "شغل جمبع التورنت و النفق I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "لم يحمل تورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "مجموع" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" @@ -593,7 +670,7 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" @@ -604,7 +681,7 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" @@ -615,174 +692,202 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "تم حذف ملف مغناطيس: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "تم خذف ملف التورنت: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "خذف ملف البيانات: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "فشل في حذف الملف: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "تم انشاء تورنت لـ \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "العديد من trackers يطلبون تسجيل التورنت قبل مشاركتها، قم بذلك قبل البداية {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "فشل في انشاء تورنت لـ \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "لا يمكن انشاء تورنت لبيانات غير موجودة: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "فشل في انشاء تورنت - عليك اختيار ملف أو مجلد" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Tracker خطأ" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" @@ -793,356 +898,377 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "بشارك" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "اكتمل" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "موافق" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "متوقف" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "لا بوجد نظائر" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "متوقف" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "تفاصيل التورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "أظهر الملفات" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "فتح ملف" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "قف التورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "قف" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "ابدأ التورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "ابدأ" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "حذف التورنت من القائمة، حذف ملف .torrent" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "حذف" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "خذف ملف التورنت و الملفات المرتبطة به" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "هل أنت متأكد من حذف التورنت \\''{0}\\'' وجمبع البيانات المحملة؟" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "حذف" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "غير معروف" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "شارك" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "غير مهم (النظير لا يحتوي على اجزاء نحتاجها)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "مشكلة (لا يمكن الحصول على اجزاء الملف من النظائر)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "تفاصيل حول {0} tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "معلومات" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "أضف تورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "من عنوان" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "أضف تورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "يمكن ايضا .نقل ملفات تورنت الى: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "سيتم القاف التورنت عند حذف الملف torrent." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "أنشئ تورنت" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "البيانات المشاركة" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" -msgstr "الملف او المجلد الذي ترغب في مشاركته " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "أنشئ تورنت" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "اعدادات" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "مجلد البيانات" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "ابدأ عند البداية" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "اذا تم تفعيل، يقوم بتشغيل التورنت تلقائيا عند اضافته" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "تيمة" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "تأخر البداية" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "دقائق" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "اقصى حد للرفع" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "النظائر" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "اقصى حد لسرعة الاتصال" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "ينصح باستعمال نصف سرعة الشبكة" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "أظهر أو غير سرعة الموجه" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "استعمال open trackers ايضا" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "اعدادت الاتصال الداخلي" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "اعدادت الاتصال الخارجي" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "حفظ الاعدادات" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "فتح" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "غنوان مغناطيس غير صحيح {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" @@ -1153,7 +1279,7 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" @@ -1164,106 +1290,135 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "وصلة مغناطيس" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "الحجم" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "انتهاء" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "الملفات" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "القطع" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "حجم القطعة" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "المجلد" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "الأولوية" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "تورنت غير موجود؟" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "الملف غير موجود في التورنت؟" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "اكتمل" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "عالي" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "عادي" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "تجاوز" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "حفظ الأولويات" diff --git a/apps/i2psnark/locale/messages_cs.po b/apps/i2psnark/locale/messages_cs.po index c21d7736d..a727d9cf7 100644 --- a/apps/i2psnark/locale/messages_cs.po +++ b/apps/i2psnark/locale/messages_cs.po @@ -4,236 +4,251 @@ # To contribute translations, see http://www.i2p2.de/newdevelopers # # Translators: +# A5h8d0wf0x , 2014 +# tradukisto , 2014 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:06+0000\n" -"PO-Revision-Date: 2013-11-19 23:52+0000\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" "Last-Translator: kytv \n" -"Language-Team: Czech (http://www.transifex.com/projects/p/I2P/language/cs/)\n" +"Language-Team: Czech (http://www.transifex.com/otf/I2P/language/cs/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cs\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Neběží žádné další torrenty." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." -msgstr "" +msgstr "I2P tunel uzavřen." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" -msgstr "" +msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Celkový limit sdílečů změněn na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Nejmenší celkový limit sdílečů je {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Horní BW limit změněn na {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Nejmenší horní limit přenosové rychlist je {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Prodleva při startu změněna na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Doba aktualizace stavu (refresh time) změněna na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Aktualizace stavu vypnuta" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "Změny I2CP a tunelu se projeví až po zastavení všech torrentů" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "Nastavení (options) I2CP změněno na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Odpojuji se od starého I2CP cíle" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Nastavení (settings) I2CP změněno na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Nemůžu se připojit s novým nastavením I2CP, vracím se k předhozímu." -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Nemohu se opětovně připojit ani s předchozím nastavením!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Opětovně připojeno k novému I2CP cíli" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "I2CP listener restartován pro \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Nové soubory budou veřejně přístupné" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Nové soubory nebudou veřejně přístupné" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Automatické spuštění zapnuto" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Automatické spuštění vypnuto" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Zapnuto automatické spuštění" -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Otevřené trackery vypnuty - aby se změna projevila je nutné restartovat všechny torrenty" -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." -msgstr "" +msgstr "DHT povoleno." -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." -msgstr "" +msgstr "DHT zakázáno." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "Téma {0} bylo nahráno, přejděte prosím na hlavní stránku i2snark" -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Nastavení nebylo změněno." -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Seznam otevřených trackerů změněn - aby se změna projevila je nutné restartovat všechny torrenty" -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Nemůžu uložit soubor s nastavením do souboru {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Připojuji se k I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Při připojování k I2P nastala chyba, zkontrolujte prosím nastavení I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Chyba: nepodařilo se přidat torrent {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Nejde otevřít \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Torrent s tímto infohašišem již běží: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -241,34 +256,46 @@ msgid "" "torrent." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Torrent v \"{0}\" je chybný" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "CHYBA - nedostatek paměti, nemohu vytvořit torrent z {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent přidán a spuštěn: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent přidán: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Získávám {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -276,311 +303,363 @@ msgid "" "DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Přídávám {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Chyba: nepodařilo se zkopírovat soubor torrentu do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "V \"{0}\" ({1}) je příliš mnoho souborů, mažu je!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 -#, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Jméno souboru torrentu \"{0}\" nemůže končit na \".torrent\", mažu ho!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 -#, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "\"{0}\" neobsahuje žádné části, mažu to!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 -#, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Příliš mnoho částí v \"{0}\", maximum je {1}, mažu to!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 -#, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." +msgid "Too many files in \"{0}\" ({1})!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 +#, java-format +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#, java-format +msgid "No pieces in \"{0}\"!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 +#, java-format +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 +#, java-format +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" +msgid "Torrent \"{0}\" has no data!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" +msgid "Torrent stopped: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" -msgstr "" +msgstr "Torrent smazán: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" -msgstr "" +msgstr "Stahování dokončeno: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 +msgid "I2PSnark" +msgstr "I2PSnark" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 msgid "Router is down" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 msgid "Torrents" -msgstr "" +msgstr "Torrenty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 -msgid "I2PSnark" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" -msgstr "" +msgstr "Fórum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" +msgstr "Status" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" -msgstr "" +msgstr "Skrýt peery" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" -msgstr "" +msgstr "Ukázat peery" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" +msgstr "Torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" @@ -588,7 +667,7 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" @@ -596,7 +675,7 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" @@ -604,174 +683,202 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" -msgstr "" +msgstr "Torrent vytvořen pro \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" -msgstr "" +msgstr "Přidat tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" @@ -779,356 +886,377 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" -msgstr "" +msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" -msgstr "" +msgstr "Neznámý" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" -msgstr "" +msgstr "Seed" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" -msgstr "" +msgstr "Přidat torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" -msgstr "" +msgstr "Z URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" +msgstr "Přidat torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." -msgstr "" +msgstr "Můžete také zkopírovat .torrent soubory do: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" -msgstr "" +msgstr "Vytvořit torrent" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" -msgstr "" +msgstr "Trackery" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" -msgstr "" +msgstr "Hlavní" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" -msgstr "" +msgstr "Vytvořit torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 -msgid "Theme" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 +msgid "Theme" +msgstr "Vzhled" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" @@ -1136,7 +1264,7 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" @@ -1144,106 +1272,135 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "" diff --git a/apps/i2psnark/locale/messages_de.po b/apps/i2psnark/locale/messages_de.po index d2147e981..38e34cec5 100644 --- a/apps/i2psnark/locale/messages_de.po +++ b/apps/i2psnark/locale/messages_de.po @@ -2,15 +2,18 @@ # Copyright (C) 2009 The I2P Project # This file is distributed under the same license as the i2psnark package. # To contribute translations, see http://www.i2p2.de/newdevelopers -# +# # Translators: # "blabla", 2011 +# blabla , 2015 # blabla , 2012 # D.A. Loader, 2012 # ducki2p , 2011 +# Ettore Atalan , 2014 # foo , 2009 # SteinQuadrat, 2013 -# echeloni2p , 2014 +# Lars Schimmer , 2014-2015 +# Max Muster , 2014 # mixxy, 2011 # nextloop , 2013 # pirr , 2012 @@ -19,1280 +22,1391 @@ msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-09 18:07+0000\n" -"PO-Revision-Date: 2014-01-05 15:27+0000\n" -"Last-Translator: echeloni2p \n" -"Language-Team: German (http://www.transifex.com/projects/p/I2P/language/" -"de/)\n" -"Language: de\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-06 08:21+0000\n" +"Last-Translator: Lars Schimmer \n" +"Language-Team: German (http://www.transifex.com/otf/I2P/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 -#: ../java/src/org/klomp/snark/SnarkManager.java:1960 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Keine weiteren Torrents laufen." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "I2P-Tunnel geschlossen." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1655 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:515 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" -msgstr "Gesamtanzahl der Uploadslots geändert auf {0}" +msgstr "Gesamthochladerbegrenzung geändert auf {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:517 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" -msgstr "Minimale Anzahl derUploadslots ist {0}" +msgstr "Minimale Gesamthochladerbegrenzung ist {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:529 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" -msgstr "Upload-Bandbreite wurde auf {0}kbyte/s geändert." +msgstr "Hochladebandbreitenbegrenzung geändert auf {0}kbyte/s." -#: ../java/src/org/klomp/snark/SnarkManager.java:531 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" -msgstr "Minimales Limit der Upload-Bandbreite ist {0} kbyte/s." +msgstr "Minimale Hochladebandbreitenbegrenzung ist {0} kbyte/s." -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" -msgstr "Startverzögerung auf {0} gesetzt" +msgstr "Startverzögerung geändert auf {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:554 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" -msgstr "Auffrischungsrate auf {0} gesetzt" +msgstr "Aktualisierungsrate geändert auf {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:556 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" -msgstr "Auffrischung abgeschaltet" +msgstr "Aktualisierung deaktiviert" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Seitengröße geändert auf {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "Datenverzeichnis muss ein absoluter Pfad sein" -#: ../java/src/org/klomp/snark/SnarkManager.java:583 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" -msgstr "Datenverzeichnis existiert nicht" +msgstr "Datenverzeichnis nicht vorhanden" -#: ../java/src/org/klomp/snark/SnarkManager.java:585 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "Kein Verzeichnis" -#: ../java/src/org/klomp/snark/SnarkManager.java:587 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "Unlesbar" -#: ../java/src/org/klomp/snark/SnarkManager.java:592 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Datenverzeichnis geändert auf {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:647 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" -msgstr "" -"Änderungen an I2CP und am Tunnel werden nach dem Stoppen aller Torrents " -"wirksam" +msgstr "Änderungen an I2CP und am Tunnel werden nach dem Stoppen aller Torrents wirksam" -#: ../java/src/org/klomp/snark/SnarkManager.java:651 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" -msgstr "I2CP-Optionen auf {0} gesetzt" +msgstr "I2CP-Optionen geändert auf {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" -msgstr "Trenne das alte I2CP-Ziel" +msgstr "Altes I2CP-Ziel wird getrennt" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "I2CP-Einstellungen geändert auf {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:664 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" -msgstr "" -"Verbinden mit den neuen Einstellungen nicht möglich, benutze wieder die " -"alten I2CP-Einstellungen" +msgstr "Verbinden mit den neuen Einstellungen nicht möglich, benutze wieder die alten I2CP-Einstellungen" -#: ../java/src/org/klomp/snark/SnarkManager.java:668 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Verbinden mit den alten Einstellungen nicht möglich!" -#: ../java/src/org/klomp/snark/SnarkManager.java:670 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Verbunden auf dem neuem I2CP-Ziel" -#: ../java/src/org/klomp/snark/SnarkManager.java:677 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" -msgstr "I2CP-Verbindung neu gestartet für \"{0}\"" +msgstr "I2CP-Lauscher neu gestartet für \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" -msgstr "Neu angelegte Dateien werden allgemein lesbar sein." +msgstr "Neu Dateien werden allgemein lesbar sein." -#: ../java/src/org/klomp/snark/SnarkManager.java:693 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" -msgstr "Neu angelegte Dateien werden nicht allgemein lesbar sein." +msgstr "Neue Dateien werden nicht allgemein lesbar sein." -#: ../java/src/org/klomp/snark/SnarkManager.java:700 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" -msgstr "Aktiviere Autostart" +msgstr "Autostart wird aktiviert" -#: ../java/src/org/klomp/snark/SnarkManager.java:702 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" -msgstr "Deaktiviere Autostart" +msgstr "Autostart wird deaktiviert" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "Smarte Sortierung aktivieren" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "Smarte Sortierung deaktivieren" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." -msgstr "" -"OpenTracker aktiviert - Um dies anzuwenden, müssen die Torrents neu " -"gestartet werden." +msgstr "OpenTracker aktiviert - Um dies anzuwenden, müssen die Torrents neu gestartet werden." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." -msgstr "" -"OpenTracker deaktiviert - Um dies anzuwenden, müssen die Torrents neu " -"gestartet werden." +msgstr "OpenTracker deaktiviert - Um dies anzuwenden, müssen die Torrents neu gestartet werden." -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." -msgstr "DHT eingeschaltet" +msgstr "DHT aktiviert." -#: ../java/src/org/klomp/snark/SnarkManager.java:719 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." -msgstr "DHT ausgeschaltet" +msgstr "DHT deaktiviert." -#: ../java/src/org/klomp/snark/SnarkManager.java:721 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" -msgstr "" -"DHT-Änderungen bedürfen des anhaltens und erneuten Startens der Tunnel." +msgstr "DHT-Änderungen erfordern das Anhalten und erneutes Öffnen des Tunnels" -#: ../java/src/org/klomp/snark/SnarkManager.java:728 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." -msgstr "" -"Thema {0} geladen. Gehen Sie zurück zur Hauptseite von i2psnark, um die " -"Änderungen zu sehen!" +msgstr "{0} Theme geladen. Gehen Sie zurück zur Hauptseite von i2psnark, um die Änderungen zu sehen!" -#: ../java/src/org/klomp/snark/SnarkManager.java:738 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Konfiguration nicht geändert." -#: ../java/src/org/klomp/snark/SnarkManager.java:770 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." -msgstr "" -"OpenTracker-Liste geändert - Um dies anzuwenden, müssen die Torrents neu " -"gestartet werden" +msgstr "OpenTracker-Liste geändert - Um dies anzuwenden, müssen die Torrents neu gestartet werden" -#: ../java/src/org/klomp/snark/SnarkManager.java:780 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." -msgstr "Liste privater Tracker geändert - betrifft nur neu erstellte Torrents" +msgstr "Liste privater Tracker geändert - betrifft nur neu erstellte Torrents." -#: ../java/src/org/klomp/snark/SnarkManager.java:826 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Konnte Konfiguration nicht in {0} speichern" -#: ../java/src/org/klomp/snark/SnarkManager.java:904 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Verbinde mit I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:907 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" -msgstr "" -"Fehler beim Verbinden mit I2P - Kontrollieren Sie die I2CP-Einstellungen!" +msgstr "Fehler beim Verbinden mit I2P - Überprüfen Sie Ihre I2CP-Einstellungen!" -#: ../java/src/org/klomp/snark/SnarkManager.java:916 -#: ../java/src/org/klomp/snark/SnarkManager.java:1692 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Fehler: Konnte den Torrent \"{0}\" nicht hinzufügen" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:938 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" -msgstr "Kann dies nicht öffnen: \"{0}\"" +msgstr "Kann \"{0}\" nicht öffnen" -#. TODO - if the existing one is a magnet, delete it and add the metainfo instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:957 -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/SnarkManager.java:1140 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:162 +#. TODO - if the existing one is a magnet, delete it and add the metainfo +#. instead? +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Torrent mit diesem Infohash läuft schon: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:963 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" -msgstr "Fehler - Keine I2P-Tracker im privaten Torrent {0}" +msgstr "FEHLER - Keine I2P-Tracker im privaten Torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:965 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" -"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and " -"DHT only." -msgstr "" -"Warnung - keine I2P-Tracker in \"{0}\", werde nur bei I2P-OpenTrackern und " -"mittels DHT bekanntgeben" +"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" +" DHT only." +msgstr "Warnung - Keine I2P-Tracker in \"{0}\", es wird nur bei I2P-OpenTrackern und mittels DHT bekanntgeben" -#: ../java/src/org/klomp/snark/SnarkManager.java:968 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." -msgstr "" -"Warnung - keine I2P-internen Tracker in \"{0}\", und OpenTracker " -"deaktiviert. Bekanntgabe erfolgt nur mittels DHT." +msgstr "Warnung - Keine I2P-Tracker in \"{0}\" und OpenTrackers sind deaktiviert. Bekanntgabe erfolgt nur mittels DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:970 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " -"disabled, you should enable open trackers or DHT before starting the torrent." -msgstr "" -"Warnung - keine I2P-internen Tracker in \"{0}\", und as Benutzen von sowohl " -"DHT alsauch OpenTracker sind deaktiviert. DHT oder OpenTracker sollten " -"aktiviert werden, bevor du den Torrent startest." +"disabled, you should enable open trackers or DHT before starting the " +"torrent." +msgstr "Warnung - Keine I2P-Tracker in \"{0}\", und DHT und OpenTrackers sind deaktiviert. Sie sollten DHT oder OpenTrackers vor dem Starten des Torrents aktivieren." -#: ../java/src/org/klomp/snark/SnarkManager.java:992 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Torrent in \"{0}\" ist nicht gültig" -#: ../java/src/org/klomp/snark/SnarkManager.java:999 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:186 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Torrentdatei gelöscht: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "Torrent Datei von {0} nach {1} verschoben" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" -msgstr "" -"Fehler - unzureichender Arbeitsspeicher, kann keinen Torrent von {0} " -"erstellen." +msgstr "FEHLER - Unzureichender Arbeitsspeicher, kann keinen Torrent von {0} erstellen." -#: ../java/src/org/klomp/snark/SnarkManager.java:1011 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent hinzugefügt und gestartet: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "Torrent hinzugefügt und gestartet: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1013 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent hinzugefügt: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "Torrent hinzugefügt: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1069 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:89 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" -msgstr "Hole {0}" +msgstr "{0} wird abgerufen" -#: ../java/src/org/klomp/snark/SnarkManager.java:1075 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " -"succeed until you start another torrent, enable open trackers, or enable DHT." -msgstr "" -"Das Verwenden von OpenTrackern ist abgeschaltet und wir haben keine DHT-" -"Gegenstellen. Das Herunterladen von {0} könnte scheitern, sofern kein " -"anderer Torrent gestartet und die Verwendung von OpenTrackern oder DHT " -"erlaubt wird." - -#: ../java/src/org/klomp/snark/SnarkManager.java:1079 -#, java-format -msgid "Adding {0}" -msgstr "Hinzufügen {0}" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1111 -#, java-format -msgid "Download already running: {0}" -msgstr "Download läuft bereits: {0}" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1150 -#: ../java/src/org/klomp/snark/SnarkManager.java:1173 -#: ../java/src/org/klomp/snark/SnarkManager.java:1611 -#, java-format -msgid "Failed to copy torrent file to {0}" -msgstr "Konnte Torrent-Datei nicht nach {0} kopieren" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 -#, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Zu viele Dateien in \"{0}\" ({1}), wird gelöscht! " - -#: ../java/src/org/klomp/snark/SnarkManager.java:1402 -#, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Torrentdatei \"{0}\" darf nicht auf '.torrent' enden, wird gelöscht!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1404 -#, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Keine Teile in \"{0}\", wird entfernt!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1406 -#, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Zu viele Teile in \"{0}\", das Limit sind {1}, werden gelöscht!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 -#, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Teile in \"{0}\" sind zu groß ({1}B), lösche es." +"succeed until you start another torrent, enable open trackers, or enable " +"DHT." +msgstr "Das Verwenden von OpenTrackern ist deaktiviert und wir haben keine DHT-Gegenstellen. Das Abrufen von {0} könnte scheitern, sofern Sie keinen anderen Torrent starten. Aktivieren Sie OpenTracker oder DHT." #: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format +msgid "Adding {0}" +msgstr "{0} wird hinzugefügt" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 +#, java-format +msgid "Download already running: {0}" +msgstr "Herunterladen läuft bereits: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 +#, java-format +msgid "Failed to copy torrent file to {0}" +msgstr "Fehler beim Kopieren der Torrentdatei nach {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 +#, java-format +msgid "Too many files in \"{0}\" ({1})!" +msgstr "Zu viele Dateien in \"{0}\" ({1})!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 +#, java-format +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "Torrent Datei \"{0}\" kann nicht mit \".torrent\" enden!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#, java-format +msgid "No pieces in \"{0}\"!" +msgstr "Keine Teile in \"{0}\"!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 +#, java-format +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "Zu viele Teile in \"{0}\", das Limit ist {1}!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 +#, java-format +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "Teile sind zu groß in \"{0}\" ({1}B)!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 +#, java-format msgid "Limit is {0}B" msgstr "Limit ist \"{0}\"Bytes" -#: ../java/src/org/klomp/snark/SnarkManager.java:1411 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "Torrent \"{0}\" enthält keine Daten und wird gelöscht!" +msgid "Torrent \"{0}\" has no data!" +msgstr "Torrent \"{0}\" hat keine Daten!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1419 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "" -"Torrents größer als \"{0}\"Bytes werden nicht unterstützt, lösche \"{1}\"." +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "Torrents größer als {0}B sind noch nicht unterstützt \"{1}\"!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1435 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Fehler: Konnte den Torrent \"{0}\" nicht entfernen" -#: ../java/src/org/klomp/snark/SnarkManager.java:1456 -#: ../java/src/org/klomp/snark/SnarkManager.java:1474 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent angehalten: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "Torrent gestoppt: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1495 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent entfernt: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1503 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" -msgstr "Füge Torrents in {0} hinzu ..." +msgstr "Torrents in {0} werden hinzugefügt" -#: ../java/src/org/klomp/snark/SnarkManager.java:1534 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" -msgstr "Limit der Upload-Bandbreite ist {0} KByte/s." +msgstr "Hochladebandbreitenbegrenzung ist {0} KByte/s." -#: ../java/src/org/klomp/snark/SnarkManager.java:1556 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" -msgstr "vollständig heruntergeladen:\"{0}\"" +msgstr "Herunterladen abgeschlossen: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1607 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo für {0} erhalten" -#: ../java/src/org/klomp/snark/SnarkManager.java:1608 -#: ../java/src/org/klomp/snark/SnarkManager.java:1837 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" -msgstr "Starte Torrent {0} ..." +msgstr "Torrent {0} wird gestartet" -#: ../java/src/org/klomp/snark/SnarkManager.java:1623 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Fehler bei Torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1686 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Konnte keine Verbindung zu I2P herstellen!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1836 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:126 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" -msgstr "I2P Tunnel öffnen ..." +msgstr "I2P-Tunnel wird geöffnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:1860 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." -msgstr "Öffne den I2P-Tunnel und starte alle Torrents ..." +msgstr "Den I2P-Tunnel öffnen und alle Torrents starten." -#: ../java/src/org/klomp/snark/SnarkManager.java:1923 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." -msgstr "Stoppe alle Torrents und beende den I2P-Tunnel." +msgstr "Alle Torrents stoppen und den I2P-Tunnel schließen." -#: ../java/src/org/klomp/snark/SnarkManager.java:1942 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Der I2P-Tunnel wird nach Benachrichtigung der Tracker geschlossen." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "Überprüfung von Torrent {0} beendet, nun {1} vollständig" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "Überprüfung von Torrent {0} beendet, keine Änderung" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "Fehler bei der Überprüfung von Torrent {0}" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" -msgstr "" -"Keine gültigen Tracker für {0}. Sollen OpenTracker und/oder DHT verwendet " -"werden?" +msgstr "Keine gültigen Tracker für {0}. OpenTrackers oder DHT aktivieren?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" -msgstr "Lade Aktualisierung ..." +msgstr "Aktualisierung" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" -msgstr "Lade Aktualisierung von {0}" +msgstr "Aktualisierung von {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:77 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" -msgstr "Torrent-Datei von {0} herunterladen" +msgstr "Torrentdatei von {0} herunterladen" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:99 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Torrent wurde nicht geladen von {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:153 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" -msgstr "Torrent geholt von {0}" +msgstr "Torrent abgerufen von {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:174 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent läuft schon: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:176 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent ist schon in der Warteschlange: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:184 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Torrent in {0} war nicht gültig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:247 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Anonymer BitTorrent-Klient" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260 -msgid "Router is down" -msgstr "Router ist Offline" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 -msgid "Torrents" -msgstr "Torrents" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1477 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2242 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287 -msgid "Refresh page" -msgstr "Aktualisiere Seite" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Konfiguration" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "Anonymer BitTorrent-Client" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Router ist Offline" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrents" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 +msgid "Refresh page" +msgstr "Seite aktualisieren" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Forum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" -msgstr "Drücke den \"Torrent Hinzufügen\" Button um den Torrent zu laden" +msgstr "Klicken Sie die \"Torrent Hinzufügen\"-Schaltfläche, um den Torrent abzurufen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:345 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" -msgstr "Lösche Nachrichten" +msgstr "Nachrichten löschen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2427 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" -msgstr "Zustand" +msgstr "Status" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "Sortieren nach {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Teilnehmer ausblenden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:423 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Teilnehmer einblenden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2236 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2256 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:442 -msgid "Estimated time remaining" -msgstr "geschätzte verbleibende Zeit" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "Dateityp" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:445 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 msgid "ETA" -msgstr "Dauer" +msgstr "ETA" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:450 -msgid "Downloaded" -msgstr "heruntergeladen" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 +msgid "Estimated time remaining" +msgstr "Geschätzte verbleibende Zeit" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" -msgstr " " +msgstr " Empf." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458 -msgid "Uploaded" -msgstr "hochgeladen" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Heruntergeladen" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Größe" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:461 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 msgid "TX" -msgstr " " +msgstr " Send." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:467 -msgid "Down Rate" -msgstr "eingehend" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "Hochladeverhältnis" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 +msgid "Uploaded" +msgstr "Hochgeladen" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 msgid "RX Rate" -msgstr "Downloadgeschwindigkeit" +msgstr "Übertragungsrate für den Empfang" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:476 -msgid "Up Rate" -msgstr "ausgehend" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 +msgid "Down Rate" +msgstr "Herunterladegeschwindigkeit" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:479 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" -msgstr "Uploadgeschwindigkeit" +msgstr "Übertragungsrate fürs Senden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Hochladegeschwindigkeit" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" -msgstr "Stoppe alle Torrents und den I2P-Tunnel" +msgstr "Alle Torrents und den I2P-Tunnel stoppen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" -msgstr "Stoppe alle" +msgstr "Alle stoppen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" -msgstr "Alle angehaltenen Torrents fortsetzen" +msgstr "Alle gestoppten Torrents fortsetzen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:510 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" -msgstr "Starte alle" +msgstr "Alle starten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" -msgstr "Starte alle Torrents und den I2P-Tunnel" +msgstr "Alle Torrents und den I2P-Tunnel starten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." -msgstr "keine Torrents geladen" +msgstr "Keine Torrents geladen." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Gesamt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "1 Torrent" msgstr[1] "{0} Torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "1 verbundener Teilnehmer" msgstr[1] "{0} verbundene Teilnehmer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" -msgstr[0] "eine DHT-Gegenstelle" +msgstr[0] "1 DHT-Gegenstelle" msgstr[1] "{0} DHT-Gegenstellen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 -msgid "First" -msgstr "erste" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "Ziel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 +msgid "First" +msgstr "Erste" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Erste Seite" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" -msgstr "Vorheriger" +msgstr "Vorherige" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Vorherige Seite" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" -msgstr "Nächster" +msgstr "Nächste" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Nächste Seite" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" -msgstr "letzte" +msgstr "Letzte" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" -msgstr "letzte Seite" +msgstr "Letzte Seite" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "Datenverzeichnis kann nicht erstellt werden" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "Kann den Torrent {0} nicht hinzufügen, da dieser in einem anderen Torrent ist: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" -msgstr "ungültige URL - muss mit \"http://\", \"{0}\" oder \"{1}\" anfangen" +msgstr "Ungültige URL - muss mit \"http://\", \"{0}\" oder \"{1}\" anfangen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" -msgstr "Magnetlink wurde gelöscht: {0}" +msgstr "Magnetlink gelöscht: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Torrentdatei gelöscht: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Download gelöscht: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" -msgstr "Daten gelöscht: {0}" +msgstr "Datendatei gelöscht: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Daten konnten nicht gelöscht werden: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Das Verzeichnis {0} konnte nicht gelöscht werden." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Verzeichnis gelöscht: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "Kann keinen Torrent mit der Endung \".torrent\" hinzufügen: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "Torrent mit diesem Namen ist schon aktiv: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "Kann keinen Torrent hinzufügen, der das I2P Verzeichnis beinhaltet: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "Kann den Torrent {0} nicht hinzufügen, da dieser den Torrent {1} enthält." + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" -msgstr "" -"Fehler - Einfügen alternativer Tracker ohne primären Tracker nicht möglich" +msgstr "Fehler - Einfügen alternativer Tracker ohne primären Tracker nicht möglich" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" -msgstr "" -"Fehler - Mischen von privaten und öffentlichen Trackern in einem Torrent " -"nicht möglich" +msgstr "Fehler - Mischen von privaten und öffentlichen Trackern in einem Torrent nicht möglich" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent erstellt für \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:968 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" -msgstr "" -"Viele I2P-Tracker erfordern eine Registrierung, bevor der Torrent verteilt " -"wird. Bitte tun Sie dies vor dem Start von \"{0}\"!" +msgstr "Viele I2P-Tracker erfordern eine Registrierung, bevor der Torrent verteilt wird. Bitte tun Sie dies vor dem Start von \"{0}\"!" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Fehler beim Erstellen eines Torrents für \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" -msgstr "Kann keinen Torrent für nicht existente Daten erstellen: {0}" +msgstr "Kann keinen Torrent für nicht existente vorhandene erstellen: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" -msgstr "" -"Fehler beim Erstellen des Torrents - Sie müssen eine Datei oder ein " -"Verzeichnis angeben." +msgstr "Fehler beim Erstellen des Torrents - Sie müssen eine Datei oder ein Verzeichnis angeben." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2018 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" -msgstr "Lösche ausgewähltes" +msgstr "Ausgewählte löschen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2019 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" -msgstr "Trackereinstellungen speichern" +msgstr "Trackerkonfiguration speichern" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1025 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Entfernt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" -msgstr "Füge Tracker hinzu" +msgstr "Tracker hinzufügen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" -msgstr "Gib einen gültigen Tracker-Namen sowie die URLs an!" +msgstr "Geben Sie einen gültigen Tracker-Namen und die URLs ein" -#. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2021 +#. "\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" -msgstr "Auf Default zurücksetzen" +msgstr "Auf Standardeinstellungen zurücksetzen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1085 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" -msgstr "Auf Default Tracker zurückgesetzt" +msgstr "Auf Standard-Tracker zurückgesetzt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1207 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Überprüfe" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1209 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Reserviere" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Trackerfehler" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1254 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "1 Teilnehmer" msgstr[1] "{0} Teilnehmern" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1234 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Starten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Verteile" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2369 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" -msgstr "vollständig" +msgstr "Vollständig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1266 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1272 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Stillstand" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" -msgstr "keine Teilnehmer" +msgstr "Keine Teilnehmer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1296 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" -msgstr "angehalten" +msgstr "Gestoppt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Details" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" -msgstr "Zeige Dateien" +msgstr "Dateien ansehen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" -msgstr "Öffne Datei" +msgstr "Datei öffnen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Torrent stoppen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1404 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Stopp" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Torrent starten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1418 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Start" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" -msgstr "" -"entfernt den Torrent von der aktiven Liste und löscht die .torrent-Datei" +msgstr "Entfernt den Torrent von der aktiven Liste und löscht die .torrent-Datei" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1435 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" -msgstr "" -"Möchten Sie wirklich die Datei \\''{0}\\'' löschen (Heruntergeladene Daten " -"werden nicht gelöscht) ?" +msgstr "Sind Sie sicher, dass Sie die Datei \\''{0}\\'' löschen möchten (Heruntergeladene Daten werden nicht gelöscht)?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1438 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Entfernen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" -msgstr "löscht die .torrent-Datei und dazugehörige Daten Datei(en)" +msgstr "Löscht die .torrent-Datei und (die) dazugehörige Datendatei(en)" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" -msgstr "" -"Sind Sie sicher, dass Sie die Torrentdatei \\''{0}\\'' und alle " -"heruntergeladenen Daten löschen wollen?" +msgstr "Sind Sie sicher, dass Sie die Torrentdatei \\''{0}\\'' und alle heruntergeladenen Daten löschen wollen?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1458 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Löschen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Unbekannt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Quelle" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1528 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" -msgstr "uninteressant (Der Teilnehmer hat keine Teile, die wir benötigen)" +msgstr "Uninteressant (Der Teilnehmer hat keine Teile, die wir benötigen)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" -msgstr "gedrosselt (Der Teilnehmer hat uns nicht erlaubt, Teile anzufordern)" +msgstr "Gedrosselt (Der Teilnehmer hat uns nicht erlaubt, Teile anzufordern)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" -msgstr "uninteressiert (Wir haben keine Teile, die der Teilnehmer benötigt)" +msgstr "Uninteressiert (Wir haben keine Teile, die der Teilnehmer benötigt)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1552 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" -msgstr "gedrosselt (Wir erlauben dem Teilnehmer nicht, Teile anzufordern)" +msgstr "Gedrosselt (Wir erlauben dem Teilnehmer nicht, Teile anzufordern)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1607 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Details beim Tracker {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1624 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Info" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Torrent hinzufügen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1677 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" -msgstr "Quell-URL" +msgstr "Von URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" -"Enter the torrent file download URL (I2P only), magnet link, maggot link, or " -"info hash" -msgstr "" -"Gib die URL einer Torrentdatei (I2P-Link), einen Magnet- / Maggot-Link oder " -"einen Info-Hash ein!" +"Enter the torrent file download URL (I2P only), magnet link, maggot link, or" +" info hash" +msgstr "Geben Sie die URL zum Herunterladen einer Torrentdatei (I2P-Link), einen Magnet-Link, einen Maggot-Link oder einen Info-Hash ein!" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1685 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Füge Torrent hinzu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1688 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "Datenverzeichnis" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "Geben Sie das Verzeichnis zum Speichern der Daten ein (Standardeinstellung {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Alternativ können Sie die .torrent-Dateien auch nach {0} kopieren." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1690 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Das Entfernen der .torrent-Datei stoppt den jeweiligen Torrent." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Torrent erstellen" -#. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716 +#. out.write("From file:
\n"); +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Daten zum Verteilen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1720 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Datei oder Verzeichnis zum Verteilen (muss im angegebenen Pfad sein)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "Datei oder Verzeichnis zum Verteilen (Gesamter Pfad oder aus dem Verzeichnis {0} )" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Primär" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternativen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" -msgstr "Erstelle Torrent" +msgstr "Torrent erstellen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1747 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" -msgstr "Keiner" +msgstr "keiner" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2033 -msgid "Configuration" -msgstr "Einstellungen" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1784 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Datenverzeichnis" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1788 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Dateien von allen lesbar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" -msgstr "" -"Ist dies markiert, können andere Benutzer auf die heruntergeladenen Dateien " -"zugreifen." +msgstr "Wenn abgehakt, können andere Benutzer auf die heruntergeladenen Dateien zugreifen." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1796 -msgid "Auto start" -msgstr "Autostart" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "Torrents automatisch starten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1800 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" -msgstr "Wenn markiert, werden hinzugefügte Torrents automatisch gestartet." +msgstr "Wenn abgehakt, werden hinzugefügte Torrents automatisch gestartet." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1804 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "Smarte Torrent Sortierung" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "Ignoriert Wörter wie 'the' bei der Sortierung, falls Aktiv" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Aufmachung" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1817 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" -msgstr "Auffrischungsintervall" +msgstr "Aktualisierungsintervall" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1830 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Nie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1836 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Startverzögerung" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "Minuten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Seitengröße" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1844 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "Torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1868 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Gesamtlimit an Hochladern" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "Teilnehmer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1875 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Bandbreitenbegrenzung beim Hochladen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Halbe verfügbare Bandbreite wird empfohlen." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Routerbandbreite ansehen oder ändern" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" -msgstr "Benutze auch OpenTracker" +msgstr "Auch OpenTracker verwenden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1888 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" -"If checked, announce torrents to open trackers as well as the tracker listed " -"in the torrent file" -msgstr "" -"Wenn markiert, wird der Torrent neben dem angegebenen Tracker auch bei den " -"OpenTrackern bekanntgegeben." +"If checked, announce torrents to open trackers as well as the tracker listed" +" in the torrent file" +msgstr "Wenn abgehakt, wird der Torrent neben dem in der Torrentdatei angegebenen Tracker auch bei den OpenTrackern bekanntgegeben." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1892 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" -msgstr "DHT einschalten" +msgstr "DHT aktivieren" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1896 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" -msgstr "Wenn ausgewählt, wird DHT verwendet" +msgstr "Wenn abgehakt, wird DHT verwendet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1912 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Einstellungen eingehend" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1918 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Einstellungen ausgehend" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1926 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "I2CP-Host" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1931 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "I2CP-Port" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "I2CP-Optionen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1951 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Einstellungen speichern" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" -msgstr "Name" +msgstr "Namen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1973 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "Webseiten-URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "Standard" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" -msgstr "offen" +msgstr "Offen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" -msgstr "privat" +msgstr "Privat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "Ankündigungs-URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2009 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Hinzufügen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2049 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" -msgstr "ungültige Magnet-URL {0}" +msgstr "Ungültige Magnet-URL {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2057 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "1 Zwischenstation" msgstr[1] "{0} Zwischenstationen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2058 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "1 Tunnel" msgstr[1] "{0} Tunnel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2265 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" -msgstr "Torrent Datei" +msgstr "Torrentdatei" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "Datenadresse" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "Info-Hash" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Primärer Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" -msgstr "Tracker Liste" +msgstr "Tracker-Liste" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2311 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Kommentar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2320 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Erstellt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2330 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Erstellt von" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2340 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "Hinzugefügt" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "Fertig" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Magnetlink" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2347 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" -msgstr "privater Torrent" +msgstr "Privater Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2357 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2421 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2423 -msgid "Size" -msgstr "Größe" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2364 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Fortschritt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Verbleibend" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2381 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Dateien" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2386 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" -msgstr "Stücke" +msgstr "Teile" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2390 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Stückgröße" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2413 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2417 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "Für Resultate Seite aktualisieren" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "Überprüfung forcieren" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Verzeichnis" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Priorität" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Eine Hierarchie nach oben" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrentdatei nicht gefunden?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2480 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "Datei nicht gefunden im Torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "vollständig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "verbleibend" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2543 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" -msgstr "hoch" +msgstr "Hoch" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" -msgstr "normal" +msgstr "Normal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" -msgstr "auslassen" +msgstr "Überspringen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2562 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "Alle auf hoch festlegen" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "Alle auf normal festlegen" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "Alle überspringen" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Prioritäten speichern" diff --git a/apps/i2psnark/locale/messages_en.po b/apps/i2psnark/locale/messages_en.po index 18e21c25c..601b06e4c 100644 --- a/apps/i2psnark/locale/messages_en.po +++ b/apps/i2psnark/locale/messages_en.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: I2P i2psnark\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-09 19:27+0000\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" "PO-Revision-Date: 2010-06-15 14:09+0100\n" "Last-Translator: duck \n" "Language-Team: duck \n" @@ -18,1221 +18,1376 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 -#: ../java/src/org/klomp/snark/SnarkManager.java:1960 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "" #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1655 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:515 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:517 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:529 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:531 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:554 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:556 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:583 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:585 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:587 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:592 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:647 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:651 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:664 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:668 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:670 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:677 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:693 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:700 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:702 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:719 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:721 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:728 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:738 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:770 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:780 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:826 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:904 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:907 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:916 -#: ../java/src/org/klomp/snark/SnarkManager.java:1692 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:938 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "" #. TODO - if the existing one is a magnet, delete it and add the metainfo instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:957 -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/SnarkManager.java:1140 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:162 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:963 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:965 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and " "DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:968 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:970 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " "disabled, you should enable open trackers or DHT before starting the torrent." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:992 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:999 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:186 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1011 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" +msgid "Torrent added and started: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1013 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" +msgid "Torrent added: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1069 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:89 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1075 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " "succeed until you start another torrent, enable open trackers, or enable DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1079 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1111 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1150 -#: ../java/src/org/klomp/snark/SnarkManager.java:1173 -#: ../java/src/org/klomp/snark/SnarkManager.java:1611 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" +msgid "Too many files in \"{0}\" ({1})!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1402 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1404 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" +msgid "No pieces in \"{0}\"!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1406 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" +msgid "Too many pieces in \"{0}\", limit is {1}!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." +msgid "Pieces are too large in \"{0}\" ({1}B)!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1409 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1411 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" +msgid "Torrent \"{0}\" has no data!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1419 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1435 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1456 -#: ../java/src/org/klomp/snark/SnarkManager.java:1474 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" +msgid "Torrent stopped: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1495 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1503 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1534 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1556 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1607 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1608 -#: ../java/src/org/klomp/snark/SnarkManager.java:1837 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1623 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1686 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1836 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:126 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1860 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1923 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1942 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:77 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:99 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:153 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:174 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:176 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:184 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:247 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260 -msgid "Router is down" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 -msgid "Torrents" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1477 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2242 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287 -msgid "Refresh page" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:295 -msgid "Forum" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" msgstr "" #: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 +msgid "Refresh page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 +msgid "Forum" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:345 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2427 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:423 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2236 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2256 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:445 -msgid "ETA" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:450 -msgid "Downloaded" -msgstr "" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:461 -msgid "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:467 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 -msgid "RX Rate" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:476 -msgid "Up Rate" -msgstr "" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:479 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:510 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "" msgstr[1] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "" msgstr[1] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "" msgstr[1] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:968 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2018 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2019 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1025 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "" -#. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2021 +#. "\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1085 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1207 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1209 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1254 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "" msgstr[1] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1234 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2369 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1266 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1272 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1296 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1404 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1418 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1435 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1438 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1458 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1528 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1552 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1607 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1624 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1677 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or " "info hash" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1685 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1688 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1690 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1720 -msgid "File or directory to seed (must be within the specified path)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1747 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2033 -msgid "Configuration" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1784 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1788 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1796 -msgid "Auto start" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1800 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1804 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1817 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1830 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1836 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1844 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1868 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1875 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1888 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed " "in the torrent file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1892 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1896 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1912 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1918 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1926 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1931 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1951 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1973 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2009 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2049 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2057 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "" msgstr[1] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2058 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "" msgstr[1] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2265 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2311 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2320 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2330 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2340 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2347 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2357 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2421 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2423 -msgid "Size" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2364 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2381 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2386 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2390 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2413 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2417 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2480 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2543 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2562 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "" diff --git a/apps/i2psnark/locale/messages_es.po b/apps/i2psnark/locale/messages_es.po index 99de0a978..46afe9bf5 100644 --- a/apps/i2psnark/locale/messages_es.po +++ b/apps/i2psnark/locale/messages_es.po @@ -2,9 +2,10 @@ # Copyright (C) 2009 The I2P Project # This file is distributed under the same license as the i2psnark package. # To contribute translations, see http://www.i2p2.de/newdevelopers -# +# # Translators: # "blabla", 2011 +# blabla , 2015 # blabla , 2012 # Daniel Mustieles , 2012-2013 # ducki2p , 2011 @@ -13,1288 +14,1397 @@ # mixxy, 2011 # punkibastardo , 2011, 2012 # punkibastardo , 2011 -# strel, 2013 -# trolly, 2013 +# strel, 2013-2015 +# Trolly, 2013 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 19:59+0000\n" -"PO-Revision-Date: 2013-11-28 18:48+0000\n" -"Last-Translator: strel\n" -"Language-Team: Spanish (http://www.transifex.com/projects/p/I2P/language/" -"es/)\n" -"Language: es\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" +"Last-Translator: kytv \n" +"Language-Team: Spanish (http://www.transifex.com/otf/I2P/language/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "No hay más torrents intercambiandose." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "Túnel I2P cerrado." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Enlace magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "El límite total de usuarios subiendo ha cambiado a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "El límite mínimo total de usuarios subiendo es {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "El límite de ancho de banda de subida cambió a {0} KB/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "El límite mínimo de ancho de banda de subida es {0} KB/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "El retardo en el arranque cambió a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Hora de actualización cambiado a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Actualización deshabilitada" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Tamaño de página cambiado a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "La carpeta de datos tiene que ser una ruta absoluta" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "La carpeta de datos no existe" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "No es una carpeta" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "No se pudo leer" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Carpeta de datos cambiada a {0} " -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" -msgstr "" -"Los cambios de I2CP (protocolo cliente I2P) y túnel serán efectivos después " -"de detener todos los torrents" +msgstr "Los cambios de I2CP (protocolo cliente I2P) y túnel serán efectivos después de detener todos los torrents" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "Opciones I2CP cambiadas a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Desconectando destino I2CP antiguo" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Preferencias de I2CP cambiadas a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" -msgstr "" -"No se pudo conectar usando las nuevas preferencias de I2CP (protocolo " -"cliente I2P), volviendo a las antiguas" +msgstr "No se pudo conectar usando las nuevas preferencias de I2CP (protocolo cliente I2P), volviendo a las antiguas" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "¡No se pudo reconectar usando las preferencias antiguas!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Reconectado con el nuevo destino I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "El escuchador de I2CP se reinició para \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Los ficheros nuevos serán públicamente legibles" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Los ficheros nuevos no serán públicamente legibles" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Arranque automático activado" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Arranque automático desactivado" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." -msgstr "" -"Trackers (rastreadores) abiertos activados - requiere reiniciar el torrent " -"para que sea efectivo." +msgstr "Trackers (rastreadores) abiertos activados - requiere reiniciar el torrent para que sea efectivo." -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." -msgstr "" -"Trackers (rastreadores) abiertos desactivados - requiere reiniciar el " -"torrent para que sea efectivo." +msgstr "Trackers (rastreadores) abiertos desactivados - requiere reiniciar el torrent para que sea efectivo." -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "DHT habilitada." -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "DHT deshabilitada." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" -msgstr "" -"Cambiar la DHT (tabla de hash distribuida) requiere cerrar el túnel y volver " -"a abrirlo" +msgstr "Cambiar la DHT (tabla de hash distribuida) requiere cerrar el túnel y volver a abrirlo" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "Tema {0} cargado, vuelva a la página principal de i2psnark para verlo" -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "La configuración no cambió." -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." -msgstr "" -"La lista de trackers (rastreadores) abiertos cambió - requiere reiniciar el " -"torrent para que sea efectiva." +msgstr "La lista de trackers (rastreadores) abiertos cambió - requiere reiniciar el torrent para que sea efectiva." -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." -msgstr "" -"La lista de trackers (rastreadores) privados cambió - afactará sólo a los " -"torrents creados a partir de ahora." +msgstr "La lista de trackers (rastreadores) privados cambió - afactará sólo a los torrents creados a partir de ahora." -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "No se pudo guardar la configuración en {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Conectando a I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Error al conectar a I2P - ¡compruebe sus preferencias de I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Error: No se pudo añadir el torrent {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "No se pudo abrir \"{0}\"" -#. TODO - if the existing one is a magnet, delete it and add the metainfo instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#. TODO - if the existing one is a magnet, delete it and add the metainfo +#. instead? +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" -msgstr "" -"Ya hay un torrent con esta información de hash (identificador " -"criptográfico): {0}." +msgstr "Ya hay un torrent con esta información de hash (identificador criptográfico): {0}." -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "ERROR - No hay trackers I2P en el torrent privado \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" -"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and " -"DHT only." -msgstr "" -"Advertencia - No hay trackers (rastreadores) I2P en \"{0}\", sólo se " -"anunciará a trackers abiertos I2P y a la DHT (tabla de hash distribuida)." +"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" +" DHT only." +msgstr "Advertencia - No hay trackers (rastreadores) I2P en \"{0}\", sólo se anunciará a trackers abiertos I2P y a la DHT (tabla de hash distribuida)." -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." -msgstr "" -"Advertencia - No hay trackers (rastreadores) I2P en \"{0}\", y los trackers " -"abiertos están deshabilitados. Sólo se anunciará a la DHT." +msgstr "Advertencia - No hay trackers (rastreadores) I2P en \"{0}\", y los trackers abiertos están deshabilitados. Sólo se anunciará a la DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " -"disabled, you should enable open trackers or DHT before starting the torrent." -msgstr "" -"Advertencia - No hay trackers (rastreadores) I2P en \"{0}\", y la DHT (tabla " -"de hash distribuida) y los trackers abiertos están deshabilitados, debe " -"habilitar los trackers abiertos o la DHT antes de iniciar el torrent." +"disabled, you should enable open trackers or DHT before starting the " +"torrent." +msgstr "Advertencia - No hay trackers (rastreadores) I2P en \"{0}\", y la DHT (tabla de hash distribuida) y los trackers abiertos están deshabilitados, debe habilitar los trackers abiertos o la DHT antes de iniciar el torrent." -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "El torrent en \"{0}\" no es válido." -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Fichero torrent borrado: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" +msgstr "ERROR - Sin memoria disponible, no se pudo crear un torrent a partir de {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 +#, java-format +msgid "Torrent added and started: {0}" msgstr "" -"ERROR - Sin memoria disponible, no se pudo crear un torrent a partir de {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent añadido e iniciado: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 -#, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent añadido: \"{0}\"" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Obteniendo {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " -"succeed until you start another torrent, enable open trackers, or enable DHT." -msgstr "" -"Los rastreadores abiertos están desactivados y no hay pares DHT. Es posible " -"que no se puedan obtener para {0} hasta que no inicie otro torrent, active " -"los rastreadores abiertos o active la DHT." +"succeed until you start another torrent, enable open trackers, or enable " +"DHT." +msgstr "Los rastreadores abiertos están desactivados y no hay pares DHT. Es posible que no se puedan obtener para {0} hasta que no inicie otro torrent, active los rastreadores abiertos o active la DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Añadiendo {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Descarga ya en marcha: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "No se pudo copiar el fichero torrent a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Hay demasiados ficheros en \"{0}\" ({1}), ¡borrándolos!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 -#, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" +msgid "Too many files in \"{0}\" ({1})!" msgstr "" -"El fichero torrent \"{0}\" no puede terminar en \".torrent\". ¡borrándolo!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "No hay partes en \"{0}\", ¡borrándolo!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Hay demasiadas partes en \"{0}\", el límite es {1}, ¡borrándolo!" +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Las partes en \"{0}\" ({1}Bytes) son demasiado grandes, ¡borrándolas!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 +#, java-format +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "El límite es de \"{0}\"Bytes" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "El torrent \"{0}\" no contiene datos, ¡borrándolo!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 -#, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" +msgid "Torrent \"{0}\" has no data!" msgstr "" -"Los torrents mayores de \"{0}\"Bytes aún no están soportados, borrando " -"\"{1}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 +#, java-format +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Error: No se pudo eliminar el torrent \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent detenido: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent eliminado: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Añadiendo torrents en {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "El limite de ancho de banda de subida es {0} KB/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Descarga finalizada: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo recibida para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Iniciando el torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Error en el torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "¡No se pudo conectar con I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Abriendo el túnel I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Abriendo el túnel I2P e iniciando todos los torrents ..." -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Deteniendo todos los torrents y cerrando el túnel I2P." -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Cerrando túnel I2P después de avisar a los trackers" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" -msgstr "" -"No hay rastreadores válidos para {0}. ¿Quiere activar los rastreadores " -"abiertos o la DHT?" +msgstr "No hay rastreadores válidos para {0}. ¿Quiere activar los rastreadores abiertos o la DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Actualizando" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Actualizando desde {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Descargar archivo torrent desde {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "El torrent no se pudo obtener desde {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent obtenido desde {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent ya en marcha: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent ya en cola: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "El torrent en {0} no era válido" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - cliente de BitTorrent anónimo" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "El router está caído" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "Torrents" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Configuración" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "Cliente BitTorrent anónimo" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "El router está caído" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrents" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Actualizar página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Foro" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Haga clic en el botón \"Añadir torrent\" para obtener un torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "eliminar mensajes" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Estado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "Ordenado por {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Ocultar pares ('peers')" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Mostrar pares ('peers')" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "Tipo de fichero" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "Llegada" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Tiempo restante estimado" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "Llegada" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "Descargado" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "Receptor" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Descargado" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Tamaño" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "Transmisor" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "Tasa de subida" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Subido" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" -msgstr "Transmisor" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "Tasa de descarga" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Tasa de descarga" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "Tasa de descarga" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "Tasa de subida" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "Tasa de subida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Tasa de subida" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Detener todos los torrents y el túnel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Detener todos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Iniciar todos los torrents parados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Iniciar todos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Iniciar todos los torrents y el túnel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "No hay torrents cargados." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Totales" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "1 torrent" msgstr[1] "{0} torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "1 par conectado" msgstr[1] "{0} pares conectados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "1 par DHT" msgstr[1] "{0} pares DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "Dest" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "Primera" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Primera página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "Anterior" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Página anterior" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "Siguiente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Página siguiente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Última" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Última página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "No se pudo crear el directorio de datos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "No puede añadir un torrent {0} dentro de otro torrent: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "URL no válida: debe comenzar con \"http://\", \"{0}\", o \"{1}\"." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet borrado: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Fichero torrent borrado: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Descarga borrada: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Fichero de datos borrado: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "No se pudo borrar el fichero de datos: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "No se pudo borrar la carpeta {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Carpeta borrada: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "No se pudo añadir un torrent que acaba en \".torrent\": {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "Un torrent con este nombre ya está intercambiandose: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "No puede añadir un torrent que incluye un directorio I2P: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "No puede añadir un torrent {0} que incluye otro torrent: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" -msgstr "" -"Error - No se pueden incluir trackers alternativos sin un tracker principal" +msgstr "Error - No se pueden incluir trackers alternativos sin un tracker principal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" -msgstr "" -"Error - No se pueden mezclar trackers privados y públicos en un torrent" +msgstr "Error - No se pueden mezclar trackers privados y públicos en un torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent creado para \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" -msgstr "" -"Muchos trackers (rastreadores) I2P requieren que registre los nuevos " -"torrents antes del seeding (sembrado) - por favor hágalo antes de iniciar " -"\"{0}\"" +msgstr "Muchos trackers (rastreadores) I2P requieren que registre los nuevos torrents antes del seeding (sembrado) - por favor hágalo antes de iniciar \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Error al crear un torrent para \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "No se pudo crear un torrent para los datos inexistentes: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Error al crear torrent - ha de introducir un fichero o carpeta" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Borrar seleccionados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Guardar configuración de tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Eliminado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Añadir tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Introduzca nombre y URLs de tracker (rastreador) válidos" -#. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. "\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Restaurar predeterminados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Trackers (rastreadores) predeterminados restaurados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Comprobando" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Asignando" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Error del tracker (rastreador)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "1 par" msgstr[1] "{0} pares" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Iniciando" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Sembrando" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Completo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" -msgstr "Aceptar" +msgstr "Bien" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Estancado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Sin pares" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Detenido" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Detalles del torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Ver ficheros" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Abrir fichero" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Detener el torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Detener" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Iniciar el torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Iniciar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" -msgstr "" -"Eliminar el torrent de la lista de torrents activos, borrando el fichero ." -"torrent" +msgstr "Eliminar el torrent de la lista de torrents activos, borrando el fichero .torrent" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" -msgstr "" -"¿Está seguro de que quiere borrar el fichero \\''{0}\\'' (los datos " -"descargados no serán borrados)?" +msgstr "¿Está seguro de que quiere borrar el fichero \\''{0}\\'' (los datos descargados no serán borrados)?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Eliminar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Borrar el fichero .torrent y el(los) ficheros(s) de datos asociado(s)" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" -msgstr "" -"¿Está seguro de que quiere borrar el torrent \\''{0}\\'' y todos los datos " -"descargados correspondientes?" +msgstr "¿Está seguro de que quiere borrar el torrent \\''{0}\\'' y todos los datos descargados correspondientes?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Borrar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Desconocido" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Semilla (seed)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Sin interés (el par no tiene las partes que necesitamos)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Restringido (el par no nos está permitiendo solicitar partes)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "No interesado (no tenemos las partes que el par precisa)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Restringiendo (no estamos permitiendo al par solicitar partes)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Detalles en el tracker (rastreador) {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Información" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Añadir torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Desde la URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" -"Enter the torrent file download URL (I2P only), magnet link, maggot link, or " -"info hash" -msgstr "" -"Introduzca URL de descarga del fichero torrent (sólo I2P), enlace magnet, " -"enlace maggot, o información de hash" +"Enter the torrent file download URL (I2P only), magnet link, maggot link, or" +" info hash" +msgstr "Introduzca URL de descarga del fichero torrent (sólo I2P), enlace magnet, enlace maggot, o información de hash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Añadir torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "Dir de datos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "Introduzca el directorio en el que guardar los datos (por defecto {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "También puede copiar ficheros .torrent a: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." -msgstr "" -"Eliminar un fichero .torrent provocará que se detengan sus transferencias." +msgstr "Eliminar un fichero .torrent provocará que se detengan sus transferencias." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Crear un torrent" -#. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#. out.write("From file:
\n"); +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Datos a sembrar ('seed')" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" -msgstr "" -"Fichero o carpeta (ha de estar en la ruta especificada) a sembrar ('seed')" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "Fichero o directorio a sembrar (seed) (ruta completa o dentro del directorio {0} ) " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Principal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternativos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Crear torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "ninguno" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "Configuración" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Carpeta de datos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Ficheros legibles por todos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" -msgstr "" -"Si está marcada, otros usuarios pueden acceder a los ficheros descargados" +msgstr "Si está marcada, otros usuarios pueden acceder a los ficheros descargados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "Arranque automático" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "Auto iniciar torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Si está marcado, iniciará automáticamente los torrents se añadan" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Tema" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Hora de actualización" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Nunca" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Retardo al arrancar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minutos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Tamaño de página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Límite total de usuarios subiendo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "pares" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Límite de velocidad de subida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Se recomienda la mitad del ancho de banda disponible." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Mostrar o cambiar ancho de banda del router (enrutador)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Usar también trackers (rastreadores) abiertos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" -"If checked, announce torrents to open trackers as well as the tracker listed " -"in the torrent file" -msgstr "" -"Si está marcado, anuncia los torrents a los trackers (rastreadores) abiertos " -"así como a los listados en el fichero torrent" +"If checked, announce torrents to open trackers as well as the tracker listed" +" in the torrent file" +msgstr "Si está marcado, anuncia los torrents a los trackers (rastreadores) abiertos así como a los listados en el fichero torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Habilitar DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Si está marcada, usar DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Preferencias de entrada" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Preferencias de salida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "Anfitrión I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "Puerto I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "Opciones de I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Guardar configuración" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Nombre" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "URL del sitio web" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "Estándar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Abrir" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Privado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "URL de anunciamientos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Añadir" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "URL de magnet no válida: {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "1 salto" msgstr[1] "{0} saltos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "1 túnel" msgstr[1] "{0} túneles" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Fichero torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "Ubicación de los datos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "Información de hash" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Tracker principal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Lista de trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Comentario" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Creado en" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Creado por" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Enlace de magnet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Torrent privado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "Tamaño" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Finalización" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Restante" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Ficheros" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Partes" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Tamaño de las partes" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Carpeta" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Prioridad" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Subir a la carpeta del siguiente nivel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "¿No se encotró el fichero torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "¿No se encontró el fichero en el torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "completo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "restante" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Alta" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Saltar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "Configurar todos a alto " + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "Configurar todos a normal" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "Omitir todos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Guardar prioridades" diff --git a/apps/i2psnark/locale/messages_fr.po b/apps/i2psnark/locale/messages_fr.po index 7de66f204..9b64f87fa 100644 --- a/apps/i2psnark/locale/messages_fr.po +++ b/apps/i2psnark/locale/messages_fr.po @@ -11,237 +11,251 @@ # Boxoa590, 2013 # Boxoa590, 2012 # jackjack , 2011 -# Towatowa441, 2013-2014 +# syl_, 2015 +# Towinet, 2013-2015 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-09 19:27+0000\n" -"PO-Revision-Date: 2014-01-23 06:59+0000\n" -"Last-Translator: Towatowa441\n" -"Language-Team: French (http://www.transifex.com/projects/p/I2P/language/fr/)\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:50+0000\n" +"Last-Translator: Towinet\n" +"Language-Team: French (http://www.transifex.com/otf/I2P/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 -#: ../java/src/org/klomp/snark/SnarkManager.java:1960 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Il n'y a plus de torrents en fonctionnement." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "Tunnel I2P fermé." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1655 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:515 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Limite totale uploaders modifiée à : {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:517 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "La limite de nombre minimal d''uploaders est {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:529 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Limite d’envoi modifiée à : {0} ko/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:531 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "La limite minimale d’envoi est {0} ko/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Délai de démarrage modifié à {0} minutes" -#: ../java/src/org/klomp/snark/SnarkManager.java:554 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Temps de rafraîchissement changé pour {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:556 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Rafraîchissement désactivé" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Taille de la page changée pour {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "Répertoire des données doit être un chemin absolu" -#: ../java/src/org/klomp/snark/SnarkManager.java:583 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "Répertoire de données n'existe pas" -#: ../java/src/org/klomp/snark/SnarkManager.java:585 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "Pas un répertoire" -#: ../java/src/org/klomp/snark/SnarkManager.java:587 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "Illisible" -#: ../java/src/org/klomp/snark/SnarkManager.java:592 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Répertoire des données changé pour {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:647 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "Les modifications sur I2CP et les tunnels seront pris en compte après avoir arrêté tous les torrents" -#: ../java/src/org/klomp/snark/SnarkManager.java:651 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "Options I2CP changées pour {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Déconnexion des anciennes destination I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Les paramètres I2CP ont été changés à {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:664 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Impossible de se connecter avec les nouveaux paramètres, retour à l'ancienne configuration I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:668 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Impossible de se reconnecter avec les anciens paramètres!" -#: ../java/src/org/klomp/snark/SnarkManager.java:670 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Reconnexion sur la nouvelle destination I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:677 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "Écouteur I2CP redémarré pour \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Les nouveaux fichiers seront publiquement lisibles" -#: ../java/src/org/klomp/snark/SnarkManager.java:693 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Les nouveaux fichiers ne seront pas publiquement lisibles" -#: ../java/src/org/klomp/snark/SnarkManager.java:700 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Démarrage automatique activé" -#: ../java/src/org/klomp/snark/SnarkManager.java:702 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Démarrage automatique désactivé" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "Tri intelligent permis" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "Tri intelligent non-permis" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." -msgstr "Open trackers activés - redémarrage des torrents requis pour prise en compte." +msgstr "Trackers ouverts activés - redémarrage des torrents requis pour prise en compte." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." -msgstr "Open trackers désactivés - redémarrage des torrents requis pour prise en compte." +msgstr "Trackers ouverts désactivés - redémarrage des torrents requis pour prise en compte." -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "DHT activée." -#: ../java/src/org/klomp/snark/SnarkManager.java:719 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "DHT désactivée." -#: ../java/src/org/klomp/snark/SnarkManager.java:721 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "Le changement DHT nécessite la fermeture puis réouverture du tunnel" -#: ../java/src/org/klomp/snark/SnarkManager.java:728 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "Thème {0} chargé, revenez à la page d''accueil d''i2psnark pour voir comme il est beau !" -#: ../java/src/org/klomp/snark/SnarkManager.java:738 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Aucun changement de configuration." -#: ../java/src/org/klomp/snark/SnarkManager.java:770 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." -msgstr "Liste des Open trackers modifiée - redémarrage des torrents requis pour prise en compte" +msgstr "Liste des trackers ouverts modifiée - redémarrage des torrents requis pour prise en compte" -#: ../java/src/org/klomp/snark/SnarkManager.java:780 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Liste tracker privé modifiée - affecte seulement les torrents nouvellement créés." -#: ../java/src/org/klomp/snark/SnarkManager.java:826 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Impossible de sauvegarder la configuration vers {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:904 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Connexion à I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:907 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Erreur de connexion à I2P - Vérifiez vos paramètres I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:916 -#: ../java/src/org/klomp/snark/SnarkManager.java:1692 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Erreur : Impossible d’ajouter le torrent : {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:938 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Impossible d’ouvrir: \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:957 -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/SnarkManager.java:1140 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:162 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Un torrent avec cette empreinte est déjà actif: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:963 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "ERREUR - Pas de trackers I2P dans le torrent privé \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:965 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "Avertissement - Pas de trackers I2P dans \"{0}\", vais annoncer aux trackers I2P ouverts et DHT seulement." -#: ../java/src/org/klomp/snark/SnarkManager.java:968 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "Avertissement - Pas de trackers I2P dans \"{0}\", et les trackers ouverts sont désactivés, vais annoncer à DHT seulement." -#: ../java/src/org/klomp/snark/SnarkManager.java:970 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -249,34 +263,46 @@ msgid "" "torrent." msgstr "Avertissement - Pas de trackers I2P dans \"{0}\", et DHT et les trackers ouverts sont désactivés, vous devriez activer les trackers ouverts ou DHT avant de démarrer le torrent." -#: ../java/src/org/klomp/snark/SnarkManager.java:992 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Le torrent dans \"{0}\" est invalide" -#: ../java/src/org/klomp/snark/SnarkManager.java:999 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:186 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Fichier torrent effacé: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "Fichier torrent déplacé depuis {0} vers {1}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "ERREUR - Mémoire insuffisante, impossible de créer le torrent depuis {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1011 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent ajouté et démarré: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "Torrent ajouté et démarré : {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1013 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent ajouté: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "Torrent ajouté : {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1069 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:89 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Envoi {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1075 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -284,968 +310,1098 @@ msgid "" "DHT." msgstr "Les trackers ouverts sont désactivés et nous n''avons pas de pairs DHT. La recherche de {0} pourrait ne pas réussir jusqu''à ce que vous démarriez un autre torrent, activiez trackers ouverts, ou activeiz DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:1079 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Ajout {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1111 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Téléchargements déjà en cours: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1150 -#: ../java/src/org/klomp/snark/SnarkManager.java:1173 -#: ../java/src/org/klomp/snark/SnarkManager.java:1611 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Impossible de copier le torrent vers {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Trop de fichiers dans \"{0}\" ({1}), suppression! " +msgid "Too many files in \"{0}\" ({1})!" +msgstr "Trop de fichiers dans \"{0}\" ({1}) !" -#: ../java/src/org/klomp/snark/SnarkManager.java:1402 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Le fichier torrent \"{0}\" ne peut pas se terminer par \".torrent\", suppression!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "Le fichier torrent \"{0}\" peut pas finir en \".torrent\" !" -#: ../java/src/org/klomp/snark/SnarkManager.java:1404 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Pas de tronçon dans \"{0}\", suppression!" +msgid "No pieces in \"{0}\"!" +msgstr "Pas de tronçons dans \"{0}\" !" -#: ../java/src/org/klomp/snark/SnarkManager.java:1406 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Trop de tronçons dans \"{0}\" , la limite est {1}, suppression!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "Trop de tronçons dans \"{0}\", la limite est de {1} !" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Les tronçons sont trop larges dans \"{0}\" ({1}B), suppression." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "Les tronçons sont trop grands dans \"{0}\" ({1}B) !" -#: ../java/src/org/klomp/snark/SnarkManager.java:1409 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "La limite est de \"{0}\"octets" -#: ../java/src/org/klomp/snark/SnarkManager.java:1411 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "Le fichier torrent \"{0}\" n'a pas de données, suppression!" +msgid "Torrent \"{0}\" has no data!" +msgstr "Le torrent \"{0}\" n'a pas de donnée !" -#: ../java/src/org/klomp/snark/SnarkManager.java:1419 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Les torrents dont la taille est supérieure à \"{0}\"octets ne sont pas encore supportés, suppression \"{1}\"." +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "Les torrents plus grands que {0}B ne sont pas encore supportés \"{1}\" !" -#: ../java/src/org/klomp/snark/SnarkManager.java:1435 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Erreur: Impossible de supprimer le torrent \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1456 -#: ../java/src/org/klomp/snark/SnarkManager.java:1474 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent arrêté: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "Torrent stoppé : {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1495 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent supprimé: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1503 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Ajout des torrents dans {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1534 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "Limite bande passante haute est {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1556 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Téléchargement terminé: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1607 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo reçue pour {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1608 -#: ../java/src/org/klomp/snark/SnarkManager.java:1837 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Démarrage du torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1623 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Erreur sur torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1686 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Impossible de se connecter à I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1836 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:126 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Ouverture du tunnel I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1860 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." -msgstr "Ouverture du tunnel I2P and démarrage de tous les torrents." +msgstr "Ouverture du tunnel I2P et démarrage de tous les torrents." -#: ../java/src/org/klomp/snark/SnarkManager.java:1923 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Arrêt de tous les torrents et fermeture du tunnel I2P." -#: ../java/src/org/klomp/snark/SnarkManager.java:1942 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Fermeture du tunnel I2P après notification aux trackers." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "Vérification du torrent {0} terminée, maintenant {1} complet" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "Vérification du torrent {0} terminée, inchangé" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "Erreur lors de la vérification du torrent {0}" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Pas de trackers valides pour {0} - activer trackers ouverts ou DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "En cours de mise à jour" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Mise à jour depuis {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:77 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Téléchargement fichier torrent depuis {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:99 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Le torrent n’a pas été reçu de {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:153 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent reçu de {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:174 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent déjà actif: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:176 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent déjà dans la file d''attente: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:184 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Le torrent {0} est invalide" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:247 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Client BitTorrent anonyme" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260 -msgid "Router is down" -msgstr "Le routeur est tombé" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 -msgid "Torrents" -msgstr "Torrents" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1477 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2242 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Configuration" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "Client BitTorrent anonyme" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Le routeur est tombé" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrents" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Rafraîchir la page" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Forum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Cliquer le bouton \"Ajout torrent\" pour aller chercher le torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:345 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "nettoyer messages" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2427 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "État" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "Trier par {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Cacher les pairs" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:423 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Afficher les pairs" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2236 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2256 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "Type de fichier" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "Temps" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Temps restant estimé" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:445 -msgid "ETA" -msgstr "Temps" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:450 -msgid "Downloaded" -msgstr "Téléchargé" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "Reçu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Téléchargé" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Taille" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "Envoyé" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "Ratio en upload" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Envoyé" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:461 -msgid "TX" -msgstr "Envoyé" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "Taux RX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:467 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Taux de téléchargement" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 -msgid "RX Rate" -msgstr "Taux RX" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:476 -msgid "Up Rate" -msgstr "Taux d'envoi" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:479 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "Taux TX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Taux d'envoi" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Arrêter tous les torrents et le tunnel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Arrêter tout" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Démarrer tous les torrents arrêtés" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:510 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Démarrer tout" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Démarrer tous les torrents et le tunnel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Aucun torrent chargé." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Totaux" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "{0} torrent" msgstr[1] "{0} torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "{0} pair connecté" msgstr[1] "{0} pairs connectés" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "1 pair DHT" msgstr[1] "{0} pairs DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "Dest" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "Premier" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Première page" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "Préc" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Page suivante" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "Suivant" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Page suivante" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Dernier" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Dernière page" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "Le répertoire données ne peut pas être créé" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "Ne peut pas ajouter le torrent {0} à l'intérieur d'un autre torrent: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "URL incorrecte - elle doit débuter par \"http://\", \"{0}\", ou \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet supprimé: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Fichier torrent effacé: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Téléchargement effacé: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Fichier de données effacé: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Le fichier de données ne peut être effacé: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Le répertoire n''a pas pu être effacé: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Répertoire effacé: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "Ne peut pas ajouter un torrent se terminant par \".torrent\": {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "Un torrent avec ce nom est déjà en cours: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "Ne peut pas ajouter un torrent incluant un dossier d''I2P: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "Ne peut pas ajouter le torrent {0} incluant un autre torrent: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "Erreur - Ne peut pas inclure de trackers trackers alternatifs sans un tracker primaire" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "Erreur - Ne peut pas mixer dans un torrent trackers public et privés" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent créé pour \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:968 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "De nombreux trackers I2P nécessitent d’enregistrer les nouveaux torrents avant de seeder - faites-le avant de démarrer \"{0}\"!" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Erreur de création du torrent pour \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Impossible de créer un torrent pour des données inexistantes: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Erreur de création du torrent - vous devez saisir un fichier ou un répertoire" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2018 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Effacer les sélectionnés" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2019 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Sauvegarder la configuration du tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1025 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Retiré" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Ajout tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Entrez nom de tracker valide et URLs" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2021 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Restaurer les paramètres d'origine" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1085 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Restaurer les trackers d'origine" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1207 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Vérification" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1209 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Allocation" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Erreur du tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1254 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "{0} pair" msgstr[1] "{0} pairs" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1234 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Démarrage" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Seed en cours" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2369 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Complet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1266 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1272 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Figé" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Pas de pair" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1296 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Arrêté" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Détails du torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Voir les fichiers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Ouvrir fichier" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Arrêter le torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1404 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Arrêter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Démarrer le torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1418 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Démarrer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Enlever le torrent de la liste active, suprression du fichier .torrent" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1435 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "Êtes-vous sûr que vous voulez supprimer le fichier \\''{0}\\'' (les données téléchargées ne seront pas supprimées) ?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1438 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Enlever" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Supprimer le fichier .torrent et le(s) fichier(s) de données associé(s)" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Êtes-vous certain de vouloir supprimer le torrent \\''{0}\\'' ainsi que toutes les données téléchargées ?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1458 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Supprimer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Inconnu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Seed" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1528 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Aucun intérêt (le pair n'a aucun tronçon utile)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "bridé (le pair ne nous permet pas de demander des tronçons)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Pas intéressé (aucun tronçon utile au pair)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1552 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "bridage (nous ne permettons pas au pair de demander un tronçon)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1607 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Détails au tracker {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1624 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Info" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Ajouter torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1677 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Depuis l'URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "Entrez l'URL de téléchargement du fichier torrent (I2P seulement), lien magnet, lien maggot, or l'info hash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1685 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Ajouter torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1688 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "Répertoire données" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "Saisissez le répertoire où sauvegarder les données par défaut (default {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Vous pouvez aussi copier les fichiers .torrent vers {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1690 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "La suppression d'un fichier .torrent entraîne l'arrêt du torrent." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Créer torrent" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Données à seeder" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1720 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Fichier ou répertoire à seeder (doit être dans le chemin spécifié)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "Fichier ou dossier à seeder (chemin complet ou dans le dossier {0} )" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Primaire" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternatifs" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Créer torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1747 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "aucun" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2033 -msgid "Configuration" -msgstr "Configuration" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1784 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Répertoire de données" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1788 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Fichiers lisibles par tous" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Si coché, les autres utilisateurs pourront accéder aux fichiers téléchargés." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1796 -msgid "Auto start" -msgstr "Démarrage automatique" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "Démarrer automatiquement les torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1800 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Si coché, les torrents démarreront automatiquement lors de l'ajout" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1804 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "Triage intelligent de torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "Si coché, ignore des mots tels que 'the' lors du tri" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Thème" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1817 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Temps de rafraîchissement " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1830 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Jamais" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1836 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Délais de démarrage" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minutes" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Taille page" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1844 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1868 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Limite totale d'envoi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "pairs" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1875 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Limite de bande passante en envoi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "La moitié de la bande passante est recommandée." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Consulter ou modifier la bande passante du routeur" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" -msgstr "Utiliser les open trackers aussi" +msgstr "Utiliser également les trackers ouverts" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1888 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Si coché, les torrents seront annoncés vers les open trackers ainsi que vers les trackers indiqués dans le fichier torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1892 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Active DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1896 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Si coché, utilise DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1912 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Paramètres entrants" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1918 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Paramètres sortants" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1926 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "Hôte I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1931 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "Port I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "Options I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1951 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Sauvegarder la configuration" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Nom" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1973 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "URL du site web" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "Standard" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Ouvrir le fichier" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Privé" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "Annoncer URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2009 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Ajout" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2049 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "URL magnet {0} incorrecte" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2057 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "{0} saut" msgstr[1] "{0} sauts" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2058 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "{0} tunnel" msgstr[1] "{0} tunnels" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2265 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Fichier torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "Emplacement donnée" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "Info hachage" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Tracker primaire" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Liste tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2311 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Commentaire" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2320 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Créé" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2330 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Créé par" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2340 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "Ajouté" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "Complété" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Lien magnet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2347 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Torrent privé" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2357 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2421 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2423 -msgid "Size" -msgstr "Taille" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2364 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Finalisation" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Restant" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2381 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Fichiers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2386 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Tronçons" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2390 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Taille des tronçons" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2413 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2417 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "Rafraîchir la page pour des résultats" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "Forcer revérification" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Répertoire" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Priorité" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Vers le répertoire parent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent non trouvé?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2480 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "Fichier non trouvé dans le torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "complet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "restant" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2543 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Haut" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Ignorer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2562 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "Mettre tous à haute" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "Mettre tous à normale" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "Tout sauter" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Sauvegarder les priorités" diff --git a/apps/i2psnark/locale/messages_hu.po b/apps/i2psnark/locale/messages_hu.po index bb14f74c2..e5bb98038 100644 --- a/apps/i2psnark/locale/messages_hu.po +++ b/apps/i2psnark/locale/messages_hu.po @@ -5,236 +5,250 @@ # # Translators: # omgitsadalek , 2013 +# benewfy , 2015 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:06+0000\n" -"PO-Revision-Date: 2013-11-19 23:52+0000\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" "Last-Translator: kytv \n" -"Language-Team: Hungarian (http://www.transifex.com/projects/p/I2P/language/hu/)\n" +"Language-Team: Hungarian (http://www.transifex.com/otf/I2P/language/hu/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hu\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Nincs több futó torrent." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "I2P alagút lezárva." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Mágnes" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Teljes feltöltők korlátja megváltoztatva a következőre: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Teljes feltöltők minimum korlátja a következő: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Feltöltési sávszélesség korlátja megváltoztatva a következőre: {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "A minimum feltöltési sávszélesség korlátja {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Késleltetés indításkor megváltoztatva a következőre: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Frissítési idő a következőre változott: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Frissítés kikapcsolva" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "Az I2CP-re és alagutakra vonatkozó változtatások az összes torrent leállítása után lépnek érvénybe" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "I2CP opciók a következőre lettek változtatva: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Lekapcsolódás a régi I2CP célállomásról" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "I2CP beállítások a következőre változtak: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Sikertelen kapcsolódás az új beállításokat használva, visszatérés a régi I2CP beállításokhoz" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Sikertelen újrakapcsolódás a régi beállításokat használva!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Újracsatlakozva az új I2CP célállomásra" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "I2CP figyelő újraindítva a következőhöz: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Az új fájlok nyilvánosan olvashatók lesznek" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Az új fájlok nyilvánosan nem lesznek olvashatók" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Automatikus indítás engedélyezve" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Automatikus indítás kikapcsolva" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Nyílt követők (tracker) engedélyezve - az érvénybe lépéshez a torrent újraindítása szükséges." -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Nyílt követők (tracker) kikapcsolva - az érvénybe lépéshez a torrent újraindítása szükséges." -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "DHT engedélyezve." -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "DHT letiltva." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} téma betöltve, megtekintéséhez térj vissza az i2psnark főoldalára." -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Beállítások nem lettek megváltoztatva." -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Nyílt Követők (tracker) listája megváltozott - az érvénybe lépéshez a torrent újraindítása szükséges." -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Megváltozott a privát tracker lista - csak az újonnan létrehozott torrentekre vonatkozik." -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Nem sikerült a beállítások mentése a következőre: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Kapcsolódás az I2P-hez" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Hiba az I2P-hez való csatlakozáskor - ellenőrizd az I2CP beállításait!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Hiba: a következő torrent hozzáadása sikertelen: {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "\"{0}\" megnyitása sikertelen" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "A torrent már fut ezzel az infó hash-el: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "HIBA - Nincsenek I2P követők (trackerek) a következő privát torrentben: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -242,34 +256,46 @@ msgid "" "torrent." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Érvénytelen torrent a következőben: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Torrent fájl törölve: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "HIBA - nincs több memória, torrent létrehozása sikertelen a következőből: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent hozzáadva és elindítva: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent hozzáadva: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Leszedés: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -277,968 +303,1098 @@ msgid "" "DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "{0} Hozzáadása" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Futó letöltés: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Nem sikerült a torrent fájl másolása a következőre: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Túl sok fájl a következőben: \"{0}\" ({1}), törlésre kerül!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Torrent fájl \"{0}\" nem végződhet így: \".torrent\", törlésre kerül!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Nincsenek részek a következőben: \"{0}\", törlésre kerül!" +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Túl sok rész a következőben: \"{0}\", a határ {1}, törlésre kerül!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "A részek túl nagyok a következőben: \"{0}\" ({1}B), törlésre kerül." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "A határ {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "\"{0}\" torrent nem tartalmaz adatot, törlésre kerül!" +msgid "Torrent \"{0}\" has no data!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Nincsenek támogatva torrentek, melyek nagyobbak, mint {0}B, \"{1}\" törlésre kerül" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Hiba: a következő torrent eltávolítása sikertelen: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent leállítva: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent eltávolítva: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Torrentek hozzáadása a következőben: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "Feltöltési sebesség korlát {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "A letöltés befejeződött: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainformáció letöltve a következőhöz: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "{0} torrent indítása" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Hiba a következő torrenten: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Sikertelen csatlakozás az I2P-hez!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Az I2P alagút megnyitása" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Az I2P alagút megnyitás, minden torrent indítás alatt." -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Az összes torrent leállítás és az I2P alagút lezárás alatt." -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Frissítés" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Torrent nem került letöltésre a következőről: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent leszedve a következőről: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent már fut: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent már a sorban van: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Érvénytelen torrent a következő helyen: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Anoním BitTorrent Kliens" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "Router leállva" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "Torrentek" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Beállítások" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Router leállva" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrentek" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Lap újratöltése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Fórum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Torrent leszedéséhez kattints a \"Torrent hozzáadása\" gombra" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "üzenetek törlése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Állapot" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Társak Elrejtése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Társak Megjelenítése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "BIE" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Becsült hátralévő idő" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "BIE" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "Letöltött" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "Be" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Letöltött" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Méret" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "Ki" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Feltöltött" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" -msgstr "Ki" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Letöltési Sebesség" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "Feltöltési Sebesség" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Feltöltési Sebesség" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Minden torrent és az I2P alagút leállítása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Mindet Leállít" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Mind Indítása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Minden torrent és az I2P alagút indítása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Egy torrent sem került betöltésre." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Összesen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "1 torrent" msgstr[1] "{0} torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "1 csatlakozott társ" msgstr[1] "{0} csatlakzott társ" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "" msgstr[1] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "Érvénytelen URL: \"http://\", \"{0}\", vagy \"{1}\" kell kezdődnie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Mágnes észlelve: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Torrent fájl törölve: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Letöltés törölve: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Adatfájl törölve: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Adatfájl törlése nem sikerült: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Könyvtár nem törölhető: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Könyvtár törölve: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent létrehozva a következőnek: \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "Sok I2P követő (tracker) megköveteli az új torrentek regisztrációját táplálás (seed) előtt - kérlek, regisztrálj, mielőtt elindítod a következőt: \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Hiba történt a torrent létrehozásakor \"{0}\" számára" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Nem sikerült torrent létrehozása, nemlétező adat: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Hiba a torrent létrehozásakor - Fájl vagy könyvtár megadása kötelező" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Kijelöltek törlése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Eltávolítva" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Követő (tracker) hozzáadása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Adj meg érvényes követő (tracker) nevet és URL címeket" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Alapértelmezések visszaállítása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Alapértelmezett követők (trackerek) visszaállítva" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Ellenőrzés" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Helyfoglalás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Követő (tracker) Hiba" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "1 társ" msgstr[1] "{0} társ" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Indítás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Táplálás (seeding)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Kész" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "Rendben" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Beragadt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Nincsenek Társak" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Leállítva" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Torrent részletek" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Fájlok megtekintése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Fájl megnyitása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Torrent leállítása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Leállítás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Torrent indítása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Indítás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Torrent eltávolítása az aktív listáról, a .torrent fájl törlésével" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Eltávolítás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr ".torrent fájl törlése a hozzá tartozó adatfájlokkal együtt" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Biztos, hogy törlöd a következő torrentet és az összes letöltött adatot: \\''{0}\\'' ?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Törlés" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Ismeretlen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Táplálás (Seed)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Érdektelen (társ nem rendelkezik számunkra szükséges részekkel)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Eltömődött (a társ nem engedi részek igénylését)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Érdektelen (nem rendelkezünk a társak számára szükséges részekkel)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Eltömődött (a társak számára a részek igénylése nem engedélyezett)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Részletek a következő követőn (tracker): {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Infó" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Torrent Hozzáadása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "URL címről" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "Add meg a torrent fájl letöltési URL-jét (csak I2P), mágnes linket, maggot linket vagy infó hash-t" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Torrent hozzáadása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Másolhatsz .torrent fájlokat a következőhöz is: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "A .torrent fájl eltávolításával meg fog állni." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Torrent létrehozása" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Adat táplálásra (seed)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Fájl vagy könyvtár táplálásra (a megadott útvonalon belül kell lennie)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Követők (trackerek)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Torrent létrehozása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "Beállítások" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Adatkönyvtár" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Mindenki által olvasható fájlok" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Ha be van jelölve, más felhasználók is elérhetik a letöltött fájlokat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "Automatikus indítás" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Ha be van jelölve, a hozzáadott torrentek automatikusan elindulnak" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Téma" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Idő frissítése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Soha" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Indítási késleltetés" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "perc" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Teljes feltöltők korlát" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "társak" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Feltöltési sávszélesség korlát" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "A rendelkezésre álló sávszélesség fele javasolt." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "A router sávszélesség megtekintése vagy megváltoztatása" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Nyílt követőket (tracker) is használjon" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Ha be van jelölve, bejelenti a torrenteket a nyílt követőkre (tracker) és torrent fájlban feltüntetett követőre is" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "DHT engedélyezése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Bejövő Beállítások" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Kimenő Beállítások" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "I2CP hoszt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "I2CP port" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "I2CP opciók" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Beállítások mentése" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Név" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "Weboldal URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Megnyitás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Privát" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "Bejelentési URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Hozzáadás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "Érvénytelen mágnes URL {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "1 ugrás" msgstr[1] "{0} ugrás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "1 alagút" msgstr[1] "{0} alagút" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Torrent fájl" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Mágnes link" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Privát torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "Méret" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Befejezés" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Hátralévő" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Fájlok" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Részek" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Rész méret" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Könyvtár" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Prioritás" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Vissza a felsőbb szintű könyvtárba" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent nem található?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "File nem található a torrentben?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "kész" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "hátralévő" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Magas" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normál" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Kihagy" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Tulajdonságok mentése" diff --git a/apps/i2psnark/locale/messages_it.po b/apps/i2psnark/locale/messages_it.po index 8d165dd3b..b97d05b67 100644 --- a/apps/i2psnark/locale/messages_it.po +++ b/apps/i2psnark/locale/messages_it.po @@ -2,1281 +2,1403 @@ # Copyright (C) 2009 The I2P Project # This file is distributed under the same license as the i2psnark package. # To contribute translations, see http://www.i2p2.de/newdevelopers -# +# # Translators: -# BadCluster , 2012 +# Bad Cluster , 2012 # ColomboI2P , 2012 # coso , 2013 -# fletcherlynd , 2013 +# Fletcher Lynd , 2013 # mkkid , 2011 -# Tony Goodyear , 2012 +# spawned76 , 2012 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:02+0000\n" -"PO-Revision-Date: 2013-11-24 11:15+0000\n" -"Last-Translator: coso \n" -"Language-Team: Italian (http://www.transifex.com/projects/p/I2P/language/" -"it/)\n" -"Language: it\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" +"Last-Translator: kytv \n" +"Language-Team: Italian (http://www.transifex.com/otf/I2P/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "Tunnel I2P chiuso." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Limite del totale di uploaders modificato a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Il minimo limite del totale di uploaders è {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Il minimo limite della banda in up modificato a {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Il minimo limite della banda in up è {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Ritardo startup modificato a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Tempo di aggiornamento cambiato in {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Aggiornamento disabilitato" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Dimensione pagina cambiata a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "La cartella dei dati deve essere un percorso assoluto" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "La cartella dei dati non esiste" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "Non è una cartella" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "Illeggibile" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Cartella dei dati cambiata a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" -msgstr "" -"I cambiamenti di tunnel ed I2CP saranno effettivi dopo aver fermato tutti i " -"torrent " +msgstr "I cambiamenti di tunnel ed I2CP saranno effettivi dopo aver fermato tutti i torrent " -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "Opzioni I2CP modificate in {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "La vecchia destinazione I2CP è in disconnessione" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Impostazioni I2CP cambiate a {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" -msgstr "" -"Impossibile connettersi con le nuove impostazioni, ritorno alle vecchie " -"impostazioni I2CP" +msgstr "Impossibile connettersi con le nuove impostazioni, ritorno alle vecchie impostazioni I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Impossibile riconnettersi con le vecchie impostazioni!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Riconnesso sulla nuova destinazione I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "Listener I2CP riavviato per \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "I nuovi file saranno visibili pubblicamente" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "I nuovi file non saranno visibili pubblicamente" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Autostart abilitato" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Autostart disabilitato" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." -msgstr "" -"Tracker aperti abilitati - è richiesto il riavvio dei torrent perchè la " -"modifica abbia effetto." +msgstr "Tracker aperti abilitati - è richiesto il riavvio dei torrent perchè la modifica abbia effetto." -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." -msgstr "" -"Tracker aperti disabilitati - è richiesto il riavvio dei torrent perchè la " -"modifica abbia effetto." +msgstr "Tracker aperti disabilitati - è richiesto il riavvio dei torrent perchè la modifica abbia effetto." -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "Abilita DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "Disabilita DHT" -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "La modifica DHT richiede il riavvio dei tunnel" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." -msgstr "" -"{0} tema caricato, ritornare alla pagina i2psnark principale per vederlo." +msgstr "{0} tema caricato, ritornare alla pagina i2psnark principale per vederlo." -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Configurazione non modificata." -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." -msgstr "" -"Lista dei tracker aperti modificata - è richiesto il riavvio dei torrent " -"perchè la modifica abbia effetto." +msgstr "Lista dei tracker aperti modificata - è richiesto il riavvio dei torrent perchè la modifica abbia effetto." -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Elenco tracker privati modificato - solo per i nuovi torrent creati." -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Impossibile salvare la configurazione su {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "In connessione a I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Errore nella connessione a I2P - controlla le tue impostazioni I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Errore: Non è stato possibile aggiungere il torrent {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Impossibile aprire \"{0}\"" -#. TODO - if the existing one is a magnet, delete it and add the metainfo instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#. TODO - if the existing one is a magnet, delete it and add the metainfo +#. instead? +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Un torrent con questo info hash è già attivo: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "ERRORE - Nessun tracker I2P nel torrent privato \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" -"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and " -"DHT only." -msgstr "" -"Attenzione - No i2P trackers entranti (in) \"{0}\", sarà richiesto alla rete " -"i2P di aprire solamente trackers e peers DHT" +"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" +" DHT only." +msgstr "Attenzione - No i2P trackers entranti (in) \"{0}\", sarà richiesto alla rete i2P di aprire solamente trackers e peers DHT" -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." -msgstr "" -"Attenzione - No i2P trackers entranti (in) \"{0}\", l'apertura di trackers è " -"disabilitata e sarà richiesto di aprire solo peers DHT" +msgstr "Attenzione - No i2P trackers entranti (in) \"{0}\", l'apertura di trackers è disabilitata e sarà richiesto di aprire solo peers DHT" -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " -"disabled, you should enable open trackers or DHT before starting the torrent." -msgstr "" -"Attenzione - No i2P trackers entranti (in) \"{0}\", l'apertura di trackers e " -"client DHT sono disabilitati. Dovresti, prima di far partire un torrent, " -"abilitare l'apertura di trackers o peers DHT." +"disabled, you should enable open trackers or DHT before starting the " +"torrent." +msgstr "Attenzione - No i2P trackers entranti (in) \"{0}\", l'apertura di trackers e client DHT sono disabilitati. Dovresti, prima di far partire un torrent, abilitare l'apertura di trackers o peers DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Il torrent in \"{0}\" non è valido" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "File torrent eliminato: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "ERRORE - Memoria piena, impossibile creare torrent da {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent aggounto e avviato: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent aggiunto: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Recupero di {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " -"succeed until you start another torrent, enable open trackers, or enable DHT." -msgstr "" -"I trackers aperti sono disabilitati e non ci sono peers DHT. Il recupero {0} " -"potrebbe non riuscire fino a che non fai partire un altro torrent, abiliti i " -"trackers aperti o abiliti il DHT. " +"succeed until you start another torrent, enable open trackers, or enable " +"DHT." +msgstr "I trackers aperti sono disabilitati e non ci sono peers DHT. Il recupero {0} potrebbe non riuscire fino a che non fai partire un altro torrent, abiliti i trackers aperti o abiliti il DHT. " -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "{0} in aggiunta" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Download già attivo: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Fallimento nella copia del file torrent su {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Troppi file in \"{0}\" ({1}), in rimozione!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Il file torrent \"{0}\" non può finire in \".torrent\", in rimozione!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Non ci sono pezzi in \"{0}\", in rimozione!" +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Troppi pezzi in \"{0}\", il limite è {1}, in rimozione!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "I pezzi sono troppo larghi in \"{0}\" ({1}B), in rimozione." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "Il limite è {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "Il torrent \"{0}\" non ha dati, in rimozione!" - -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 -#, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" +msgid "Torrent \"{0}\" has no data!" msgstr "" -"Torrent più grandi di {0}B non sono ancora supportati, \"{1}\" in rimozione" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 +#, java-format +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Errore: Non è stato possibile rimuovere il torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent fermato: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent rimosso: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Torrent in aggiunta in {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "La banda di Upload massima è {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Download completato: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo ricevute per {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Avvio del torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Errore sul torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Impossibile connettersi a I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Apertura tunnel I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Avvio di tutti i torrent e apertura del tunnel I2P in corso. " -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Stop di tutti i torrent e chiusura del tunnel I2P in corso." -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Chiusura tunnel I2P dopo la notifica ai trackers." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Trackers non validi {0} - abilitare i trackers aperti o il DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Aggiornamento" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Aggiornamento da {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Download file torrent da {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Il torrent non è stato recuperato da {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent recuperato da {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent già avviato: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent già in coda: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Il torrent a {0} non è stato valido" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Client BitTorrent Anonimo" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "Il router non è in funzione" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "Torrent" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Configurazione" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Il router non è in funzione" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Ricarica pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Forum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Clicca il bottone \"Aggiungi torrent\" per scaricare il torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "pulisci messaggi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Stato" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Nascondi Peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Mostra Peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "ETA" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Stima del tempo rimanente" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "ETA" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "Scaricato" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "RX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Scaricato" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Dimensione" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "TX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Inviato" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" -msgstr "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "Velocità Ricezione (RX) " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Tasso di Download" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "Velocità Ricezione (RX) " - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "Tasso di Upload" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "Velocità Trasmissione (TX)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Tasso di Upload" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Ferma tutti i torrent e il tunnel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Ferma Tutto" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Avvia tutti i torrent fermati" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Avvia Tutti" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Avvia tutti i torrent e il tunnel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Nessun torrent caricato." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Totali" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "1 torrent" msgstr[1] "{0} torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "1 peer connesso" msgstr[1] "{0} peer connessi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "uno: 1 DHT peer" msgstr[1] "altri: {0} DHT peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "Primo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Prima pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "Ind" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Pagina precedente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "Avanti" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Pagina successiva" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Ultimo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Ultima pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "URL non valido: Deve cominciare con \"http://\", \"{0}\", o \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet eliminato: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "File torrent eliminato: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Downloads cancellati: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "File di dati eliminato: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Non è stato possibile eliminare il file di dati: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "La Cartella non può essere cancellata: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Cartella cancellata: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" -msgstr "" -"Errore - Impossibile includere tracker alternativi senza un tracker primario" +msgstr "Errore - Impossibile includere tracker alternativi senza un tracker primario" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" -msgstr "" -"Errore - Impossibile fare un mix di tracker privati e pubblici in un torrent" +msgstr "Errore - Impossibile fare un mix di tracker privati e pubblici in un torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent creato per \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" -msgstr "" -"Molti tracker I2P ti richiedono di registrare nuovi torrent prima del " -"seeding - per cortesia fallo, prima di avviare \"{0}\"" +msgstr "Molti tracker I2P ti richiedono di registrare nuovi torrent prima del seeding - per cortesia fallo, prima di avviare \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Errore nella creazione di un torrent per \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Impossibile creare un torrent per i dati nonesistenti: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" -msgstr "" -"Errore nella creazione del torrent - devi inserire un file o una directory" +msgstr "Errore nella creazione del torrent - devi inserire un file o una directory" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Elimina selezionati" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Salva configurazione tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Rimosso" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Aggiungi tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Inserisci nome e URL validi per il tracker" -#. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. "\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Ripristina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Ripristina tracker di default" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Controllo (Check)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Allocando" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Errore del Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "1 peer" msgstr[1] "{0} peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "In partenza" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Seeding" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Completo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "In Stallo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Nessun Peer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Fermato" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Dettagli torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Vedi files" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Apri file" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Ferma il torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Ferma" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Avvia il torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Avvia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Rimuovi il torrent dalla lista attiva eliminando il file .torrent" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" -msgstr "" -"Sei sicuro di voler cancellare il file \\\"{0}\\\" (i dati scaricati non " -"verranno cancellati)?" +msgstr "Sei sicuro di voler cancellare il file \\\"{0}\\\" (i dati scaricati non verranno cancellati)?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Rimuovi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Elimina il file .torrent e i file dati associati" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" -msgstr "" -"Sei sicuro di voler eliminare il torrent \\\"{0}\\\" e tutti i dati " -"scaricati?" +msgstr "Sei sicuro di voler eliminare il torrent \\\"{0}\\\" e tutti i dati scaricati?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Elimina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Sconosciuto" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Seed" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Non interessante (Il peer non ha pezzi di nostro interesse)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Soffocato (Il peer non ci sta permettendo di richiedere pezzi)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Non interessato (Non abbiamo pezzi di interesse per il peer)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Soffocando (Non stiamo permettendo al peer di richiedere pezzi)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Dettagli al tracker {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Info" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Aggiungi Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Da URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" -"Enter the torrent file download URL (I2P only), magnet link, maggot link, or " -"info hash" -msgstr "" -"Inserisci l'URL del file torrent da scaricare (solo I2P), link magnet, link " -"maggot o info hash" +"Enter the torrent file download URL (I2P only), magnet link, maggot link, or" +" info hash" +msgstr "Inserisci l'URL del file torrent da scaricare (solo I2P), link magnet, link maggot o info hash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Aggiungi torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Puoi anche copiare files .torrent su: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Rimuovere un .torrent lo fermerà." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Crea Torrent" -#. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#. out.write("From file:
\n"); +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Dati da mandare in seed" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" msgstr "" -"File o cartella da mandare in seed (dev'essere all'interno del percorso " -"specificato)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Primario" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternativi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Crea torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "nessuno" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "Configurazione" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Directory dati" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "File visibili da tutti" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Se selezionato, gli altri utenti potrebbero accedere ai file scaricati" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "Avvio automatico" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Se selezionato, avvia automaticamente torrent che vengono aggiunti" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Tema" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Tempo di aggiornamento" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Mai" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Ritardo di avvio" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minuti" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Dimensione pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Limite di uploader totale" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Limite di banda in upload" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Raccomandata metà della banda disponibile." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Vedi o cambia la banda del router" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Usa anche tracker aperti" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" -"If checked, announce torrents to open trackers as well as the tracker listed " -"in the torrent file" -msgstr "" -"Se selezionato, annuncia i torrent sia a tracker aperti che ai tracker " -"elencati nel file torrent " +"If checked, announce torrents to open trackers as well as the tracker listed" +" in the torrent file" +msgstr "Se selezionato, annuncia i torrent sia a tracker aperti che ai tracker elencati nel file torrent " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Abilita DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Se selezionato, usa DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Impostazioni d'Entrata" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Impostazioni d'Uscita" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "Host I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "Porta I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "Opzioni I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Salva configurazione" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Nome" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "URL Sitoweb" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Apri" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Privato" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "URL Announce" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Aggiungi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "Magnet URL {0} non valido" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "1 hop" msgstr[1] "{0} hop" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "1 tunnel" msgstr[1] "{0} tunnel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "File torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Tracker primario" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Elenco dei tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Commento" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Creato" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Creato da" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Link magnet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Torrent privato" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "Dimensione" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Completamento" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Rimanente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Files" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Pezzi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Dimensione pezzo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Cartella" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Priorità" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Fino a cartella di livello superiore" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent non trovato?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "File non trovato nel torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "completo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "rimanente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Alto" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normale" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Salta" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Salva priorità " diff --git a/apps/i2psnark/locale/messages_nb.po b/apps/i2psnark/locale/messages_nb.po index e4b74539e..33e6ff25e 100644 --- a/apps/i2psnark/locale/messages_nb.po +++ b/apps/i2psnark/locale/messages_nb.po @@ -4,237 +4,250 @@ # To contribute translations, see http://www.i2p2.de/newdevelopers # # Translators: -# mikalv , 2013 +# Mikal , 2013 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:06+0000\n" -"PO-Revision-Date: 2013-11-19 23:52+0000\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" "Last-Translator: kytv \n" -"Language-Team: Norwegian Bokmål (http://www.transifex.com/projects/p/I2P/language/nb/)\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/otf/I2P/language/nb/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nb\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "I2P tunnelen lukket." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Total opplaster grense satt til {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Minimum total opplaster grense er {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Opp båndbredde endret til {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Minimum opp båndbredde grense er {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Oppstart utsettelse sett til {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Oppdaterings tid endret til {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Oppdatering skrudd av" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "I2CP og tunnel endringer vil ta effekt etter sopping av alle torrents" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "I2CP instillinger endret til {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Frakobler fra gammel I2CP destinasjon" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "I2CP instillinger endret til {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Umulig å få tilkobling med de nye instillingene, går tilbake til de gamle I2CP instillingene" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Umulig å koble seg til på nytt med gammle instillinger!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Gjentilkobler på den nye I2CP destinasjonen" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "I2CP lytter omstartet for \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Nye filer vil bli lesbar for alle" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Nye filer vil ikke bli lesbar for alle" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Autostart er skrudd på" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Autostart er avslått" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Skru på åpne trackers - krever torrent omstart for å ta effekt." -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Skru av åpne trackers - krever torrent omstart for å ta effekt." -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "DHT skrudd på" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "DHT skrudd av" -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "DHT endring krever tunnel avslutting og gjennåpning" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} tema lastet, returner til hovedsiden for i2psnart for å se." -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Konfigurasjon uendret." -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Åpen tracker listen endret - torrent omstart kreves før det tar effekt." -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Privat tracker list endret - vil kun påvirke ny opprettet torrent filer." -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Umulig å lagre konfigurasjon til {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Kobler til I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Feil ved tilkobling til I2P - Sjekk dine I2CP instillinger!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Feil: kan ikke legge til torrenten {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Kan ikke åpne \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Torrent med samme info hash kjører allerede: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "FEIL - Ingen I2P trackers i privat torrent \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "Advarsel - Ingen I2P trackers i \"{0}\", vil bare annonsere til I2P åpne trackers og DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "Advarsel - Ingen I2P tracker i \"{0}\", og åpne trackers er skrudd av, vil annonsere kun på DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -242,34 +255,46 @@ msgid "" "torrent." msgstr "Advarsel - Ingen I2P trackers i \"{0}\", og DHT og åpne trackers er avskrudd, du burde skru på åpen tracker eller DHT før du starter torrenten." -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Torrent i \"{0}\" er ugyldig" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Torrent fil slettet: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "FEIL - Tomt for minne, kan ikke lage torrent fra {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent lagt til og startet: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent lagt til: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Henter {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -277,968 +302,1098 @@ msgid "" "DHT." msgstr "Åpne trackers er skrudd av og vi har ingen DHT peers. Mottak av {0} blir muligens ikke fullført før du starter en annen torrent, starter åpne trackers, eller DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Legger til {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Nedlastning kjører alt: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Feilet med å kopiere torrent fil til {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "For mange filer i \"{0}\" ({1}), sletter det!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Torrent filen \"{0}\" kan ikke avsluttes i \".torrent\", sletter den!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Ingen biter i \"{0}\", sletter den!" +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "For mange biter i \"{0}\", grensen er {1}, sletter den!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Bitene er for store i \"{0}\" ({1}B), sletter den." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "Grensen er {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "Torrent \"{0}\" har ingen data, sletter den!" +msgid "Torrent \"{0}\" has no data!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Torrents større enn {0}B er ikke supportet ennå, sletter \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Feil: kan ikke fjerne torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent stoppet: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent fjernet: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Legger til torrents i {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "Opp hastighet grense er {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Nedlastning fullført: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Meta informasjon mottatt for {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Starter opp torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Feil i torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Umulig å koble til I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Åpner I2P tunnelen" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Åpner I2P tunnelen og starter alle torrents." -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Stopper alle torrents og lukker I2P tunnelen." -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Lukker I2P tunnel etter beskjed til trackers." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Ingen valid tracker for {0} - skru på åpne trackers eller DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Oppdaterer" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Oppdaterer fra {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Last ned torrent file fra {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Torrent var ikke mottatt fra {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent hentet fra {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent kjører allerede: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent allerede i kø: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Torrent ved {0} var ikke valid" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Anonym BitTorrent Klient" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "Ruter er nede" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "Torrents" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Konfigurasjon" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Ruter er nede" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrents" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Oppdater side" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Forum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Klikk \"Legg til trorrent\" knappen for å motta torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "fjern meldinger" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Status" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Gjem peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Vis peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "ETA" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Beregnet tid som gjenstår" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "ETA" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "Lastet ned" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "RX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Lastet ned" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Størrelse" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "TX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Lastet opp" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" -msgstr "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "RX Fart" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Ned hastighet" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "RX Fart" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "Opp hastighet" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "TX Fart" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Opp hastighet" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Stopp alle torrents og I2P tunellen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Stopp alle" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Start alle" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Start alle torrents og I2P tunellen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Ingen torrent lastet." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Totaler" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "1 torrent" msgstr[1] "{0} torrents " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "1 tilkoblet peer" msgstr[1] "{0} tilkoblet peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "1 DHT peer" msgstr[1] "{0} DHT peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "Ugyldig URL: Den må starte med \"http://\", \"{0}\", eller \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet slettet: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Torrent fil slettet: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Nedlastning slettet: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Data fil slettet: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Data fil kunne ikke bli slettet: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Mappen kunne ikke bli slettet: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Mappe slettet: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent laget for \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "Mange I2P trackers krever at du registerer nye torrents før seeding - Vennligst gjør det før du starter \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Feil ved laging av torrent for \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Kan ikke lage torrent fra den ikke-eksisterende data: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Feil ved opprettelse av torrent - du må velge en fil eller mappe" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Slett markerte" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Lagre tracker konfigurasjon" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Fjernet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Legg til tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Skriv inn valid tracker navn og URLer" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Gjenopprett standarder" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Gjenopprettet standard trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Sjekker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Tildeling" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Tracker Feil" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "1 peer" msgstr[1] "{0} peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Starter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Deler" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Ferdig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Fastlåst" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Ingen Peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Stoppet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Torrent detaljer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Vis filer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Åpne fil" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Stopp torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Stopp" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Start torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Start" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Fjern torrent fra den aktive listen, og slette .torrent filen" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Fjern" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Slett .torrent filen og all tilhørende data fil(er)" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Er du sikker på at du vil slette torrent \\\"{0}\\\" og all nedlastet data?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Slett" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Ukjent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Deler" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Uinteressang (Peeren har ingen biter vi trenger)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Skjult (Peeren gir oss ikke lov til å be om biter)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Uinteresang (Vi har ingen biter peeren trenger)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Hoster (Vi tillater ikke peeren til å be om biter)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Detaljer hos {0} tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Informasjon" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Legg til torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Fra URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "Skriv inn torrent fil nedlastings URL (kun I2P), magnet link, maggot link, eller info hash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Legg til torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Du kan også kopiere .torrent filer til: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Fjerning av .torrent vil få den til å stoppe." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Opprett Torrent" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Data for deling" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Fil eller mappe for deling (den må være inni den spesifiserte stien)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Opprett torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "Konfigurasjon" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Data mappe" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Filer tilgjengelig for alle" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Hvis merket, andre lokale brukere kan få tilgang til nedlastninger" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "Auto start" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Hvis avmerket, vil torrents som blir lagt til automatisk startet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Theme" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Oppdater tid" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Aldri" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Oppstarts utsettelse" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minutter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Total opplaster grense" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Opp båndbredde grense" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Halve tilgjengelige hastigheten er anbefalt." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Vis eller endre router båndbredde" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Bruk åpne trackers også" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Hvis avmerked, annonser torrenter til åpne trackers i tillegg til tracker listen i torrent filen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Skru på DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Hvis markert, bruk DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Inngående instillinger" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Utgående instillinger" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "I2CP vert" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "I2CP port" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "I2CP alternativer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Lagre konfigurasjon" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Navn" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "Webside URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Åpne" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Privat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "Annonserings URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Legg til" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "Invalid magnet URL {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "1 hopp" msgstr[1] "{0} hopp" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "1 tunnel" msgstr[1] "{0} tunneler" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Torrent fil" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Magnet link" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Privat torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "Størrelse" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Fullføring" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Gjennstår" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Filer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Biter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Bit størrelse" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Mappe" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Prioritet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Opp en level i mappe" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent ikke funnet?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "Fil ikke funnet i torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "ferdig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "gjennstår" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Høy" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Dropp" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Lagre prioriteter" diff --git a/apps/i2psnark/locale/messages_nl.po b/apps/i2psnark/locale/messages_nl.po index f5a09996e..c01117700 100644 --- a/apps/i2psnark/locale/messages_nl.po +++ b/apps/i2psnark/locale/messages_nl.po @@ -6,1240 +6,1397 @@ # Translators: # ducki2p , 2011 # foo , 2009 +# Nathan Follens, 2015 +# Nathan Follens, 2015 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:06+0000\n" -"PO-Revision-Date: 2013-11-19 23:52+0000\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" "Last-Translator: kytv \n" -"Language-Team: Dutch (http://www.transifex.com/projects/p/I2P/language/nl/)\n" +"Language-Team: Dutch (http://www.transifex.com/otf/I2P/language/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Er draaien geen torrents meer." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "I2P tunnel gesloten." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" -msgstr "" +msgstr "Magneet" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Totale uploaders limiet gewijzigd in {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Minimum totale uploaders limiet is {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Up bandbreedte limiet gewijzigd in {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Minimum up bandbreedte limiet is {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Opstartvertraging gewijzigd in {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" -msgstr "" +msgstr "Ververstijd gewijzigd naar {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" -msgstr "" +msgstr "Verversen uitgezet" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" -msgstr "" +msgstr "Paginagrootte gewijzigd naar {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" -msgstr "" +msgstr "Data-directory moet een absoluut pad zijn" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" -msgstr "" +msgstr "Data-directory bestaat niet" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" -msgstr "" +msgstr "Geen directory" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" -msgstr "" +msgstr "Onleesbaar" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" -msgstr "" +msgstr "Data-directory gewijzigd naar {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "I2CP en tunnel wijzigingen hebben pas effect na het stoppen van alle torrents" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" -msgstr "" +msgstr "I2CP-opties gewijzigd naar {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Oude I2CP destination wordt afgesloten" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "I2CP instellingen gewijzigd in {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Kan geen connectie maken met de nieuwe instellingen, we keren terug naar oude I2CP instellingen" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Kan niet opnieuw verbinden met de oude instellingen!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Opnieuw verbonden met de nieuwe I2CP destination" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "I2CP listener herstart voor \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" -msgstr "" +msgstr "Nieuwe bestanden zullen publiek bereikbaar zijn" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" -msgstr "" +msgstr "Nieuwe bestanden zullen niet publiek bereikbaar zijn" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Autostart ingeschakeld" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Autostart uitgeschakeld" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Open Trackers ingeschakeld - torrent herstart nodig." -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Open Trackers uitgeschakeld - torrent herstart nodig." -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." -msgstr "" +msgstr "DHT aangezet." -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." -msgstr "" +msgstr "DHT uitgezet." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" -msgstr "" +msgstr "DHT-wijziging vereist afsluiten en opnieuw openen van tunnel" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} thema geladen, ga naar de hoofd i2psnark pagina om deze te bekijken." -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Configuratie ongewijzigd." -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Open Tracker lijst gewijzigd - torrent herstart nodig." -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." -msgstr "" +msgstr "Privé trackerlijst gewijzigd - beïnvloedt enkel nieuw aangemaakte torrents." -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Kan de configuratie niet opslaan in {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Verbinden met I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Fout bij verbinden met I2P - controlleer je I2CP instellingen!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Fout: Kan de torrent {0} niet toevoegen" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Kan \"{0}\" niet openen" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Torrent met deze info hash is al actief: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" -msgstr "" +msgstr "FOUT - Geen I2P-trackers in privé-torrent \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." -msgstr "" +msgstr "Waarschuwing - Geen I2P-trackers in \"{0}\", zal alleen aankondigen aan open trackers en DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." -msgstr "" +msgstr "Waarschuwing - Geen I2P-trackers in \"{0}\", en open trackers zijn uitgezet, zal alleen aankondigen aan DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " "disabled, you should enable open trackers or DHT before starting the " "torrent." -msgstr "" +msgstr "Waarschuwing - Geen I2P-trackers in \"{0}\", en DHT en open trackers zijn uitgezet, je moet open trackers of DHT aanzetten alvorens de torrent te starten." -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Torrent in \"{0}\" is ongeldig" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Torrent bestand verwijderd: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "ERROR - Geen geheugen meer, kan geen torrent maken van {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent toegevoegd en gestart: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent toegevoegd: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Downloaden {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " "succeed until you start another torrent, enable open trackers, or enable " "DHT." -msgstr "" +msgstr "Open trackers zijn uitgezet en we hebben geen DHT peers. Ophalen van {0} zal misschien niet lukken tot je een andere torrent start, open trackers aanzet, of DHT aanzet." -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Toevoegen van {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" -msgstr "" +msgstr "Download is al bezig: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Kan het torrent bestand niet kopieren naar {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Te veel bestanden in \"{0}\" ({1}), wordt verwijderd!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Torrent bestand \"{0}\" kan niet eindigen in \".torrent\", wordt verwijderd!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Geen stukken in \"{0}\", wordt verwijderd!" +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Te veel stukken in \"{0}\", limiet is {1}, wordt verwijderd!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Stukken zijn te groot in \"{0}\" ({1}B), wordt verwijderd." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "Limiet is {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" +msgid "Torrent \"{0}\" has no data!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Torrents groter dan {0}B worden nog niet ondersteund, verwijder \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Fout: Kan de torrent {0} niet verwijderen" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent gestopt: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent verwijderd: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Toevoegen van torrents in {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" -msgstr "" +msgstr "Bandbreedtelimiet omhoog is {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Download gereed: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo ontvangen voor {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Starten met torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" -msgstr "" +msgstr "Fout bij torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Kan niet verbinden met I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" -msgstr "" +msgstr "Bezig met openen van I2P-tunnel" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Openen van de I2P tunnel en starten van alle torrents." -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Stoppen van alle torrents en sluiten van I2P tunnel." -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." +msgstr "Bezig met sluiten van I2P-tunnel na verwittigen van trackers." + +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" msgstr "" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" -msgstr "" +msgstr "Geen geldige trackers voor {0} - open trackers of DHT aanzetten?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" -msgstr "" +msgstr "Bezig met updaten" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" -msgstr "" +msgstr "Bezig met updaten van {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" -msgstr "" +msgstr "Torrent-bestand downloaden van {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Torrent was niet ontvangen van {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent gedownload van {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent draait al: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent zit al in de wachtrij: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Torrent op {0} was niet geldig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Anonieme BitTorrent Client" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "Torrents" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Configuratie" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "Anonieme BitTorrent-cliënt" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Router is uitgeschakeld" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrents" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Ververs pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Forum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" -msgstr "" +msgstr "Klik op de \"Torrent toevoegen\"-knop om de torrent op te halen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" -msgstr "" +msgstr "berichten wissen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Status" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "Sorteren op {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Verberg Peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Toon Peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "Bestandstype" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "ETA" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Schatting resterende tijd" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "ETA" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "Gedownload" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "RX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Gedownload" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Grootte" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "TX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "Upload-ratio" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Geupload" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" -msgstr "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "RX-ratio" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Down Snelheid" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 +msgid "TX Rate" +msgstr "TX-ratio" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 msgid "Up Rate" msgstr "Up Snelheid" -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 -msgid "TX Rate" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Stop alle torrents en de I2P tunnel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Stop Alle" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" -msgstr "" +msgstr "Start alle gestopte torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Start Alle" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Start alle torrents en de I2P tunnel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Geen torrents geladen." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Totalen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "1 torrent" msgstr[1] "{0} torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "1 verbonden peer" msgstr[1] "{0} verbonden peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "1 DHT peer" +msgstr[1] "{0} DHT peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" -msgstr "" +msgstr "Eerste" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" -msgstr "" +msgstr "Eerste pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" -msgstr "" +msgstr "Vorige" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" -msgstr "" +msgstr "Vorige pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" -msgstr "" +msgstr "Volgende" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" -msgstr "" +msgstr "Volgende pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" -msgstr "" +msgstr "Laatste" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" -msgstr "" +msgstr "Laatste pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "Data-directory kan niet aangemaakt worden" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "Kan torrent {0} niet toevoegen binnen andere torrent: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "Ongeldige URL: moet beginnen met \"http://\", \"{0}\", of \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet verwijderd: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Torrent bestand verwijderd: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" -msgstr "" +msgstr "Download verwijderd: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Data bestand verwijderd: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Kan data bestand niet verwijderen: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" -msgstr "" +msgstr "Directory kon niet worden verwijderd: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" -msgstr "" +msgstr "Map verwijderd: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "Kan geen torrent toevoegen die eindig op \".torrent\": {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "Torrent met deze naam is al bezig: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "Kan geen torrent toevoegen die een I2P-directory bevat: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "Kan torrent {0} die een andere torrent bevat niet toevoegen: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" -msgstr "" +msgstr "Fout - Kan geen alternatieve trackers toevoegen zonder een primaire tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" -msgstr "" +msgstr "Fout - Kan privé en publieke trackers in een torrent niet mengen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent gemaakt voor \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "Veel I2P trackers vereisen dat je de nieuwe torrent registreert voor het seeden - doe dit voordat je \"{0}\" start" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Fout bij het maken van een torrent voor \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Kan geen torrent maken voor niet-bestaande data: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Fout bij het maken van de torrent - je moet een bestand of directory invullen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" -msgstr "" +msgstr "Geselecteerde verwijderen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" -msgstr "" +msgstr "Trackerconfiguratie opslaan" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" -msgstr "" +msgstr "Verwijderd" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" -msgstr "" +msgstr "Tracker toevoegen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" -msgstr "" +msgstr "Geef een geldige trackernaam en URLs in" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" -msgstr "" +msgstr "Standaardtrackers herstellen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" -msgstr "" +msgstr "Standaardtrackers hersteld" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" -msgstr "" +msgstr "Bezig met controleren" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" -msgstr "" +msgstr "Bezig met toewijzen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Tracker Fout" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "1 peer" msgstr[1] "{0} peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" -msgstr "" +msgstr "Bezig met starten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Seeding" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Voltooid" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Vastgelopen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Geen Peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Gestopt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Torrent details" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Bekijk bestanden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Open bestand" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Stop de torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Stop" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Start de torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Start" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Verwijder de torrent van de actieve lijst, het .torrent bestand wordt verwijderd" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" -msgstr "" +msgstr "Ben je zeker dat je het bestand \\''{0}\\'' wil verwijderen (gedownloade data zullen niet verwijderd worden)?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Weghalen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Verwijder het .torrent bestand en de gerelateerde data bestand(en)" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Weet je zeker dat je de torrent \\''{0}\\'' en alle gedownloade data wilt verwijderen?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Verwijderen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Onbekend" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Seed" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Niet interessant (De peer heeft geen stukken die we nodig hebben)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Verstikt (De peer laat ons niet toe om stukken op te vragen)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Niet geïnteresseerd (We heben geen stukken die de peer nodig heeft)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Verstikt (We laten de peer niet toe om stukken op te vragen)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Details op de {0} tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Info" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Torrent Toevoegen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Van URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" -msgstr "" +msgstr "Voer de download-URL (alleen I2P), magneetlink, maggotlink of infohash van het torrentbestand in" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Torrent toevoegen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "Datamap" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "Voer de directory om de gegevens in op te slaan in (standaard {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Je kan ook .torrent bestanden kopieren naar: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Verwijderen van een .torrent zorgt dat deze stopt." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Creëer Torrent" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Data om te seeden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Bestand of directory om te seeden (moet binnen het gespecificeerde pad zijn)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "Bestand of directory om te seeden (volledig pad of binnen de directory {0} )" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" -msgstr "" +msgstr "Trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" -msgstr "" +msgstr "Primair" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" -msgstr "" +msgstr "Alternatieven" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Creëer torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" -msgstr "" +msgstr "geen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "Configuratie" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Data directory" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" -msgstr "" +msgstr "Bestanden leesbaar door iedereen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" -msgstr "" +msgstr "Indien aangevinkt hebben andere gebruikers toegang tot de gedownloade bestanden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "Auto start" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "Torrents automatisch starten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Indien aangevinkt, start toegevoegde torrents automatisch" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Thema" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" -msgstr "" +msgstr "Ververstijd" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" -msgstr "" +msgstr "Nooit" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Startup vertraging" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minuten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" -msgstr "" +msgstr "Paginagrootte" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" -msgstr "" +msgstr "torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Totale uploader limiet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "peers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Up bandbreedte limiet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Helft van beschikbare bandbreedte aanbevolen." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Bekijk of wijzig router bandbreedte" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Gebruik ook open trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Indien aangevinkt, kondig torrents ook aan bij de tracker uit het torrent bestand" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" -msgstr "" +msgstr "DHT aanzetten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" -msgstr "" +msgstr "Gebruik DHT indien aangevinkt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Inkomende Instellingen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Uitgaande Instellingen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "I2CP host" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "I2CP poort" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "I2CP opties" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Configuratie opslaan" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" -msgstr "" +msgstr "Naam" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" -msgstr "" +msgstr "Website-URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "Standaard" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Open" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" -msgstr "" +msgstr "Privé" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" -msgstr "" +msgstr "Kondig URL aan" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" -msgstr "" +msgstr "Toevoegen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "Ongeldige magnet URL {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "1 hop" msgstr[1] "{0} hops" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "1 tunnel" msgstr[1] "{0} tunnels" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" -msgstr "" +msgstr "Torrentbestand" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "Datalocatie" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "Infohash" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" -msgstr "" +msgstr "Primaire tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" -msgstr "" +msgstr "Trackerlijst" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" -msgstr "" +msgstr "Opmerking" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" -msgstr "" +msgstr "Aangemaakt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" +msgstr "Aangemaakt door" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Magnet link" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" -msgstr "" +msgstr "Privé-torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "Grootte" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Voltooiing" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" -msgstr "" +msgstr "Resterend" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Bestanden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Stukken" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Stukgrootte" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Directory" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Prioriteit" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Naar bovenliggende directory" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent niet gevonden?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "Bestand niet gevonden in torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "voltooid" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" -msgstr "" +msgstr "resterend" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Hoog" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normaal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Overslaan" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "Stel alle in als hoog" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "Stel alle in als normaal" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "Alle overslaan" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Prioriteiten opslaan" diff --git a/apps/i2psnark/locale/messages_pl.po b/apps/i2psnark/locale/messages_pl.po index f26998956..d5cf89343 100644 --- a/apps/i2psnark/locale/messages_pl.po +++ b/apps/i2psnark/locale/messages_pl.po @@ -7,586 +7,665 @@ # PolishAnon , 2011 # Warton , 2012 # foo , 2009 +# polacco , 2014-2015 # polacco , 2012 -# sebx, 2014 -# Smert , 2013 +# seb, 2014 +# Smert i2p , 2013 +# Taporpo Ne , 2015 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:06+0000\n" -"PO-Revision-Date: 2014-01-01 12:32+0000\n" -"Last-Translator: sebx\n" -"Language-Team: Polish (http://www.transifex.com/projects/p/I2P/language/pl/)\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" +"Last-Translator: kytv \n" +"Language-Team: Polish (http://www.transifex.com/otf/I2P/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Nie ma więcej uruchomionych torrentów." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "Zamknięto tunel I2P." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Ograniczenie liczby uploaderów zmieniono do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Minimalny całkowity limit uploadera: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" -msgstr "Ograniczenie pasma WY zmieniono na: {0} KB/s" +msgstr "Ograniczenie pasma wyjściowego zmieniono na: {0} KB/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" -msgstr "Minimalne pasmo WY to: {0} KB/s" +msgstr "Minimalne pasmo wyjściowe to: {0} KB/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" -msgstr "Opóźnienia startu zmieniono na {0}" +msgstr "Opóźnienie uruchamiania zmieniono na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Czas odświerzania zmieniony na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Odświeżanie wyłączone" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Rozmiar strony zmieniony do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" -msgstr "Katalog danych musi być pełna ścieżką" +msgstr "Katalog danych musi być pełną ścieżką" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "Katalog danych nie istnieje" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "To nie jest katalog" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "Nieczytelne" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Katalog danych zmieniony do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "Zmiany dotyczące I2CP i tuneli będą wprowadzone po zatrzymaniu wszystkich torrentów." -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "Opcje I2CP zmienione na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Rozłączanie starych celów I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Ustawienia I2CP zmienione do: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Nie można połączyć się z nowymi ustawieniami, powrót do starych ustawień I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Nie można się połączyć ze starymi ustawieniami!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Ponowne podłączanie do nowych celów I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "Nasłuch I2CP zrestartowany dla \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Nowe pliki będą publicznie dostępne" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Nowe pliki nie będą publicznie dostępne" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" -msgstr "Włącz automatycznie uruchamianie" +msgstr "Włączono automatyczne uruchamianie" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" -msgstr "Wyłącz automatycznie uruchamianie" +msgstr "Wyłączono automatyczne uruchamianie" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Włączono otwarte trackery - wymagane ponowne uruchomienie torrenta." -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Wyłączono otwarte trackery - wymagane ponowne uruchomienie torrenta." -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "DHT włączone." -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "DHT wyłączone." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "Zmiana DHT wymaga zamknięcia tunelu i jego ponownego otwarcia" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." -msgstr "{0} temat załadowany, powrót do strony głównej i2psnark by zobaczyć." +msgstr "Załadowano temat {0}. Przejdź do strony głównej i2psnark, by zobaczyć." -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Ustawienia niezmienione." -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." -msgstr "Zmieniła się lista otwartych trackerów - wymagane ponowne uruchomienie torrenta." +msgstr "Lista otwartych trackerów została zmieniona – wymagane ponowne uruchomienie torrenta." -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." -msgstr "Prywatna lista trackerów została zmieniona - dotyczy tylko nowo utworzonych torrentów. " +msgstr "Lista prywatnych trackerów została zmieniona – dotyczy tylko nowo utworzonych torrentów." -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Nie można zapisać konfiguracji do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Łączenie z I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Nie można się połączyć z I2P, sprawdź swoje ustawienia I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Błąd: Nie można dodać torrenta {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Nie można otworzyć \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Torrent o tym hashu jest już uruchomiony: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "BŁĄD – brak trackerów w prywatnym torrencie \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." -msgstr "Uwaga - Nie ma trackerów I2P w \"{0}\", zostanie to zameldowane tylko do otwartych I2P trackerów i DHT." +msgstr "Uwaga – Nie ma trackerów I2P w \"{0}\", zostanie to zameldowane tylko do otwartych trackerów i DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." -msgstr "Ostrzeżenie - Brak Trackerów I2P w \"{0}\", i DHT również otwarte trackery są wyłączone, w odniesieniu do DHT tylko." +msgstr "Uwaga – Brak trackerów I2P w \"{0}\", a otwarte trackery są wyłączone. Torrent będzie działał wyłącznie w oparciu o DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " "disabled, you should enable open trackers or DHT before starting the " "torrent." -msgstr "Ostrzeżenie - Brak Trackerów I2P w \"{0}\", i DHT również otwarte trackery są wyłączone, należy włączyć otwarte trackery lub DHT przed rozpoczęciem torrenta. " +msgstr "Uwaga – Brak trackerów I2P w \"{0}\". Otwarte trackery i DHT również są wyłączone. Należy włączyć otwarte trackery lub DHT przed rozpoczęciem torrenta." -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Torrent w \"{0}\" jest niepoprawny" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Plik torrenta usunięto: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" -msgstr "BŁĄD - Brak pamięci, nie można utworzyć pliku torrent z {0}" +msgstr "BŁĄD – Brak pamięci, nie można utworzyć pliku torrent z {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent dodany i uruchomiony: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent dodany: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Pobieranie: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " "succeed until you start another torrent, enable open trackers, or enable " "DHT." -msgstr "Otwarte trackery są wyłączone i nie mamy żadnych DHT peerów. Pobranie z {0} może się nie udać dopóki nie uruchomisz innego torrenta, włączysz otwarte trackery, lub włączysz DHT." +msgstr "Otwarte trackery są wyłączone i nie mamy żadnych peerów DHT. Pobranie z {0} może się nie udać, dopóki nie uruchomisz innego torrenta, włączysz otwarte trackery lub włączysz DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Dodawanie {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Pobieranie już zostało uruchomione: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Nie udało się skopiować pliku torrent do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Za dużo plików w \"{0}\" ({1}), usuwanie go!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Torrent \"{0}\" nie może się kończyć w \".torrent\", usuwanie go!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "W torrencie \"{0}\" nie ma piece'ów, usuwanie go!" +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Za dużo piece''ów w \"{0}\" (limit to {1}), usuwanie go!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Za duże piece''y w torrencie \"{0}\" ({1}B), usuwanie go." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "Granica to {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "cTorrent \"{0}\" nie zawiera danych, usuwanie!" +msgid "Torrent \"{0}\" has no data!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Torrenty większe niż {0}B nie są jeszcze wspierane, usunięcie \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Błąd: nie można usunąć torrenta {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent zatrzymany: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent usunięty: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Dodawanie torrentów w {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" -msgstr "limit transferu połczeń wychodzcych to {0} KBps" +msgstr "Limit transferu połączeń wychodzcych to {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Pobieranie ukończone: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo otrzymane dla {0} " -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Uruchamianie torrenta: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Błąd w torrencie {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Nie można podłączyć się do I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Otwieranie tunelu I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Otwieranie tunelu I2P i uruchamianie wszystkich torrentów." -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." -msgstr "Zatrzymywanie wszystkich torrentów i zamykanie tunelu I2P" +msgstr "Zatrzymywanie wszystkich torrentów i zamykanie tunelu I2P." -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Zamknięcie tunelu I2P po powiadomieniu trackerów." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Brak prawidłowych trackerów dla {0} – włączyć otwarte trackery lub DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Aktualizacja" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Aktualizacja z {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Pobieranie pliku torrent z {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Torrent nie był pobrany z: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent pobrano z {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent już uruchomiony: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent już w kolejce: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Torrent pobrany z {0} jest niepoprawny" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark – anonimowy klient BitTorrent" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "Ruter jest wyłączony" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "Torrenty" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Ustawienia" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "Anonimowy klient protokołu BitTorrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Węzeł jest wyłączony" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrenty" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Odśwież stronę" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Forum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Kliknij \"Dodaj torrent\" by pobrać torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "wyczyść komunikaty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Stan" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "Sortuj wg {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Ukryj peery" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Pokaż peery" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "Rodzaj pliku" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "Pozostało" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Szacowany pozostały czas" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "Pozostało" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "Pobrano" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "RX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Pobrano" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Rozmiar" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "TX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "Współczynnik wysyłania (ratio)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Wysłano" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" -msgstr "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "↓" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Prędkość pobierania" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "Ocena RX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 +msgid "TX Rate" +msgstr "↑" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 msgid "Up Rate" msgstr "Prędkość wysyłania" -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 -msgid "TX Rate" -msgstr "Ocena TX" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Zatrzymaj wszystkie torrenty i tunel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Zatrzymaj wszystkie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Uruchom wszystkie zatrzymane torrenty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Uruchom wszystkie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Uruchom wszystkie torrenty i tunel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Nie załadowano torrentów." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Łącznie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" @@ -594,7 +673,7 @@ msgstr[0] "{0} torrent" msgstr[1] "{0} torrenty" msgstr[2] "{0} torrentów" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" @@ -602,7 +681,7 @@ msgstr[0] "{0} podłączony peer" msgstr[1] "{0} podłączone peery" msgstr[2] "{0} podłączonych peerów" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" @@ -610,174 +689,202 @@ msgstr[0] "{0} peer DHT" msgstr[1] "{0} peery DHT" msgstr[2] "{0} peerów DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 -msgid "First" -msgstr "Pierwszy" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "Cel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 +msgid "First" +msgstr "Pierwsza" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Pierwsza strona" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" -msgstr "Poprzedni" +msgstr "Poprzednia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Poprzednia strona" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" -msgstr "Następny" +msgstr "Następna" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Następna strona" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Ostatnia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Ostatnia strona" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "Katalog nie może zostać utworzony" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "Nie można dodać torrenta {0} wewnątrz innego torrenta {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "Nieprawidłowy URL: musi zaczynać się od \"http://\", \"{0}\" lub \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Odnośnik Magnet usunięty: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Plik torrenta usunięto: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Pobrane usunięte: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Pliki z danymi usunięte: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Nie można usunąć pliku z danymi: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Katalog nie może być usunięty: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Usunięto katalog: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "Nie można dodać torrent kończącego się \".torrent\": {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "Torrent z tą nazwą już jest uruchomiony: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "Nie można dodać torrenta zawierającego katalog I2P: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "Nie można dodać torrenta {0} zawierającego inny torrent {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" -msgstr "Błąd - Nie można dodać alternatywnych trackerów bez głównego trackera" +msgstr "Błąd – Nie można dodać alternatywnych trackerów bez głównego trackera" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" -msgstr "Błąd - Nie można mieszać prywatnych i publicznych trackerów w torrencie" +msgstr "Błąd – Nie można mieszać prywatnych i publicznych trackerów w torrencie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Utworzono torrent dla \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" -msgstr "Wiele trackerów w I2P wymaga zarejestrowania torrenta przed seedowaniem - proszę, zrób tak przed uruchomieniem \"{0}\"" +msgstr "Wiele trackerów w I2P wymaga zarejestrowania torrenta przed seedowaniem – proszę, zrób tak przed uruchomieniem \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Błąd podczas tworzenia torrenta dla: \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Nie można utworzyć torrenta dla nieistniejących danych: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" -msgstr "Błąd przy tworzeniu torrenta - musisz podać plik lub katalog" +msgstr "Błąd przy tworzeniu torrenta – musisz podać plik lub katalog" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Usuń zaznaczone" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Zapisz ustawienia trackerów" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Usunięto" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Dodaj tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Podaj prawidłową nazwę trackera i URL" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Przywróć domyślne" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" -msgstr "Przywróć domyślne trackery" +msgstr "Przywrócono domyślne trackery" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Sprawdzanie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Alokowanie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Błąd trackera" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" @@ -785,356 +892,377 @@ msgstr[0] "{0} peer" msgstr[1] "{0} peery" msgstr[2] "{0} peerów" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Uruchamianie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Seedowanie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Zakończono" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Utknięto" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Brak peerów" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Zatrzymany" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Szczegóły torrenta" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Zobacz pliki" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Otwórz plik" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Zatrzymaj torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Zatrzymaj" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Uruchom torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Uruchom" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Usuń torrent z aktywnej listy, usuwając plik .torrent" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "Czy jesteś pewnien, że chcesz usunąć plik \\''{0}\\'' (pobrane dane nie będą usunięte) ?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Usuń" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Usuń plik .torrent i związane z nim pliki z danymi" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Czy na pewno chcesz usunąć plik \\''{0}.torrent\\'' oraz pobrane dane?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Usuń" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Nieznany" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Seed" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Uninteresting (peer nie ma piece'ów, które potrzebujemy)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Choked (peer nie pozwala nam na prośbę o piece)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Uninterested (nie mamy piece'ów, których peer potrzebuje)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Choking (nie pozwalamy peerowi na prośbę o piece)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Szczegóły na trackerze {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Info" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Dodaj torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Z adresu URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" -msgstr "Wpisz adres URL pliku torrent (I2P tylko), Magnet link, link maggot, lub info hash" +msgstr "Wpisz adres URL pliku torrent (tylko I2P), Magnet link, link maggot lub info hash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Dodaj torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "Katalog na pobrane dane" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "Podaj katalog do zapisu danych (domyślnie: {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." -msgstr "Możesz także skopiować pliki .torrent do: {0}" +msgstr "Możesz także skopiować pliki .torrent do: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Usunięcie pliku .torrent spowoduje jego zatrzymanie." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Utwórz torrent" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Dane do seedowania" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Plik lub katalog do seedowania (musi się znajdować wewnątrz podanej ścieżki)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "Plik lub katalog do seedowania (pełna ścieżka lub katalog wewnątrz \"{0}\")" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Trackery" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Główne" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternatywne" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Utwórz torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "brak" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "Ustawienia" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Katalog z danymi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Pliki dostępne dla wszystkich" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Jeśli zaznaczone, inni użytkownicy mogą mieć dostęp do pobranych plików" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "Automatyczne uruchamianie" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "Uruchamiaj automatycznie torrenty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" -msgstr "Jeśli zaznaczone - automatycznie uruchamiaj dodane torrenty" +msgstr "Jeśli zaznaczone – automatycznie uruchamiaj dodane torrenty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Motyw" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Czas odświerzania" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Nigdy" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Opóźnienie uruchomienia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minuty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Rozmiar strony" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "torrenty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Całkowity limit uploaderów" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "peery" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" -msgstr "Ograniczenie pasma WY" +msgstr "Ograniczenie pasma wyjściowego" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Zalecana połowa dostępnego pasma." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" -msgstr "Zobacz lub zmień pasmo routera" +msgstr "Zobacz lub zmień pasmo węzła" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Używaj również otwartych trackerów" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Jeśli zaznaczone, zgłaszaj torrenty do otwartych trackerów, jak również do trackerów podanych w pliku torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Włącz DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Jeśli zaznaczone, używa DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Tunele wejściowe" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Tunele wyjściowe" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "Adres I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "Port I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "Parametry I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Zapisz ustawienia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Nazwa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "URL strony www" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 -msgid "Open" -msgstr "Otwórz" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "Standardowy" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 +msgid "Open" +msgstr "Otwarty" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Prywatny" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "URL rozgłaszania" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Dodaj" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" -msgstr "Nieprawidłowy URL magnet {0}" +msgstr "Nieprawidłowy link magnet {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" @@ -1142,7 +1270,7 @@ msgstr[0] "{0} skok" msgstr[1] "{0} skoki" msgstr[2] "{0} skoków" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" @@ -1150,106 +1278,135 @@ msgstr[0] "{0} tunel" msgstr[1] "{0} tunele" msgstr[2] "{0} tuneli" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Plik torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 -msgid "Primary Tracker" -msgstr "Główne Trackery" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "Położenie danych" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "Info hash" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 +msgid "Primary Tracker" +msgstr "Główny Tracker" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Lista Trackerów" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Komentarz" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Utworzony" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Utworzony przez" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Link magnet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Prywatny torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "Rozmiar" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" -msgstr "Zkończono" +msgstr "Zakończono" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Pozostało" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Pliki" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Części" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Rozmiar części" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Katalog" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Priorytet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Do katalogu nadrzędnego" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" -msgstr "Torrent not found?" +msgstr "Torrent nie znaleziony?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" -msgstr "File not found in torrent?" +msgstr "Plik nie znaleziony w torrencie?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "zakończono" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "pozostało" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Wysoki" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normalny" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Pomiń" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "Ustaw wszystkie na wysoki" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "Ustaw wszystkie na normalny" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "Pomiń wszystkie" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Zapisz priorytety" diff --git a/apps/i2psnark/locale/messages_pt.po b/apps/i2psnark/locale/messages_pt.po index c764c999c..9b9923ca9 100644 --- a/apps/i2psnark/locale/messages_pt.po +++ b/apps/i2psnark/locale/messages_pt.po @@ -10,240 +10,253 @@ # hxdcmls, 2013 # hxdcmls, 2013 # wtfisthis , 2013 -# rafaelbf, 2013 -# Ruthein , 2012 -# tuliouel, 2013 +# Rafael Ferrari, 2013 +# Ruthein Alex , 2012 +# Tulio Simoes Martins Padilha , 2013 # wicked, 2013 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-09 19:27+0000\n" -"PO-Revision-Date: 2014-01-18 20:22+0000\n" -"Last-Translator: kgtm \n" -"Language-Team: Portuguese (http://www.transifex.com/projects/p/I2P/language/pt/)\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-09 03:40+0000\n" +"Last-Translator: kytv \n" +"Language-Team: Portuguese (http://www.transifex.com/otf/I2P/language/pt/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 -#: ../java/src/org/klomp/snark/SnarkManager.java:1960 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "Túnel I2P fechado" #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1655 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:515 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Limite total de uploaders alterado para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:517 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Limite mínimo de uploaders alterado para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:529 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Largura de banda para a envio alterada para {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:531 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Largura de banda mínima para envio é {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Demora na inicialização alterada para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:554 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Tempo de actualização alterado para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:556 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Actualização desactivada" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Tamanho de pagina alterado para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "Diretório de dados deve ter um caminho absoluto" -#: ../java/src/org/klomp/snark/SnarkManager.java:583 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "Diretório de dados não existe" -#: ../java/src/org/klomp/snark/SnarkManager.java:585 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "Não é um diretório" -#: ../java/src/org/klomp/snark/SnarkManager.java:587 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "Ilegível" -#: ../java/src/org/klomp/snark/SnarkManager.java:592 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Diretório de dados alterado para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:647 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "Mudanças do I2CP e do túnel farão efeito após interromper todos os torrents" -#: ../java/src/org/klomp/snark/SnarkManager.java:651 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "opções de I2cp alteradas para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Desconectando destinação anterior do I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Preferências do I2CP alteradas para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:664 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Conectar-se não foi posível com as novas preferências I2CP, utilizarei as anteriores." -#: ../java/src/org/klomp/snark/SnarkManager.java:668 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Impossível se conectar usando as preferências anteriores!" -#: ../java/src/org/klomp/snark/SnarkManager.java:670 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Conectado com a nova Destinação I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:677 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "Conexão I2CP re-estabelecida para \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Novos ficheiros serão lidos pelo publico" -#: ../java/src/org/klomp/snark/SnarkManager.java:693 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Novos ficheiros não serão lidos pelo publico" -#: ../java/src/org/klomp/snark/SnarkManager.java:700 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Ativado o iniciar automáticamente" -#: ../java/src/org/klomp/snark/SnarkManager.java:702 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Desativado o iniciar automáticamente" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Uso de rastreadores abertos ativado - Para ter efeito é necesário reiniciar os torrentes." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Uso dos rastreadores abertos desativado - Para ter efeito é necesário reiniciar os torrentes." -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "Habilitar DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:719 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "Desabilitar DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:721 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "Mudança no DHT requer fechamento e reabertura do túnel" -#: ../java/src/org/klomp/snark/SnarkManager.java:728 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "Tema {0} foi carregado. Volte no menú principal para vê-lo." -#: ../java/src/org/klomp/snark/SnarkManager.java:738 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Configuração não mudada." -#: ../java/src/org/klomp/snark/SnarkManager.java:770 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Listado de rastreadores abertos mudado - Para ter efeito é necesário reiniciar os torrentes." -#: ../java/src/org/klomp/snark/SnarkManager.java:780 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Lista de rastreadores privados alterada - somente afetará os novos torrentes criados." -#: ../java/src/org/klomp/snark/SnarkManager.java:826 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Não se pode guardar a configuração em {0}." -#: ../java/src/org/klomp/snark/SnarkManager.java:904 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Conectando com I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:907 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Erro ao se conectar com I2P - Verifique a sua configuração I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:916 -#: ../java/src/org/klomp/snark/SnarkManager.java:1692 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Erro: Não se pode adicionar o torrente {0}." #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:938 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Não pode se abrir \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:957 -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/SnarkManager.java:1140 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:162 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "torrente com este info hash já em marcha: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:963 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "ERRO - Não há tracker I2P no torrent privado \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:965 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "Aviso - Nenhum rastreador I2P em \"{0}\", o anúncio será feito apenas por rastreadores I2P abertos e DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:968 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "Aviso - Nenhum rastreador I2P em \"{0}\", e rastreadores I2P abertos estão desabilitados. O anúncio será feito apenas por DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:970 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -251,34 +264,46 @@ msgid "" "torrent." msgstr "Aviso - Nenhum rastreador I2P em \"{0}\", e DHT e rastreadores abertos estão desabilitados. Rastreadores abertos ou DHT devem ser habilitados antes de começar o torrente." -#: ../java/src/org/klomp/snark/SnarkManager.java:992 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "O arquivo .torrent em \"{0}\" não é válido." -#: ../java/src/org/klomp/snark/SnarkManager.java:999 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:186 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Apagado o arquivo torrente: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "ERRO - Não ha espaço suficente, não se pode crear um torrente desde {0}." -#: ../java/src/org/klomp/snark/SnarkManager.java:1011 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "torrente adicionado e iniciado: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1013 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "torrente adicionado: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1069 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:89 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Buscando {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1075 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -286,968 +311,1098 @@ msgid "" "DHT." msgstr "Rastreadores abertos estão desabilitados e não há participantes DHT. Descarregamento de {0} pode não prosseguir enquanto outra torrente não for iniciada, rastreadores abertos forem habilitados ou DHT habilitado." -#: ../java/src/org/klomp/snark/SnarkManager.java:1079 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Adicionando {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1111 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "arquivo já descarregando: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1150 -#: ../java/src/org/klomp/snark/SnarkManager.java:1173 -#: ../java/src/org/klomp/snark/SnarkManager.java:1611 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Não se pode copiar o torrente para {0}." -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Ha arquivos demais no \"{0}\", se apagará ({1}). " +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1402 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "O arquivo de dados do torrente \"{0}\" não pode terminar em \".torrent' e será apagado." +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1404 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Não ha peças no \"{0}\", se apagará." +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1406 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Ha peças demais no \"{0}\" e o limite é {1}. Se apagarão." +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Peças no \"{0}\" são grandes demais ({1}B). Se apagarão." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1409 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "O limite são \"{0}\"Bytes" -#: ../java/src/org/klomp/snark/SnarkManager.java:1411 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "O torrente \"{0}\" não contem dados e será apagado." +msgid "Torrent \"{0}\" has no data!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1419 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "torrentes maiores que \"{0}\" Bytes ainda não funcionam, se apagará \"{1}\"." +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1435 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Erro: Não se pode quitar o torrente \"{0}\"." -#: ../java/src/org/klomp/snark/SnarkManager.java:1456 -#: ../java/src/org/klomp/snark/SnarkManager.java:1474 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "torrente detido: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1495 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "torrente quitado: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1503 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Os torrentes serão adicionados em {0} ..." -#: ../java/src/org/klomp/snark/SnarkManager.java:1534 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "Limite de transmissão de dados é {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1556 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Finalizada a descarga de \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1607 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo recibido para {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1608 -#: ../java/src/org/klomp/snark/SnarkManager.java:1837 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Iniciando o torrente {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1623 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Erro no torrente {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1686 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Impossível de se conectar com I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1836 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:126 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Abrindo o túnel I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1860 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Abrendo o túnel I2P e iniciando os torrentes ..." -#: ../java/src/org/klomp/snark/SnarkManager.java:1923 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Detindo todos os torrentes e fechando o túnel I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1942 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Fechando túnel I2P após notificar os rastreadores." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Nenhum rastreador válido para {0} - habilitar rastreadores abertos ou DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Atualizando" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Atualizando de {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:77 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Descarregando arquivo torrente de {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:99 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Não se pode obter torrente de {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:153 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "torrente obtido de {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:174 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "torrente já em marcha: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:176 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "torrente já na cola: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:184 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "torrente em {0} não foi válido" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:247 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Cliente de BitTorrent Anônimo" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260 -msgid "Router is down" -msgstr "Roteador não está funcionando" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 -msgid "Torrents" -msgstr "torrentes" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1477 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2242 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Preferências" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Roteador não está funcionando" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "torrentes" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Atualizar página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Foro" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Clique no botão \"Adicionar torrent\" para obter o torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:345 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "limpar mensagens" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2427 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Estado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "ocultar parceiros" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:423 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "mostrar parceiros" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2236 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2256 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "Tempo" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Tempo que falta para completar" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:445 -msgid "ETA" -msgstr "Tempo" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:450 -msgid "Downloaded" -msgstr "Descarregado" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "Baixado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Descarregado" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Tamanho" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "Subido" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Subido" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:461 -msgid "TX" -msgstr "Subido" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "Taxa de recepção" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:467 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Taxa de descarga" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 -msgid "RX Rate" -msgstr "Taxa de recepção" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:476 -msgid "Up Rate" -msgstr "Taxa de subida" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:479 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "Taxa de transmissão" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Taxa de subida" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Deter todos os torrentes e o túnel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Deter tudos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Iniciar todos os torrents interrompidos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:510 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Arrancar todos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Iniciar todos os torrentes e o túnel I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Não carregado nenhum torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Total" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "1 torrente" msgstr[1] "{0} torrentes" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "1 parceiro conectado" msgstr[1] "{0} parceiros conectados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "1 parceiros DHT" msgstr[1] "{0} parceiros DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "Prim." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Primeira página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "Ant." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Página anterior" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "Próx." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Próxima página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Últ." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Última página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "Endereço não válido - tem que começar com \"http://\", \"{0}\", ou \"{1}\"." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Apagada o magnet: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Apagado o arquivo torrente: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Download excluído: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Apagado o arquivo de dados: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Não se pode apagar o arquivo de dados: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Pasta não pôde ser excluída: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Pasta excluída: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "Erro - Impossível incluir rastreadores alternativos sem o rastreador primário" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "Erro - Impossível misturar rastreadores públicos e privados num torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "torrente criado para \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:968 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "Muitos rastreadores no I2P exigem que você registre novos torrentes antes de poder semeá-los. Por favor, faça isto antes de iniciar \"{0}\"!" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Erro ao criar o torrente \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Não se pode criar um torrente para dados que não existam: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Erro ao criar o torrente - Tens que especificar um arquivo ou uma pasta." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2018 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Excluir selecionado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2019 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Salvar configurações do rastreador" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1025 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Excluído" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Adicionar tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Insira um nome válido para o tracker e URLs" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2021 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Voltar aos padrões" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1085 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Voltar aos rastreadores padrão" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1207 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Verificando" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1209 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Reservando espaço" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Erro do rastreador" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1254 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "1 parceiro" msgstr[1] "{0} parceiros" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1234 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Iniciando" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "semeando" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2369 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "completo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1266 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1272 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "bem" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "estancado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "sem parceiros" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1296 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "detenido" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Detalhes do torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "mostrar arquivos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "abrir arquivo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Deter o torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1404 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Deter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Iniciar o torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1418 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Iniciar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Retire o torrente da lista ativa, apagando o arquivo .torrent" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1435 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "Tem a certeza que deseja apagar o ficheiro \\\"{0}\\\" (dados transferidos não serão apagados) ?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1438 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Quitar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Apagar o arquivo torrente e o(s) arquivo(s) de dados pertenecentes" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Está seguro de que quer apagar o arquivo torrente \\''{0}\\'' e todos os dados descarregados deste torrente?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1458 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Apagar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "desconhecido" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Semeador" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1528 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "não interessante (O parceiro não tem peças que precisamos.)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "sufocado (De momento o parceiro não está nos permitindo pedir mais peças.c)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "desinteressado (Não temos as peças que o parceiro quer.)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1552 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "sufocando (De momento não estamos permitindo que os parceiros peçam mais peças)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1607 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Detalhes no rastreador {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1624 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Info" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Adicionar um torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1677 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "URL fonte:" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "Digite a URL para download do arquivo torrent (só I2P), ou magnet link, maggo link, ou ainda o seu hash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1685 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Adicionar torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1688 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Também pode copiar arquivos torrentes a {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1690 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "A remoção de um arquivo .torrent fará com que ele pare." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Criar um torrente" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Dados para semear" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1720 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Arquivo ou pasta para semear (deve estar no caminho especificado)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Rastreadores" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Primário" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternativos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Criar torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1747 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "nenhum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2033 -msgid "Configuration" -msgstr "Preferências" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1784 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Pasta de dados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1788 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Ficheiro legível por todos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Se marcado, outros usuários poderão acessar os ficheiros descarregados" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1796 -msgid "Auto start" -msgstr "Iniciar automáticamente" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1800 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "se marcado, os torrentes adicionados se iniciarão automaticamente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1804 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Tema" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1817 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Tempo de actualização" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1830 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Nunca" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1836 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Demora do arranque" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minutos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Tamanho da página" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1844 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "torrents" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1868 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Limite global de subidores" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "parceiros" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1875 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Limite de largura de banda para a subida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Se recomenda a metade da largura de banda disponível." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "mostrar e mudar as preferências da largura de banda do roteador" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "usar também rastreadores abertos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1888 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Se marcado, anunciar os torrentes aos rastreadores abertos, assim como aos rastreadores listados no arquivo torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1892 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Habilitar DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1896 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Se marcado, usar DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1912 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Preferências de entrada" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1918 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Preferências de saida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1926 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "Anfitrião I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1931 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "Porto I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "Opções I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1951 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Guardar configuração" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Nome" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1973 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "URL do Website" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "abrir" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Privado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "URL para anúncio" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2009 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Adicionar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2049 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "URL magnet {0} não válida" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2057 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "1 salto" msgstr[1] "{0} saltos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2058 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "1 túnel" msgstr[1] "{0} túneles" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2265 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Arquivo torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Rastreador Primário" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Lista de Rastreadores" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2311 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Commentar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2320 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Criado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2330 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Criado por" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2340 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "URL magnet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2347 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Torrente privado" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2357 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2421 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2423 -msgid "Size" -msgstr "Tamanho" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2364 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Finalização" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Restantes" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2381 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Arquivos" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2386 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Peças" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2390 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Tamanho das peças" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2413 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2417 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Pasta" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Prioridade" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Subir uma herarquia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Não achei o arquivo torrente?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2480 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "Arquivo não achado no torrente?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "completo" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "restantes" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2543 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "alta" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "normal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Ignorar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2562 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Guardar prioridades" diff --git a/apps/i2psnark/locale/messages_pt_bR.po b/apps/i2psnark/locale/messages_pt_bR.po new file mode 100644 index 000000000..e0baae5de --- /dev/null +++ b/apps/i2psnark/locale/messages_pt_bR.po @@ -0,0 +1,1400 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the i2psnark package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# testsubject67 , 2014 +# blueboy, 2015 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" +"Last-Translator: kytv \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/otf/I2P/language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 +msgid "I2P tunnel closed." +msgstr "Túnel I2P fechado" + +#: ../java/src/org/klomp/snark/MagnetURI.java:42 +#: ../java/src/org/klomp/snark/MagnetURI.java:52 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 +msgid "Magnet" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:791 +#, java-format +msgid "Total uploaders limit changed to {0}" +msgstr "Limite de uploaders totais alterada para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:793 +#, java-format +msgid "Minimum total uploaders limit is {0}" +msgstr "Mínimo de uploaders totais alterada para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:805 +#, java-format +msgid "Up BW limit changed to {0}KBps" +msgstr "Limite de Up BW alterada para {0}KBps" + +#: ../java/src/org/klomp/snark/SnarkManager.java:807 +#, java-format +msgid "Minimum up bandwidth limit is {0}KBps" +msgstr "O limite de mínimo de banda larga é {0}KBps" + +#: ../java/src/org/klomp/snark/SnarkManager.java:819 +#, java-format +msgid "Startup delay changed to {0}" +msgstr "Atraso de inicialização alterada para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:830 +#, java-format +msgid "Refresh time changed to {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:832 +msgid "Refresh disabled" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:848 +#, java-format +msgid "Page size changed to {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 +msgid "Data directory must be an absolute path" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:859 +msgid "Data directory does not exist" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:861 +msgid "Not a directory" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:863 +msgid "Unreadable" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:868 +#, java-format +msgid "Data directory changed to {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:923 +msgid "I2CP and tunnel changes will take effect after stopping all torrents" +msgstr "Alterações em túneis e I2C entrarão em vigor depois de parar todos torrents" + +#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#, java-format +msgid "I2CP options changed to {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:933 +msgid "Disconnecting old I2CP destination" +msgstr "Desconectando destinação do velho I2CP" + +#: ../java/src/org/klomp/snark/SnarkManager.java:935 +#, java-format +msgid "I2CP settings changed to {0}" +msgstr "Configurações de I2CP alteradas para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:940 +msgid "" +"Unable to connect with the new settings, reverting to the old I2CP settings" +msgstr "Não é possível conectar com as novas configurações. Revertendo para as prévias configurações de I2CP" + +#: ../java/src/org/klomp/snark/SnarkManager.java:944 +msgid "Unable to reconnect with the old settings!" +msgstr "Não é possível conectar com as novas configurações!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:946 +msgid "Reconnected on the new I2CP destination" +msgstr "Reconectado à nova destinação de I2CP" + +#: ../java/src/org/klomp/snark/SnarkManager.java:953 +#, java-format +msgid "I2CP listener restarted for \"{0}\"" +msgstr "Auditor I2CP recomeçadas a \"{0}\"" + +#: ../java/src/org/klomp/snark/SnarkManager.java:967 +msgid "New files will be publicly readable" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:969 +msgid "New files will not be publicly readable" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:976 +msgid "Enabled autostart" +msgstr "Autocomeço permitido" + +#: ../java/src/org/klomp/snark/SnarkManager.java:978 +msgid "Disabled autostart" +msgstr "Autocomeço não permitido" + +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 +msgid "Enabled open trackers - torrent restart required to take effect." +msgstr "Trackers abertos permitidos - reinício de torrents é preciso para entrar em vigor" + +#: ../java/src/org/klomp/snark/SnarkManager.java:996 +msgid "Disabled open trackers - torrent restart required to take effect." +msgstr "Trackers abertos não permitidos - reinício de torrents é preciso para entrar em vigor" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 +msgid "Enabled DHT." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 +msgid "Disabled DHT." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 +msgid "DHT change requires tunnel shutdown and reopen" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 +#, java-format +msgid "{0} theme loaded, return to main i2psnark page to view." +msgstr "Tema {0} carregado, retornar para a página principal de i2psnark para visualizar." + +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 +msgid "Configuration unchanged." +msgstr "Configuração sem alteração" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 +msgid "Open Tracker list changed - torrent restart required to take effect." +msgstr "Lista de trackers abertos alterada - reinício de torrents é preciso para entrar em vigor" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 +msgid "Private tracker list changed - affects newly created torrents only." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 +#, java-format +msgid "Unable to save the config to {0}" +msgstr "Não é possivel salvar configurações para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 +msgid "Connecting to I2P" +msgstr "Conectando a I2P" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 +msgid "Error connecting to I2P - check your I2CP settings!" +msgstr "Erro ao conectar a I2P - verifique as configurações de I2CP!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 +#, java-format +msgid "Error: Could not add the torrent {0}" +msgstr "Erro: não é possível adicionar o torrent {0}" + +#. catch this here so we don't try do delete it below +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 +#, java-format +msgid "Cannot open \"{0}\"" +msgstr "Não é possível abrir \"{0}\"" + +#. TODO - if the existing one is a magnet, delete it and add the metainfo +#. instead? +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 +#, java-format +msgid "Torrent with this info hash is already running: {0}" +msgstr "O torrent com este info has já está sendo executado: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 +#, java-format +msgid "ERROR - No I2P trackers in private torrent \"{0}\"" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 +#, java-format +msgid "" +"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" +" DHT only." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 +#, java-format +msgid "" +"Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " +"announce to DHT only." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 +#, java-format +msgid "" +"Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " +"disabled, you should enable open trackers or DHT before starting the " +"torrent." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 +#, java-format +msgid "Torrent in \"{0}\" is invalid" +msgstr "O torrent em \"{0}\" é inválido" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Arquivo de torrent deletado: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 +#, java-format +msgid "ERROR - Out of memory, cannot create torrent from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 +#, java-format +msgid "Torrent added and started: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 +#, java-format +msgid "Torrent added: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 +#, java-format +msgid "Fetching {0}" +msgstr "Buscando {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 +#, java-format +msgid "" +"Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " +"succeed until you start another torrent, enable open trackers, or enable " +"DHT." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 +#, java-format +msgid "Adding {0}" +msgstr "Adicionando {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 +#, java-format +msgid "Download already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 +#, java-format +msgid "Failed to copy torrent file to {0}" +msgstr "Falha ao copiar arquivo de torrent de {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 +#, java-format +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 +#, java-format +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#, java-format +msgid "No pieces in \"{0}\"!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 +#, java-format +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 +#, java-format +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 +#, java-format +msgid "Limit is {0}B" +msgstr "O limite é {0}B" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 +#, java-format +msgid "Torrent \"{0}\" has no data!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 +#, java-format +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 +#, java-format +msgid "Error: Could not remove the torrent {0}" +msgstr "Erro: não foi possível remover o torrent {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 +#, java-format +msgid "Torrent stopped: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 +#, java-format +msgid "Torrent removed: \"{0}\"" +msgstr "Torrent removido: \"{0}\"" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 +#, java-format +msgid "Adding torrents in {0}" +msgstr "Adicionando torrents em {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 +#, java-format +msgid "Up bandwidth limit is {0} KBps" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 +#, java-format +msgid "Download finished: {0}" +msgstr "Download terminado: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 +#, java-format +msgid "Metainfo received for {0}" +msgstr "Metainfo recebido para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 +#, java-format +msgid "Starting up torrent {0}" +msgstr "Iniciando torrent {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 +#, java-format +msgid "Error on torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 +msgid "Unable to connect to I2P!" +msgstr "Incapaz de conectar ao I2P!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 +msgid "Opening the I2P tunnel" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 +msgid "Opening the I2P tunnel and starting all torrents." +msgstr "Abrindo o túnel I2P e começando todos os torrents." + +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 +msgid "Stopping all torrents and closing the I2P tunnel." +msgstr "Parando todos os torrents e fechando o túnel I2P" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 +msgid "Closing I2P tunnel after notifying trackers." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 +#, java-format +msgid "No valid trackers for {0} - enable opentrackers or DHT?" +msgstr "" + +#: ../java/src/org/klomp/snark/UpdateHandler.java:49 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 +msgid "Updating" +msgstr "" + +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 +#, java-format +msgid "Updating from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 +#, java-format +msgid "Download torrent file from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 +#, java-format +msgid "Torrent was not retrieved from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 +#, java-format +msgid "Torrent fetched from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 +#, java-format +msgid "Torrent already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 +#, java-format +msgid "Torrent already in the queue: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 +#, java-format +msgid "Torrent at {0} was not valid" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 +msgid "I2PSnark" +msgstr "I2PSnar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Configuração" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrents" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 +msgid "Refresh page" +msgstr "Recarregar página" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 +msgid "Forum" +msgstr "Fórum" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 +msgid "Click \"Add torrent\" button to fetch torrent" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 +msgid "clear messages" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 +msgid "Status" +msgstr "Status" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 +msgid "Hide Peers" +msgstr "Ocultar Pares" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 +msgid "Show Peers" +msgstr "Mostrar Pares" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 +msgid "Torrent" +msgstr "Torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "ETA" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 +msgid "Estimated time remaining" +msgstr "Tempo restante estimado" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 +msgid "RX" +msgstr "RX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Baixado" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "TX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 +msgid "Uploaded" +msgstr "Uploaded" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 +msgid "Down Rate" +msgstr "Taxa de down" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 +msgid "TX Rate" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Taxad de up" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 +msgid "Stop all torrents and the I2P tunnel" +msgstr "Parar todos os torrents e o túnel I2P" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 +msgid "Stop All" +msgstr "Parar todos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 +msgid "Start all stopped torrents" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 +msgid "Start All" +msgstr "Começar todos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 +msgid "Start all torrents and the I2P tunnel" +msgstr "Começar todos os torrents e o túnel I2P" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 +msgid "No torrents loaded." +msgstr "Nenhum torrent carregado." + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 +msgid "Totals" +msgstr "Totais" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 +#, java-format +msgid "1 torrent" +msgid_plural "{0} torrents" +msgstr[0] "1 torrent" +msgstr[1] "{0} torrents" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 +#, java-format +msgid "1 connected peer" +msgid_plural "{0} connected peers" +msgstr[0] "1 peer conectado" +msgstr[1] "{0} pares conectados" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 +#, java-format +msgid "1 DHT peer" +msgid_plural "{0} DHT peers" +msgstr[0] "" +msgstr[1] "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 +msgid "First" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 +msgid "First page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +msgid "Prev" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +msgid "Previous page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 +msgid "Next" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 +msgid "Next page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 +msgid "Last" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 +msgid "Last page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 +#, java-format +msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" +msgstr "URL inválido: deve começar com \"http://\", \"{0}\", ou \"{1}\"" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 +#, java-format +msgid "Magnet deleted: {0}" +msgstr "Magnet deletado: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 +#, java-format +msgid "Download deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 +#, java-format +msgid "Data file deleted: {0}" +msgstr "Arquivo de data deletado: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#, java-format +msgid "Data file could not be deleted: {0}" +msgstr "Não foi possível apagar o arquivo de data: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 +#, java-format +msgid "Directory could not be deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 +#, java-format +msgid "Directory deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +msgid "Error - Cannot include alternate trackers without a primary tracker" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 +msgid "Error - Cannot mix private and public trackers in a torrent" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 +#, java-format +msgid "Torrent created for \"{0}\"" +msgstr "Torrent criado para \"{0}\"" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 +#, java-format +msgid "" +"Many I2P trackers require you to register new torrents before seeding - " +"please do so before starting \"{0}\"" +msgstr "Muitos I2P trackers requerem o registro de torrents antes de seeding - por favor, faça isso antes de começar \"{0}\"" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 +#, java-format +msgid "Error creating a torrent for \"{0}\"" +msgstr "Erro ao criar torrent para \"{0}\"" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 +#, java-format +msgid "Cannot create a torrent for the nonexistent data: {0}" +msgstr "Não foi possível criar um torrent para a informação inexistente: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 +msgid "Error creating torrent - you must enter a file or directory" +msgstr "Erro ao criar torrent - é preciso um arquiso ou diretório" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +msgid "Delete selected" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 +msgid "Save tracker configuration" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 +msgid "Removed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 +msgid "Add tracker" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 +msgid "Enter valid tracker name and URLs" +msgstr "" + +#. "\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 +msgid "Restore defaults" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 +msgid "Restored default trackers" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 +msgid "Checking" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 +msgid "Allocating" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +msgid "Tracker Error" +msgstr "Erro de tracker" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 +#, java-format +msgid "1 peer" +msgid_plural "{0} peers" +msgstr[0] "1 peer" +msgstr[1] "{0} pares" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 +msgid "Starting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 +msgid "Seeding" +msgstr "Seeding" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 +msgid "Complete" +msgstr "Completo" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 +msgid "OK" +msgstr "OK" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 +msgid "Stalled" +msgstr "Estagnado" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 +msgid "No Peers" +msgstr "Sem pares" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 +msgid "Stopped" +msgstr "Parad" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 +msgid "Torrent details" +msgstr "Detalhes do torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 +msgid "View files" +msgstr "Ver arquivos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 +msgid "Open file" +msgstr "Abrir arquivos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +msgid "Stop the torrent" +msgstr "Parar o torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 +msgid "Stop" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 +msgid "Start the torrent" +msgstr "Começar o torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 +msgid "Start" +msgstr "Começar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 +msgid "Remove the torrent from the active list, deleting the .torrent file" +msgstr "Remover o torrent da lista de ativos, deletando o arquivo .torrent" + +#. Can't figure out how to escape double quotes inside the onclick string. +#. Single quotes in translate strings with parameters must be doubled. +#. Then the remaining single quote must be escaped +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 +#, java-format +msgid "" +"Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " +"not be deleted) ?" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 +msgid "Remove" +msgstr "Remover" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 +msgid "Delete the .torrent file and the associated data file(s)" +msgstr "Deletar o arquivo ;torrent e associar data file(s)" + +#. Can't figure out how to escape double quotes inside the onclick string. +#. Single quotes in translate strings with parameters must be doubled. +#. Then the remaining single quote must be escaped +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 +#, java-format +msgid "" +"Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " +"data?" +msgstr "Tem certeza que quer remover o torrent \\''{0}\\'' e todas as informaçoes baixadas?" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 +msgid "Delete" +msgstr "Deletar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 +msgid "Unknown" +msgstr "desconhecido" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 +msgid "Seed" +msgstr "Seed" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 +msgid "Uninteresting (The peer has no pieces we need)" +msgstr "Desinteressante (O par não tem partes que precisemos)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 +msgid "Choked (The peer is not allowing us to request pieces)" +msgstr "Engasgado (O par não está nos permitindo solicitar partes)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +msgid "Uninterested (We have no pieces the peer needs)" +msgstr "Desinteressado (Não temos quaisquer partes que o par precise)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +msgid "Choking (We are not allowing the peer to request pieces)" +msgstr "Engasgando (O par está impossibilitado de solicitar partes)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 +#, java-format +msgid "Details at {0} tracker" +msgstr "Detalhes em tracker {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +msgid "Info" +msgstr "Info" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 +msgid "Add Torrent" +msgstr "Adicionar Torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +msgid "From URL" +msgstr "Do URL" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 +msgid "" +"Enter the torrent file download URL (I2P only), magnet link, maggot link, or" +" info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +msgid "Add torrent" +msgstr "Acidionar torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 +#, java-format +msgid "You can also copy .torrent files to: {0}." +msgstr "Pode também copiar arquivos .torrents de: {0}." + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 +msgid "Removing a .torrent will cause it to stop." +msgstr "A remoção de um .torrent parará a mesma" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 +msgid "Create Torrent" +msgstr "Criar Torrent" + +#. out.write("From file:
\n"); +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 +msgid "Data to seed" +msgstr "Arquivo para seed" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 +msgid "Trackers" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 +msgid "Primary" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 +msgid "Alternates" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 +msgid "Create torrent" +msgstr "Criar torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 +msgid "none" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 +msgid "Data directory" +msgstr "Diretório de arquivo" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 +msgid "Files readable by all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 +msgid "If checked, other users may access the downloaded files" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 +msgid "If checked, automatically start torrents that are added" +msgstr "Automaticamente começar torrents adicionados se verificado" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 +msgid "Theme" +msgstr "Tema" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 +msgid "Refresh time" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 +msgid "Never" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 +msgid "Startup delay" +msgstr "Atraso de inicialização" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 +msgid "minutes" +msgstr "minutos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 +msgid "Page size" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 +msgid "torrents" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 +msgid "Total uploader limit" +msgstr "Limite total do uploader" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 +msgid "peers" +msgstr "pares" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 +msgid "Up bandwidth limit" +msgstr "Up limite de banda larga" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 +msgid "Half available bandwidth recommended." +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 +msgid "View or change router bandwidth" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 +msgid "Use open trackers also" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 +msgid "" +"If checked, announce torrents to open trackers as well as the tracker listed" +" in the torrent file" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +msgid "Enable DHT" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +msgid "If checked, use DHT" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 +msgid "Inbound Settings" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 +msgid "Outbound Settings" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 +msgid "I2CP host" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 +msgid "I2CP port" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 +msgid "I2CP options" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 +msgid "Save configuration" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "Name" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 +msgid "Website URL" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 +msgid "Open" +msgstr "Abrir" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +msgid "Private" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 +msgid "Announce URL" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 +msgid "Add" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 +#, java-format +msgid "Invalid magnet URL {0}" +msgstr "" + +#. * dummies for translation +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 +#, java-format +msgid "1 hop" +msgid_plural "{0} hops" +msgstr[0] "" +msgstr[1] "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +#, java-format +msgid "1 tunnel" +msgid_plural "{0} tunnels" +msgstr[0] "" +msgstr[1] "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 +msgid "Torrent file" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 +msgid "Primary Tracker" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 +msgid "Tracker List" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 +msgid "Comment" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 +msgid "Created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 +msgid "Created By" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 +msgid "Magnet link" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 +msgid "Private torrent" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 +msgid "Completion" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +msgid "Remaining" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 +msgid "Files" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 +msgid "Pieces" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 +msgid "Piece size" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 +msgid "Directory" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 +msgid "Priority" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 +msgid "Up to higher level directory" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 +msgid "Torrent not found?" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 +msgid "File not found in torrent?" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 +msgid "complete" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 +msgid "remaining" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 +msgid "High" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 +msgid "Normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 +msgid "Skip" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 +msgid "Save priorities" +msgstr "" diff --git a/apps/i2psnark/locale/messages_ro.po b/apps/i2psnark/locale/messages_ro.po index 5259dc9c8..c95d1fa06 100644 --- a/apps/i2psnark/locale/messages_ro.po +++ b/apps/i2psnark/locale/messages_ro.po @@ -4,236 +4,253 @@ # To contribute translations, see http://www.i2p2.de/newdevelopers # # Translators: +# Di N., 2015 +# Di N., 2015 +# titus , 2015 +# titus , 2015 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:06+0000\n" -"PO-Revision-Date: 2013-12-05 15:04+0000\n" -"Last-Translator: polearnik \n" -"Language-Team: Romanian (http://www.transifex.com/projects/p/I2P/language/ro/)\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" +"Last-Translator: kytv \n" +"Language-Team: Romanian (http://www.transifex.com/otf/I2P/language/ro/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ro\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Nu sunt torrente care rulează" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "Tunel I2P închis." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Limita totala de incarcare schimbat la {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Limita totala minimă de incarcare este {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Limita de incarcare BW schimbat la {0} Kbps" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Limita de lățime de bandă minima la incarcarea este {0} Kbps" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Întârziere de pornire schimbat la {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Actualizarea timpului schimbat la {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Refresh dezactivat" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Schimbat dimensiunea paginii la {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "Dosarul de data de lucru trebuie să fie o cale absolută" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "Dosarul de date nu există" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "Nu e un dosar" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "necitibil" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Dosarul de date s-a schimbat la {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "I2CP și tunel modificările vor intra în vigoare după oprirea tuturor torrentele" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "Opțiuni I2CP schimbat la {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Deconectarea destinației vechi I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Opțiuni I2CP schimbat la {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Imposibil de a se conecta cu noile setări, revenirea la vechile setări I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Nu pot să se reconectez cu setările vechi!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Reconectat la destinație noua I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "I2CP ascultător repornit pentru \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Fișiere noi vor putea fi citite public" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Fișiere noi nu vor putea fi citite public" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Activeaza autopornirea" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Dezactivează autopornirea" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Trackere deschise activat - repornirea torrentui este necesara să aibă efect." -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Trackere deschise dezactivat - repornirea torrentui este necesara să aibă efect." -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "DHT activat." -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "DHT dezactivat." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "Schimbare DHT necesită oprirea tunel și redeschiderea lui" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} temă încărcata, a reveni la pagina principală i2psnark pentru a vizualiza." -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Configuraţia neschimbată" -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Trackere deschise schimbat - repornirea torrentui este necesara să aibă efect." -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Lista trackerilor private schimbat - afectează doar nou-create torrente." -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Imposibil de a salva configurarea {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Conectarea la I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Eroare la conectarea la I2P - verificați setările I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Eroare: Nu sa putut adăuga torentul {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Nu se poate deschide \"{0}\"." #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Torrent cu aceste informații hash este deja pornit: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "EROARE - Nu sunt trackere I2P in torrent privat \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "Avertisment - Nu sunt trackere I2P în \"{0}\", va anunța numai la I2P trackers deschise și DHT ." -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "Avertisment - Nu sunt trackere I2P în \"{0}\", și trackere deschise sunt dezactivate, se va anunța numai prin DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -241,34 +258,46 @@ msgid "" "torrent." msgstr "Avertisment - Nu sunt trackere I2P în \"{0}\", și DHT și trackere deschise sunt dezactivate, ar trebui să permiteti trackere deschise sau DHT înainte de a începe torrent." -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Torrent în \"{0}\" este incorect" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Fișier torrent șters: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "EROARE - Out de memorie, nu se pot crea torrent din {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent adăugat și pornit: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent adăugat: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Preluarea {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -276,311 +305,363 @@ msgid "" "DHT." msgstr "Trackere deschise sunt dezactivate și nu avem colegii DHT. Descarcarea din{0} nu poate reuși până când veți începe un alt torrent, permite trackere deschise, sau permite DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Adăugarea {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Descarcarea deja rulează: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr " Copierea fisieurului torent in {0} a esuat" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Prea multe fișiere în \"{0}\" ({1}), ștergeti-le!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Torrent \"{0}\" nu se poate termina cu \". Torrent\", ștergeti!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Nu sunt piese din \"{0}\", ștergeti!" +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Prea multe piese în \"{0}\", limita este de {1}, ștergeti!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Piese sunt prea mari în \"{0}\" ({1} B), ștergeti." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "Limita este de {0} B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "Torrent \"{0}\" nu dispune de date, șterge-o!" +msgid "Torrent \"{0}\" has no data!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Torrents mai mari de {0} B nu sunt acceptate încă, ștergerea \"{1}\"Torrents mai mari de {0} B nu sunt acceptate încă, ștergerea \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Eroare: Nu am putut șterge torentul {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent oprit: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent sters: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Adăugarea torrente în {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "Limita de lățime de bandă la incarcarea este {0} Kbps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Descarcare finisata: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo primit pentru {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Pornirea torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Eroare pe torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Nu se poate stabili o conexiune la I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Deschiderea tunelului I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Deschiderea tunelului I2P și pornirea tuturor torrentelor." -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Oprirea tuturor torrentelor și inchiderea tunelului I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Închiderea tunelului I2P după notificarea trackere." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Nu sunt trackere valabile pentru {0} - permite opentrackers sau DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Actualizare" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Actualizarea din {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Descărca fișierul torrent de la {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Torrent nu a fost preluat de la {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent preluat de la {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent deja rulează: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent deja în coada de așteptare: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Torrent la {0} nu a fost valid" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - BitTorrent Client Anonim" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "Router-ul este deactivat" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "Torente" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Configurație" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "Client Bittorrent anonim" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Router-ul este deactivat" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torente" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "refresh pagina" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Forum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Faceți clic pe \"Adauga torrent\" pentru a aduce torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "stergerea mesajelor" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Stare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "Sortează după {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Ascunde utilizatori" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Arată utilizatori" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "Tip fișier" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "eta" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Estimare timp rămas" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "eta" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "Descărcat" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "RX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Descărcat" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Dimensiune" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "TX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "Rată de încărcare" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Încărcat" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" -msgstr "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "RX Rate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Rata de descarcare " #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "RX Rate" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "Rata de incarcare " - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "TX Rate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Rata de incarcare " + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Opreste toate torrentele și tunelul I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Oprește toate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Începeți toate torrentele oprite" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Pornește toate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Porneste toate torrentele și tunelul I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Niciun torent încărcat." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Totaluri" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" @@ -588,7 +669,7 @@ msgstr[0] "1 torrent" msgstr[1] "{0} torrente" msgstr[2] "{0} torrentу" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" @@ -596,7 +677,7 @@ msgstr[0] "{0} utilizator conectat " msgstr[1] "{0} utilizatori conectati" msgstr[2] "{0} utilizatori conectati" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" @@ -604,174 +685,202 @@ msgstr[0] "1 partener DHT" msgstr[1] "{0} parteneri DHT" msgstr[2] "{0} parteneri DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "Dest" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "Primul" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "P&rima pagină" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "Prev" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Pagina anterioară" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "Următorul" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Pagina următoare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Ultimul" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Ultima pagină" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "Directorul de date nu poate fi creat" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "Nu se poate adăuga torrentul {0} în interiorul altui torrent: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "URL incorect: trebuie să înceapă cu \"http://\", \"{0}\", sau \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet sters: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Fișier torrent șters: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Descarcă șterse: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Fișier data șters: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Fișier de date nu a putut fi șters: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Dosarul nu a putut fi sters {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Directorii șterse: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "Nu se poate adăuga un torrent terminat în \".torrent\": {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "Torrentul cu acest nume deja rulează: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "Nu se poate adăuga un torent ce include un director I2P: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "Nu se poate adăuga torrent {0} ce include un alt torrent: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "Eroare - Nu pot conține trackere alternative fără un tracker primar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "Eroare - Nu se poate amesteca trackere publice și private într-un torent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent creat pentru \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "Multe trackere I2P cer să vă înregistrați torrentele noi înainte de seedat - vă rugăm să faceți acest lucru înainte de a începe \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Eroare la crearea unui torrent pentru \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Nu se poate crea un torrent pentru datele inexistente: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Eroare la crearea torrent - trebuie să introduceți un fișier sau director" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Șterge pe cel ales" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Salvați configurația tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Șters" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Adaugă tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Introduceți numele tracker valid și URL-uri" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Restabileşte implicitele" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Trackers implicite restaurate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Se verifică" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Alocare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Eroare tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" @@ -779,356 +888,377 @@ msgstr[0] "1 partener" msgstr[1] "{0} parteneri" msgstr[2] "{0} parteneri" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Începere" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Încărcare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Complet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Întrerupt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Nu sunt utilizatori" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Oprit" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Detalii torent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Vizualizare fișierilor" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Deschide fișier" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Oprește torentul" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Stop" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Pornește torentul" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Start" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Scoateți torrent din lista torentelor activi, ștergem fișierul torrent." #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "Sigur doriți să ștergeți dosarul \\'' {0} \\'' (datele descărcate nu vor fi șterse)?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Șterge" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Ștergeți fișierul torrent. Și fișier(e) de date asociat(e)" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Sigur doriți să ștergeți torrent \\'' {0} \\'' și toate datele descărcate?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Șterge" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Necunoscut" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Seed" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Neinteresante (partener nu are piese de care avem nevoie)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Înecat (partener nu ne permite să solicitam bucăți)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Neinteresat (Nu avem piese de care are nevoie partener)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "partenerSufocare (Noi nu permitem partenerului solicitarea bucăților)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Detalii la tracker {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Info" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Adaugă torent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Din URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "Introduceți URL-ul de descarcare fișierilor torrent (I2P numai), link-ul magnet, maggot-link, sau info hash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Adaugă torent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "Dir date" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "Introdu directorul în care să se salveze datele (default {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "De asemenea, puteți copia fișiere torrent la: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Stergerea .torrent va face ca acesta să se oprească." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Creează un torent" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Date pentru seedare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Fișier sau director de seedare (trebuie să fie în calea specificată)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "Fișier sau director de seedare (calea completă sau în director {0} )" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Trackere" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Primar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternativă" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Creează un torent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "nici unul" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "Configurație" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Dosar cu date" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Fișiere lizibile de către toți" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Dacă este bifată, utilizatorii pot accesa fișierele descărcate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "Start automat" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "Pornește automat torrente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Dacă este bifată, începe automat torrentele care sunt adăugate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Teme" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Timp de reîmprospătare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Niciodată" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "întârziere de pornire" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minute" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Mărimea paginii" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "Torente" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Limită totală de încărcare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "Parteneri" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "limita de incarcare de lățime de bandă" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Jumătate lățime de bandă disponibilă este recomandat." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Vizualizeaza sau modifica lățime de bandă router" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Utilizați trackere deschise, de asemenea," -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Dacă este bifată, anunta torrente pentru a urmări trackere deschise , precum și trackere listate în fișierul torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Activează DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Dacă este bifată, utilizați DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Setări de intrare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Setări de ieșire" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "Portul I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "Portul I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "Opțiuni I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Salvare configurări" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Nume" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "URL website" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "Standard" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Deschis" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Privat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "URL de anuntare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Adaugă" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "URL-ul magnet invalid {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" @@ -1136,7 +1266,7 @@ msgstr[0] "1 hop" msgstr[1] "{0} hop-uri" msgstr[2] "{0} hop-uri" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" @@ -1144,106 +1274,135 @@ msgstr[0] "1 tunel" msgstr[1] "{0} tunele" msgstr[2] "{0} tunele" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Fișier torent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "Locaţie date" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "Informație index" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Tracker primar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Lista Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Comentariu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Creat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Creat de" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Legătură Magnet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Torrent privat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "Dimensiune" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Completare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Rămas" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Fișiere" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Piese:" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Dimensiune piesei" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Dosar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Prioritate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Spre dosarul de nivel superior" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent nu a fost găsit?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "Fișierul nu a fost găsit în torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "încheiat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "Rămas" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Ridicat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Omitere" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "Configurează toate ca înalte" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "Configurează toate ca normal" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "Omite tot" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Salvați priorități" diff --git a/apps/i2psnark/locale/messages_ru.po b/apps/i2psnark/locale/messages_ru.po index 40c42d73c..cafbe3c72 100644 --- a/apps/i2psnark/locale/messages_ru.po +++ b/apps/i2psnark/locale/messages_ru.po @@ -4,245 +4,261 @@ # To contribute translations, see http://www.i2p2.de/newdevelopers # # Translators: -# IOException , 2013 +# Aleksey Orekhov , 2013 # mama__1 , 2013 +# Dmitriy Mamonov , 2014 # ducki2p , 2011 -# varnav, 2013 +# Eugene, 2013 # foo , 2009 # mama__1 , 2013 -# Роман Азаренко , 2013 +# Foster Snowhill, 2013 # sr4d , 2014 -# Роман Азаренко , 2013 +# vertnis , 2015 +# Foster Snowhill, 2013 +# yume, 2014-2015 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-09 19:27+0000\n" -"PO-Revision-Date: 2014-01-11 08:49+0000\n" -"Last-Translator: sr4d \n" -"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/I2P/language/ru_RU/)\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-14 16:31+0000\n" +"Last-Translator: vertnis \n" +"Language-Team: Russian (Russia) (http://www.transifex.com/otf/I2P/language/ru_RU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru_RU\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 -#: ../java/src/org/klomp/snark/SnarkManager.java:1960 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Нет запущенных торрентов." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "Соединение с I2P закрыто." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1655 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:515 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Новое значение лимита количества слотов отдачи: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:517 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Минимально допустимое значение для количества слотов: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:529 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Новое значение лимита скорости отдачи: {0} КБ/с" -#: ../java/src/org/klomp/snark/SnarkManager.java:531 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Минимально допустимое значение для лимита скорости отдачи: {0} КБ/с" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Задержка запуска изменена на {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:554 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Время обновления изменено на {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:556 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Обновление отключено" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Размер страницы изменён на {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "Директория данных должна быть абсолютным путём" -#: ../java/src/org/klomp/snark/SnarkManager.java:583 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "Директория данных не существует" -#: ../java/src/org/klomp/snark/SnarkManager.java:585 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "Не директория" -#: ../java/src/org/klomp/snark/SnarkManager.java:587 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "Нечитаемо" -#: ../java/src/org/klomp/snark/SnarkManager.java:592 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Директория данных изменена на {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:647 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "Изменения настроек I2CP и туннелей вступят в силу после остановки всех торрентов." -#: ../java/src/org/klomp/snark/SnarkManager.java:651 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "Параметры I2CP изменены на {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Разрываем старое I2CP соединение" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Новые параметры I2CP: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:664 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Не удалось соединиться с использованием новых настроек I2CP, возвращаемся к старым настройкам" -#: ../java/src/org/klomp/snark/SnarkManager.java:668 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Не удалось пересоединиться с использованием старых настроек I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:670 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Пересоединились по новому адресу I2CP" -#: ../java/src/org/klomp/snark/SnarkManager.java:677 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "I2CP-приёмник перезапущен для \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Новые файлы будут доступны на чтение публично" -#: ../java/src/org/klomp/snark/SnarkManager.java:693 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Новые файлы не будут доступны на чтение публично" -#: ../java/src/org/klomp/snark/SnarkManager.java:700 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Автостарт включен" -#: ../java/src/org/klomp/snark/SnarkManager.java:702 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Автостарт выключен" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "Включена \"умная\" сортировка" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "Отключена \"умная\" сортировка" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Включено использование открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Отключено использование открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу." -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "DHT включено." -#: ../java/src/org/klomp/snark/SnarkManager.java:719 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "DHT выключено." -#: ../java/src/org/klomp/snark/SnarkManager.java:721 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "Изменение DHT требует повторного открытия туннеля" -#: ../java/src/org/klomp/snark/SnarkManager.java:728 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} тема загружена, вернитесь на основную страницу i2psnark для просмотра." -#: ../java/src/org/klomp/snark/SnarkManager.java:738 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Настройки не изменились." -#: ../java/src/org/klomp/snark/SnarkManager.java:770 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Изменен список открытых трекеров. Требуется перезапуск торрента, чтобы изменения вступили в силу." -#: ../java/src/org/klomp/snark/SnarkManager.java:780 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Список частных трекеров изменился - влияет только на заново созданные торренты." -#: ../java/src/org/klomp/snark/SnarkManager.java:826 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Не удалось сохранить настройки в {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:904 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Устанавливается соединение с I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:907 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Ошибка соединения с I2P, проверьте настройки I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:916 -#: ../java/src/org/klomp/snark/SnarkManager.java:1692 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Ошибка: Не удалось добавить торрент {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:938 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Не удалось открыть \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:957 -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/SnarkManager.java:1140 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:162 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Торрент с таким info hash уже запущен: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:963 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "ОШИБКА - нет I2P-трекеров в частном торренте \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:965 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "Предупреждение - Нет I2P трекеров в \"{0}\", анонсирование будет выполняться только на открытых трекерах и в DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:968 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "Предупреждение - Нет I2P трекеров в \"{0}\" и использование открытых трекеров запрещено, анонсирование будет выполняться только в DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:970 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -250,34 +266,46 @@ msgid "" "torrent." msgstr "Предупреждение - Нет I2P трекеров в \"{0}\" и использование открытых трекеров и DHT запрещено. Следует разрешить их использование перед запуском торрента." -#: ../java/src/org/klomp/snark/SnarkManager.java:992 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Торрент в \"{0}\" некорректен" -#: ../java/src/org/klomp/snark/SnarkManager.java:999 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:186 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Удален торрент: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "Торрент файл перемещен из {0} в {1}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "ОШИБКА - нехватка памяти, невозможно создать торрент из {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1011 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Торрент добавлен и запущен: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "Торрент добавлен и запущен: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1013 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Торрент добавлен: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "Добавлен торрент: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1069 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:89 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Получение торрента: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1075 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -285,974 +313,1110 @@ msgid "" "DHT." msgstr "Использование открытых трекеров запрещено и нет DHT-пиров. Передача {0} не может быть завершена. Запустите другой торрент или разрешите использование открытых трекеров и/или DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:1079 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Добавление {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1111 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Закачка уже запущена: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1150 -#: ../java/src/org/klomp/snark/SnarkManager.java:1173 -#: ../java/src/org/klomp/snark/SnarkManager.java:1611 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Не удалось скопировать торрент в: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Слишком много файлов в торренте \"{0}\" ({1}), удаляем его!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "Слишком много файлов в \"{0}\" ({1})!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1402 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Торрент \"{0}\" содержит единственный файл заканчивающийся на \".torrent\", удаляем его!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "Торрент файл \"{0}\" не может оканчиваться на \".torrent\"!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1404 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "В торренте \"{0}\" не оказалось ни одной части, удаляем его!" +msgid "No pieces in \"{0}\"!" +msgstr "Нет частей в \"{0}\"!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1406 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "Слишком много частей в \"{0}\" (предел — {1}), удаляем торрент!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "Слишком много частей в \"{0}\", предел {1}!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Слишком крупные части в \"{0}\" ({1}Б), удаляем торрент." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "Слишком большой размер части в \"{0}\" ({1}B)!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1409 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "Наш предел {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1411 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "Торрент \"{0}\" не содержит данных, удаляем его!" +msgid "Torrent \"{0}\" has no data!" +msgstr "Торрент \"{0}\" не содержит данных!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1419 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Торренты крупнее чем {0}Б пока не поддерживается, удаляем \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "Торренты больше, чем {0} В не поддерживаются \"{1}\"!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1435 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Ошибка: Невозможно удалить торрент {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1456 -#: ../java/src/org/klomp/snark/SnarkManager.java:1474 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Торрент остановлен: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "Торрент остановлен {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1495 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Торрент удален: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1503 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Добавление торрентов через {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1534 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "Ограничение отдачи {0} КБ/с" -#: ../java/src/org/klomp/snark/SnarkManager.java:1556 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Закачка завершена: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1607 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Метаданные получены для {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1608 -#: ../java/src/org/klomp/snark/SnarkManager.java:1837 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Запускаем торрент: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1623 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Ошибка в торренте {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1686 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Не удалось установить соединение с I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1836 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:126 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Открытие I2P туннеля" -#: ../java/src/org/klomp/snark/SnarkManager.java:1860 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Соединяемся с I2P и запускаем все торренты." -#: ../java/src/org/klomp/snark/SnarkManager.java:1923 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Останавливаем все торренты и закрываем соединение с I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1942 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Закрытие туннеля I2P после уведомления трекеров" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "Закончена перепроверка торрента {0}, теперь {1} завершен" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "Закончена перепроверка торрента {0}, без изменений" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "Ошибка проверки торрента {0}" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Нет трекеров для {0} — включены ли открытые трекеры или DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Обновление" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Обновлено из {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:77 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Загрузка торрент файла из: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:99 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Не удалось получить торрент из: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:153 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Получен торрент из: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:174 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Торрент уже запущен: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:176 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Торрент уже в очереди: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:184 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Торрент полученный из {0} некорректен" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:247 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark — анонимный BitTorrent клиент" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260 -msgid "Router is down" -msgstr "Маршрутизатор выключен" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 -msgid "Torrents" -msgstr "Торренты" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1477 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2242 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Настройки" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "Анонимный BitTorrent клиент" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Маршрутизатор выключен" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Торренты" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Обновить страницу" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Форум" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Нажмите \"Добавить торрент\", чтобы получить торрент" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:345 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "очистить сообщения" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2427 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Статус" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "Сортировать по {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "скрыть список пиров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:423 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "показать список пиров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2236 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2256 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Торрент" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "Тип файла" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "Осталось" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Примерное оставшееся время" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:445 -msgid "ETA" -msgstr "Осталось" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:450 -msgid "Downloaded" -msgstr "Получено" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "Принято" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Получено" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Размер" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "Отдано" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "Коэффициент отдачи" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Отдано" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:461 -msgid "TX" -msgstr "Отдано" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "Скорость получения" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:467 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Скорость загрузки" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 -msgid "RX Rate" -msgstr "Скорость получения" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:476 -msgid "Up Rate" -msgstr "Скорость отдачи" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:479 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "Скорость отдачи" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Скорость отдачи" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Остановить все торренты и закрыть соединение с I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Остановить все" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Запустить все остановленные торренты" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:510 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Запустить все" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Запустить все торренты и открыть соединение с I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Нет загруженных торрентов." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Всего" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "{0} торрент" msgstr[1] "{0} торрента" msgstr[2] "{0} торрентов" +msgstr[3] "{0} торрентов" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "{0} подсоединенный пир" msgstr[1] "{0} подсоединенных пиров" msgstr[2] "{0} подсоединенных пиров" +msgstr[3] "{0} подсоединенных пиров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "{0} DHT пир" msgstr[1] "{0} DHT пира" msgstr[2] "{0} DHT пиров" +msgstr[3] "{0} DHT пиров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "Адрес назначения" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "Первый" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Первая страница" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "Предыдущее" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Предыдущая страница" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "Следующее" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Следующая страница" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Последний" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Последняя страница" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "Не удалось создать директорию для файлов" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "Не могу добавить торрент {0} в состав другого торрента: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "Некорректный URL: должен начинаться с \"http://\", \"{0}\", или \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet удален: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Удален торрент: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Закачка удалена: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Файл удален: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Не удалось удалить файл: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Каталог не может быть удалён: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Каталог удалён: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "Не могу добавить окончание торрента в файл \".torrent\": {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "Торрент с таким именем уже запущен: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "Не могу добавить торрент с I2P директорией: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "Не могу добавить торрент {0}, включающий в себя другой торрент: {1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "Ошибка - нельза добавить альтернативные трекеры без основного" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "Ошибка - невозможно объединить приватный и публичные трекеры в торренте" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Создан торрент для \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:968 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "Многие I2P трекеры требуют зарегистрировать на них торрент перед началом раздачи — пожалуйста проверьте требуется ли это перед запуском \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Ошибка при создании торрента для: \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Невозможно создать торрент для несуществующего файла или директории: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Торрент не создан — вы должны указать файл или директорию" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2018 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Удалить выбранное" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2019 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Сохранить настройки трекеров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1025 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Удален" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Добавить трекер" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Введите действительное название и URL трекера" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2021 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Восстановить значения по-умолчанию" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1085 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Восстановить трекеры по-умолчанию" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1207 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Проверка" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1209 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Выделение места" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Ошибка Трекера" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1254 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "{0} пир" msgstr[1] "{0} пира" msgstr[2] "{0} пиров" +msgstr[3] "{0} пиров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1234 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Запускается" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Раздается" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2369 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Завершен" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1266 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1272 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "Загружается" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Простаивает" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" -msgstr "Нет Пиров" +msgstr "Нет пиров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1296 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Остановлен" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Подробная информация" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Открыть директорию" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Открыть файл" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Остановить торрент" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1404 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Остановить" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Запустить торрент" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1418 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Запустить" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Удалить торрент из списка и с диска" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1435 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "Вы уверены, что хотите удалить файл \\''{0}\\'' (скачанные данные не будут удалены) ?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1438 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Удалить" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Удалить торрент и стереть загруженные файлы" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Вы действительно хотите удалить торрент \\''{0}\\'' и все загруженные файлы?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1458 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Стереть" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Неизвестный" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Сид" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1528 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Uninteresting (У пира нет нужных нам частей торрента)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Choked (Этот пир не позволяет нам запрашивать части торрента)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Uninterested (У нас нужных этому пиру частей торрента)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1552 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Choking (Мы не позволяем этому пиру запрашивать у нас части торрента)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1607 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Детали на трекере {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1624 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Информация" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Добавить Торрент" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1677 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Из URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "Введите URL для скачивания torrent-файла (только I2P), magnet-/maggot-ссылку или хэш" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1685 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Добавить торрент" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1688 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "Директория для файлов" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "Путь для сохранения файлов (по умолчанию {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Либо вы можете просто скопировать .torrent-файлы в директорию {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1690 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Удаление .torrent-файла приведёт к остановке торрента." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Создать Торрент" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Файлы для раздачи" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1720 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Файл или директория для раздачи (вводите только название файла или директории, указание абсолютных путей не поддерживается)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "Файл или директория для раздачи (полный путь или относительно директории {0} )" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Трекеры" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Основной" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Альтернативный" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Создать торрент" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1747 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "нет" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2033 -msgid "Configuration" -msgstr "Настройки" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1784 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Директория для файлов" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1788 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Файлы доступны для чтения всеми" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Если отмечено, другие пользователи могут иметь доступ к скачанным файлам" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1796 -msgid "Auto start" -msgstr "Автозапуск" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "Автоматически стартовать торренты" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1800 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Автоматически запускать торренты после добавления" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1804 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "\"Умная\" сортировка торрентов" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "Если отмечено, игнорировать такие слова, как 'the' при сортировке" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Тема" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1817 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Время обновления интерфейса" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1830 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Никогда" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1836 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Задержка запуска" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "минут" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Размер страницы" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1844 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "торренты" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1868 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Ограничение количества слотов отдачи" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "пиров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1875 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Ограничение скорости отдачи" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Рекомендуется использовать половину от доступной пропускной способности." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Посмотреть/настроить ограничения скорости в маршрутизаторе I2P" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Дополнительно использовать открытые трекеры" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1888 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Анонсировать торренты на открытых трекерах, дополнительно к тем, что указаны внутри торрента" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1892 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Включить DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1896 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Если выбрано, используется DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1912 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Входящие туннели" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1918 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Исходящие туннели" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1926 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "Адрес I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1931 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "Порт I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "Параметры I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1951 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Сохранить настройки" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Имя" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1973 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "URL сайта" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "Стандартный" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Открыть" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Частный" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "URL анонсирования" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2009 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Добавить" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2049 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "Неправильный magnet URL {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2057 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "{0} хоп" msgstr[1] "{0} хопа" msgstr[2] "{0} хопов" +msgstr[3] "{0} хопов" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2058 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "{0} туннель" msgstr[1] "{0} туннеля" msgstr[2] "{0} туннелей" +msgstr[3] "{0} туннелей" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2265 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Торрент-файл" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "Расположение данных" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "Инфо хэш" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Первичный трекер" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Список трекеров" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2311 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Комментарий" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2320 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Создан" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2330 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Создан кем" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2340 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "Добавлено" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "Завершено" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Magnet-ссылка" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2347 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Частный Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2357 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2421 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2423 -msgid "Size" -msgstr "Размер" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2364 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Загружено" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Осталось" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2381 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Файлов" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2386 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Части" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2390 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Размер части" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2413 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2417 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "Обновите страницу для получения результатов" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "Быстрая повторная проверка" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Директория" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Приоритет" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Перейти в директорию уровнем выше" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent not found?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2480 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "File not found in torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "скачано" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "осталось" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2543 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Высокий" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Нормальный" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Пропустить" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2562 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "Всем высокий приоритет" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "Всем нормальный приоритет" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "Пропустить все" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Сохранить приоритеты" diff --git a/apps/i2psnark/locale/messages_sk.po b/apps/i2psnark/locale/messages_sk.po index f36a36ab8..6a7113e70 100644 --- a/apps/i2psnark/locale/messages_sk.po +++ b/apps/i2psnark/locale/messages_sk.po @@ -4,237 +4,250 @@ # To contribute translations, see http://www.i2p2.de/newdevelopers # # Translators: -# Svistwarrior273 , 2014 +# Roman 'Kaktuxista' Benji , 2014 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-09 19:27+0000\n" -"PO-Revision-Date: 2014-04-18 07:03+0000\n" -"Last-Translator: Svistwarrior273 \n" -"Language-Team: Slovak (http://www.transifex.com/projects/p/I2P/language/sk/)\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" +"Last-Translator: kytv \n" +"Language-Team: Slovak (http://www.transifex.com/otf/I2P/language/sk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sk\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 -#: ../java/src/org/klomp/snark/SnarkManager.java:1960 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "I2P tunel je zatvorený." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1655 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:515 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Celkový limit uploaderov bol zmenený na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:517 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Minimálny celkový limit uploaderov je {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:529 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Limit nárastu ŠP bol zmenený na {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:531 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Minimálny limit nárastu šírky pásma je {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Zdržanie pri spustení bolo zmenené na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:554 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Čas refreshu bol zmenený na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:556 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Refresh zakázaný" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Veľkosť stránky bola zmenená na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "Dátový priečinok musí byť absolútna cesta" -#: ../java/src/org/klomp/snark/SnarkManager.java:583 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "Dátový priečinok neexistuje" -#: ../java/src/org/klomp/snark/SnarkManager.java:585 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "Nie je priečinok" -#: ../java/src/org/klomp/snark/SnarkManager.java:587 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "Nečitateľné" -#: ../java/src/org/klomp/snark/SnarkManager.java:592 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Dátový priečinok bol zmenený na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:647 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "Zmeny I2CP a tunelov sa prejavia po zastavení všetkých torrentov" -#: ../java/src/org/klomp/snark/SnarkManager.java:651 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "I2CP nastavenia boli zmenené na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Odpája sa starý I2CP cieľ" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "I2CP nastavenia boli zmenené na {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:664 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Nie je možné sa pripojiť pomocou nových nastavení, vracia sa naspäť k starým I2CP nastaveniam" -#: ../java/src/org/klomp/snark/SnarkManager.java:668 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Nie je možné sa znova pripojiť pomocou starých nastavení!" -#: ../java/src/org/klomp/snark/SnarkManager.java:670 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Znova sa pripája k novému I2CP cieľu" -#: ../java/src/org/klomp/snark/SnarkManager.java:677 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "I2CP listener bol reštartovaný pre \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Nové súbory budú verejne čitateľné" -#: ../java/src/org/klomp/snark/SnarkManager.java:693 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Nové súbory nebudú verejne čitateľné" -#: ../java/src/org/klomp/snark/SnarkManager.java:700 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Povolené automatické spustenie" -#: ../java/src/org/klomp/snark/SnarkManager.java:702 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Zakázané automatické spustenie" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Povolené otvorené stopovače - pre prejavenie efektu sa vyžaduje reštart torrentu." -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Zakázané otvorené stopovače - pre prejavenie efektu sa vyžaduje reštart torrentu." -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "Povolené DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:719 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "Zakázané DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:721 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "Zmena DHT vyžaduje vypnutie a znovuotvorenie tunela" -#: ../java/src/org/klomp/snark/SnarkManager.java:728 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} téma bola načítaná, vráťte sa na hlavnú stránku i2psnark pre zobrazenie." -#: ../java/src/org/klomp/snark/SnarkManager.java:738 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Konfigurácia nebola zmenená." -#: ../java/src/org/klomp/snark/SnarkManager.java:770 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Zoznam otvorených stopovačov sa zmenil - pre prejavenie efektu sa vyžaduje reštart torrentu." -#: ../java/src/org/klomp/snark/SnarkManager.java:780 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Súkromný zoznam stopovačov bol zmenený - to sa bude týkať iba novo vytvorených torrentov." -#: ../java/src/org/klomp/snark/SnarkManager.java:826 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Nebolo možné uložiť konfiguráciu do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:904 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Pripája sa k I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:907 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Chyba pri pripájaní sa k I2P - skontrolujte si vaše I2CP nastavenia!" -#: ../java/src/org/klomp/snark/SnarkManager.java:916 -#: ../java/src/org/klomp/snark/SnarkManager.java:1692 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Chyba: Nebolo možné pridať torrent {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:938 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Nie je možné otvoriť \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:957 -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/SnarkManager.java:1140 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:162 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Torrent s týmto info hashom je už spustený: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:963 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "CHYBA - Žiadne I2P stopovače v súkromnom torrente \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:965 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "Varovanie - V \"{0}\" nie sú žiadne I2P stopovače, oznámené to bude iba DHT a otvoreným stopovačom I2P." -#: ../java/src/org/klomp/snark/SnarkManager.java:968 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "Varovanie - V \"{0}\" nie sú žiadne I2P stopovače, pričom otvorené stopovače sú zakázané, oznámené to bude iba DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:970 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -242,34 +255,46 @@ msgid "" "torrent." msgstr "Varovanie - V \"{0}\" nie sú žiadne I2P stopovače, pričom otvorené stopovače aj DHT sú zakázané, mali by ste otvorené stopovače alebo DHT pred spustením torrentu povoliť." -#: ../java/src/org/klomp/snark/SnarkManager.java:992 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Torrent v \"{0}\" je neplatný" -#: ../java/src/org/klomp/snark/SnarkManager.java:999 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:186 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Súbor torrentu bol odstránený: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "CHYBA - Nedostatok pamäte, nie je možné vytvoriť torrent z {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1011 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent bol pridaný a spustený: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1013 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent bol pridaný: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1069 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:89 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Získava sa {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1075 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -277,311 +302,363 @@ msgid "" "DHT." msgstr "Otvorené stopovače sú zakázané a my nemáme žiadnych DHT peerov. Získanie {0} nemusí uspieť, pokiaľ nespustíte ďalší torrent, prípadne nepovolíte otvorené stopovače alebo DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:1079 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Pridáva sa {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1111 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Sťahovanie je už spustené: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1150 -#: ../java/src/org/klomp/snark/SnarkManager.java:1173 -#: ../java/src/org/klomp/snark/SnarkManager.java:1611 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Nepodarilo sa skopírovať súbor torrentu do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "Príliš veľa súborov v \"{0}\" ({1}), odstraňuje sa!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1402 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Súbor torrentu \"{0}\" nemôže končiť na \".torrent\", odstraňuje sa!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1404 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "V \"{0}\" nie sú žiadne kúsky, odstraňuje sa!" +msgid "No pieces in \"{0}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1406 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "V \"{0}\" je príliš veľa kúskov, limit je {1}, odstraňuje sa!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "Kúsky v \"{0}\" ({1}B) sú príliš veľké, odstraňuje sa." +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1409 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "Limit je {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1411 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "Torrent \"{0}\" neobsahuje žiadne dáta, odstraňuje sa!" +msgid "Torrent \"{0}\" has no data!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1419 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Torrenty väčšie než {0}B zatiaľ nie sú podporované, odstraňuje sa \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1435 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Chyba: Nebolo možné odstrániť torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1456 -#: ../java/src/org/klomp/snark/SnarkManager.java:1474 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent bol zastavený: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1495 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent bol odstránený: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1503 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Pridávajú sa torrenty do {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1534 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "Limit nárastu šírky pásma je {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1556 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Sťahovanie bolo dokončené: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1607 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainformácie pre {0} boli doručené" -#: ../java/src/org/klomp/snark/SnarkManager.java:1608 -#: ../java/src/org/klomp/snark/SnarkManager.java:1837 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Spúšťa sa torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1623 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Chyba na torrente {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1686 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Nie je možné sa pripojiť k I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1836 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:126 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Otvára sa I2P tunel" -#: ../java/src/org/klomp/snark/SnarkManager.java:1860 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Otvára sa I2P tunel a spúšťajú sa všetky torrenty." -#: ../java/src/org/klomp/snark/SnarkManager.java:1923 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Zastavujú sa všetky torrenty a zatvára sa I2P tunel." -#: ../java/src/org/klomp/snark/SnarkManager.java:1942 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Po upozornení stopovačov sa zatvára I2P tunel." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Nie sú žiadne platné stopovače pre {0} - povoliť otvorené stopovače alebo DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Aktualizuje sa" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Aktualizuje sa z {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:77 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Stiahnuť súbor torrentu z {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:99 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Torrent nebol získaný z {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:153 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent bol získaný z {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:174 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent už spustený je: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:176 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent už vo fronte je: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:184 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Torrent na {0} nebol platný." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:247 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Anonymný BitTorrent klient" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260 -msgid "Router is down" -msgstr "Router nie je spustený" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 -msgid "Torrents" -msgstr "Torrenty" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1477 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2242 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Konfigurácia" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Router nie je spustený" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrenty" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Obnoviť stránku" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Fórum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Kliknite na tlačidlo \"Pridať torrent\" pre získanie torrentu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:345 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "zmazať správy" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2427 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Stav" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Skryť peerov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:423 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Zobraziť peerov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2236 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2256 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "ETA" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Odhadovaný zostávajúci čas" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:445 -msgid "ETA" -msgstr "ETA" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:450 -msgid "Downloaded" -msgstr "Stiahnuté" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "RX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Stiahnuté" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Veľkosť" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "TX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Uploadnuté" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:461 -msgid "TX" -msgstr "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "RX sadzba" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:467 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Dolná sadzba" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 -msgid "RX Rate" -msgstr "RX sadzba" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:476 -msgid "Up Rate" -msgstr "Horná sadzba" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:479 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "TX sadzba" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Horná sadzba" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Zastaviť všetky torrenty a I2P tunel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Zastaviť všetko" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Spustiť všetky zastavené torrenty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:510 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Spustiť všetko" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Spustiť všetky torrenty a I2P tunel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Neboli načítané žiadne torrenty." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Súhrny" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" @@ -589,7 +666,7 @@ msgstr[0] "1 torrent" msgstr[1] "{0} torrenty" msgstr[2] "{0} torrentov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" @@ -597,7 +674,7 @@ msgstr[0] "1 pripojený peer" msgstr[1] "{0} pripojení peerovia" msgstr[2] "{0} pripojených peerov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" @@ -605,174 +682,202 @@ msgstr[0] "1 DHT peer" msgstr[1] "{0} DHT peerovia" msgstr[2] "{0} DHT peerov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "Prvé" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Prvá stránka" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "Predchádzajúce" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Predchádzajúca stránka" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "Nasledujúce" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Nasledujúca stránka" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Posledné" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Posledná stránka" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "Neplatná URL: Musí začínať na \"http://\", \"{0}\" alebo \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet bol odstránený: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Súbor torrentu bol odstránený: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Sťahovanie odstránené: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Dátový súbor bol odstránený: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Dátový súbor nemohol byť odstránený: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Priečinok nemohol byť odstránený: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Priečinok bol odstránený: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "Chyba - Nie je možné zahrnúť alternatívne stopovače bez toho primárneho" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "Chyba - Nie je možné zmiešať v torrente súkromné aj verejné stopovače" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Pre \"{0}\" bol vytvorený torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:968 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "Mnoho I2P stopovačov od vás vyžaduje registrovať pred seedovaním nové torrenty - prosím urobte tak pred spustením \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Chyba pri vytváraní torrentu pre \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Nie je možné vytvoriť torrent pre neexistujúce dáta: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Chyba pri vytváraní torrentu - musíte zadať súbor alebo priečinok" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2018 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Zvolená možnosť odstrániť" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2019 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Uložiť konfiguráciu stopovača" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1025 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Odstránené" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Pridať stopovač" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Zadajte platný názov a URL stopovača" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2021 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Obnoviť predvolené nastavenia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1085 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Obnoviť predvolené stopovače" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1207 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Kontroluje sa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1209 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Alokuje sa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Chyba stopovača" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1254 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" @@ -780,356 +885,377 @@ msgstr[0] "1 peer" msgstr[1] "{0} peerovia" msgstr[2] "{0} peerov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1234 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Spúšťa sa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Seeduje sa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2369 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Dokončené" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1266 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1272 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Zablokované" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Žiadni peerovia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1296 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Zastavené" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Detaily torrentu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Zobraziť súbory" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Otvoriť súbor" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Zastaviť torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1404 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Zastaviť" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Spustiť torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1418 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Spustiť" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Odstrániť torrent zo zoznamu aktívnych zmazaním .torrent súboru." #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1435 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "Ste si istý, že chcete odstrániť súbor \\\"{0}\\\"\n(stiahnuté dáta nebudú odstránené) ?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1438 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Odstrániť" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Odstrániť .torrent súbor a aj príslušný dátový súbor(y)" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Ste si istý, že chcete odstrániť torrent \\\"{0}\\\" a s ním aj všetky stiahnuté dáta?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1458 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Zmazať" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Neznáme" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Seed" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1528 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Nezaujímavý (Peer nemá žiadne kúsky, ktoré potrebujeme)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Zapchaný (Peer nám neumožňuje žiadať o kúsky)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Nezaujímajúci sa (Nemáme žiadne kúsky, ktoré peer potrebuje)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1552 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Zapchaný (Neumožňujeme peerovi žiadať o kúsky)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1607 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Detaily sú v {0} stopovači" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1624 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Informácie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Pridať torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1677 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Z URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "Zadajte URL (iba I2P) pre stiahnutie torrentu, magnetový alebo maggotový link, prípadne info hash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1685 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Pridať torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1688 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Môžete tiež skopírovať .torrent súbory do: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1690 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Odstránenie .torrent spôsobí jeho zastavenie." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Vytvoriť torrent" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Dáta na seedovanie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1720 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Súbor alebo priečinok na seedovanie (musí byť v rámci špecifickej cesty)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Stopovače" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Primárne" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternatívne" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Vytvoriť torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1747 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "žiadne" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2033 -msgid "Configuration" -msgstr "Konfigurácia" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1784 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Dátový priečinok" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1788 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Súbory čitateľné všetkými" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Ak je zaškrtnuté, ostatní užívatelia budú môcť pristupovať k stiahnutým súborom" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1796 -msgid "Auto start" -msgstr "Automatické spustenie" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1800 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Ak je zaškrtnuté, automaticky sa spustia pridané torrenty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1804 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Téma" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1817 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Čas refreshu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1830 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Nikdy" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1836 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Zdržanie pri spustení" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minúty" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Veľkosť stránky" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1844 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "torrentov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1868 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Celkový limit uploaderov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "peerovia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1875 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Limit nárastu šírky pásma" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Odporúča sa polovica dostupnej šírky pásma." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Zobraziť alebo zmeniť šírku pásma routra" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Použiť aj otvorené stopovače" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1888 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Ak je zaškrtnuté, otvorené stopovače tak isto ako aj stopovače vypísané v súbore torrentu sa oboznámia so všetkými torrentmi" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1892 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Povoliť DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1896 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Ak je zaškrtnuté, použije sa DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1912 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Nastavenia prichádzajúcich dát" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1918 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Nastavenia odchádzajúcich dát" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1926 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "I2CP host" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1931 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "I2CP port" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "I2CP nastavenia" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1951 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Uložiť konfiguráciu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Názov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1973 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "URL webovej stránky" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Otvoriť" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Súkromné" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "Oznámiť URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2009 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Pridať" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2049 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "Neplatná magnetová URL {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2057 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" @@ -1137,7 +1263,7 @@ msgstr[0] "1 hop" msgstr[1] "{0} hopy" msgstr[2] "{0} hopov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2058 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" @@ -1145,106 +1271,135 @@ msgstr[0] "1 tunel" msgstr[1] "{0} tunely" msgstr[2] "{0} tunelov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2265 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Súbor torrentu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Primárny stopovač" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Zoznam stopovačov" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2311 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Komentár" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2320 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Vytvorené" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2330 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Vytvorené užívateľom" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2340 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Magnetový link" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2347 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Súkromný torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2357 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2421 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2423 -msgid "Size" -msgstr "Veľkosť" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2364 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Dokončenie" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Zostávajúce" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2381 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Súbory" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2386 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Kúsky" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2390 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Veľkosť kúsku" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2413 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2417 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Priečinok" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Priorita" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Hore do priečinka vyššej úrovne" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent nenájdený?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2480 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "Súbor nenájdený v torrente?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "dokončiť" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "zostávajúcich" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2543 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Vysoká" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normálna" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Preskočiť" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2562 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Uložiť priority" diff --git a/apps/i2psnark/locale/messages_sv.po b/apps/i2psnark/locale/messages_sv.po index 4dc672d67..60bf28a92 100644 --- a/apps/i2psnark/locale/messages_sv.po +++ b/apps/i2psnark/locale/messages_sv.po @@ -5,8 +5,10 @@ # # Translators: # 123hund123 , 2011 -# samaire , 2013 +# Anders Nilsson , 2015 +# Calle Rundgren , 2013 # ducki2p , 2011 +# cacapo , 2015 # hottuna , 2011 # hottuna , 2013 # hottuna , 2011-2012 @@ -17,232 +19,245 @@ msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-09 19:27+0000\n" -"PO-Revision-Date: 2014-01-12 13:14+0000\n" -"Last-Translator: WinterFairy \n" -"Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/I2P/language/sv_SE/)\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-08 21:08+0000\n" +"Last-Translator: Anders Nilsson \n" +"Language-Team: Swedish (Sweden) (http://www.transifex.com/otf/I2P/language/sv_SE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sv_SE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 -#: ../java/src/org/klomp/snark/SnarkManager.java:1960 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "Inga fler torrents kör." + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "I2P-tunneln är stängd." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1655 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:515 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "Gräns för totalt antal uppladdare är bytt till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:517 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "Minsta tillåtna gräns för uppladdare är {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:529 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Uppladdningsbandbredd bytt till {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:531 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Minsta uppladdningsbandbredd bytt till {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "Fördröjning vid uppstart bytt till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:554 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "Uppdateringstiden ändrad till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:556 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "Uppdatering inaktiverad" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "Torrentar per sida ändrat till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "Datamappen måste vara en absolut sökväg" -#: ../java/src/org/klomp/snark/SnarkManager.java:583 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "Datamappen finns ej" -#: ../java/src/org/klomp/snark/SnarkManager.java:585 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "Inte en mapp" -#: ../java/src/org/klomp/snark/SnarkManager.java:587 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "Oläsbar" -#: ../java/src/org/klomp/snark/SnarkManager.java:592 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "Datamappen ändrad till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:647 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "I2CP- och tunnelförändringar kommer träda i kraft efter alla torrentar stoppats" -#: ../java/src/org/klomp/snark/SnarkManager.java:651 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "Alternativ för I2CP ändrade till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "Kopplar ifrån gammal I2CP destination" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "Inställningar för I2CP ändrade till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:664 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "Misslyckades med anslutningsförsök med nya inställningar, återställer de gamla I2CP inställningarna" -#: ../java/src/org/klomp/snark/SnarkManager.java:668 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "Misslyckades med anslutningsförsök med gamla inställningar!" -#: ../java/src/org/klomp/snark/SnarkManager.java:670 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "Återanslöt mot den nya I2CP destinationen" -#: ../java/src/org/klomp/snark/SnarkManager.java:677 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "I2CP-lyssnare omstartad för \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "Nya filer kommer vara publikt läsbara" -#: ../java/src/org/klomp/snark/SnarkManager.java:693 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "Nya filer kommer inte vara publikt läsbara" -#: ../java/src/org/klomp/snark/SnarkManager.java:700 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "Aktiverade automatisk start" -#: ../java/src/org/klomp/snark/SnarkManager.java:702 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "Inaktiverade automatisk start" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "Aktiverade smart sortering" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "Inaktiverade smart sortering" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "Aktiverade publika trackers - torrenten måste startas om för att inställningen ska träda i kraft" -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "Inaktiverade publika trackers - torrenten måste startas om för att inställningen ska träda i kraft" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "Aktivera DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:719 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "Inaktiverade DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:721 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "Förändring i DHT kräver att tunneln stängs och öppnas igen " -#: ../java/src/org/klomp/snark/SnarkManager.java:728 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} tema laddat, återgå till huvudvyn för i2psnark." -#: ../java/src/org/klomp/snark/SnarkManager.java:738 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "Inställningar oförändrade." -#: ../java/src/org/klomp/snark/SnarkManager.java:770 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "Listan över publika trackers förändrad - torrenten måste startas om för att inställningen ska träda i kraft" -#: ../java/src/org/klomp/snark/SnarkManager.java:780 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "Privat trackerlista ändrad - påverkar bara nyligen skapade torrents" -#: ../java/src/org/klomp/snark/SnarkManager.java:826 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "Misslyckades med att spara inställningar till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:904 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Ansluter till I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:907 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "Problem vid anslutning till I2P - kontrollera dina inställningar för I2CP!" -#: ../java/src/org/klomp/snark/SnarkManager.java:916 -#: ../java/src/org/klomp/snark/SnarkManager.java:1692 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "Problem: Kunde inte lägga till torrent {0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:938 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "Kan inte öppna \"{0}\"" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:957 -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/SnarkManager.java:1140 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:162 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "Torrent med denna infohash körs redan: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:963 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "FEL - Inga I2P trackers i den privata torrenten \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:965 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "Varning - Ingen I2P tracker i \"{0}\", kommer enbart att annonsera till publika I2P trackers och DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:968 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "Varning - Ingen I2P tracker i \"{0}\" och publika trackers är inaktiverade, kommer enbart att annonsera till DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:970 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -250,34 +265,46 @@ msgid "" "torrent." msgstr "Varning - Ingen I2P tracker i \"{0}\" och både DHT och publika trackers är inaktiverade, du bör aktivera publika trackers eller DHT innan du startar torrenten. " -#: ../java/src/org/klomp/snark/SnarkManager.java:992 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "Torrent i \"{0}\" är ogiltig" -#: ../java/src/org/klomp/snark/SnarkManager.java:999 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:186 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "Torrentfil borttagen: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "Torrentfil flyttad från {0} till {1}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "FEL - Minnet har tagit slut, kan inte skapa torrent från {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1011 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "Torrent tillagd och startad: \"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "Torrent tillagd och startad: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1013 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "Torrent tillagd: \"{0}\"" +msgid "Torrent added: {0}" +msgstr "Torrent tillagd: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1069 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:89 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "Hämtar {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1075 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -285,968 +312,1098 @@ msgid "" "DHT." msgstr "Publika trackers är inaktiverade och vi har inga DHT klienter. Hämtningen av {0} kan kanske inte genomföras innan du startar en annan torrent eller aktiverar publika trackers eller DHT." -#: ../java/src/org/klomp/snark/SnarkManager.java:1079 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "Lägger till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1111 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "Hämtar redan: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1150 -#: ../java/src/org/klomp/snark/SnarkManager.java:1173 -#: ../java/src/org/klomp/snark/SnarkManager.java:1611 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "Misslyckades att kopiera torrentfil till {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "För många filer i \"{0}\" ({1}), tar bort den!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "För många filer i \"{0}\" ({1})!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1402 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "Torrenten \"{0}\" får inte sluta med \".torrent\", tar bort den!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "Torrentfilen \"{0}\" kan inte sluta på \".torrent\"!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1404 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "Inga delar i \"{0}\", tar bort den!" +msgid "No pieces in \"{0}\"!" +msgstr "Inga delar i \"{0}\"!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1406 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "För många delar i \"{0}\", gränsen är {1}, tar bort den!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "För många delar i \"{0}\", gränsen är {1}!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "För stora delar i \"{0}\" ({1}B), tar bort den!" +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "Delarna är för stora i \"{0}\" ({1}B)!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1409 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "Gränsen är {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1411 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "Torrenten \"{0}\" har ingen data, tar bort den!" +msgid "Torrent \"{0}\" has no data!" +msgstr "Torrent \"{0}\" har ingen data!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1419 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "Torrentar större än {0}B stöds inte än, tar bort \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "Torrents större än {0}B stöds inte än \"{1}\"!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1435 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "Fel: Kunde ej ta bort torrenten {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1456 -#: ../java/src/org/klomp/snark/SnarkManager.java:1474 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "Torrent stannad: \"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "Torrent stoppad: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1495 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "Torrent borttagen: \"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1503 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "Lägger till torrentar i {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1534 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "Upp bandbredds gräns är {0} KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:1556 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "Hämtning klar: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1607 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "Metainfo mottagen för {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1608 -#: ../java/src/org/klomp/snark/SnarkManager.java:1837 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "Startar torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1623 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "Fel på torrent {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1686 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "Misslyckades med att ansluta till I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:1836 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:126 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "Öppnar I2P tunneln" -#: ../java/src/org/klomp/snark/SnarkManager.java:1860 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "Öppnar I2P-tunneln och startar torrentar." -#: ../java/src/org/klomp/snark/SnarkManager.java:1923 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "Stoppar alla torrentar och stänger I2P-tunneln." -#: ../java/src/org/klomp/snark/SnarkManager.java:1942 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "Stänger I2P tunnel efter att ha meddelat trackers." -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "Avslutade omkontroll av torrent {0}, nu {1} färdig" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "Avslutade omkontroll av torrent {0}, oförändrad" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "Fel vid kontroll av torrent {0}" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "Ingen giltig tracker för {0} - aktivera publika trackers eller DHT?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "Uppdaterar" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "Uppdaterar från {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:77 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "Hämtar torrentfil från {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:99 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "Torrent kunde inte hämtas från {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:153 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "Torrent hämtad från {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:174 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "Torrent redan igång: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:176 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "Torrent finns redan i kön: {0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:184 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "Torrent vid {0} var inte giltig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:247 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - Anonym bittorrentklient" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:260 -msgid "Router is down" -msgstr "Routern är avstängd" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 -msgid "Torrents" -msgstr "Torrentar" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1477 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2242 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Inställningar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "Anonym BitTorrent Klient" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "Routern är avstängd" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "Torrentar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Ladda om sida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Forum" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "Klicka på \"Lägg till torrent\" för att hämta en torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:345 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:346 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "rensa meddelandena" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:398 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:400 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2427 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Status" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "Sortera efter{0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "Dölj klienter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:423 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "Visa klienter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2236 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2256 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "Torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "Filtyp" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "Förväntas klar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "Uppskattad återstående tid" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:445 -msgid "ETA" -msgstr "Förväntas klar" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:450 -msgid "Downloaded" -msgstr "Hämtade" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "RX" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Hämtade" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Storlek" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "TX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "Upload ratio" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Uppladdat" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:461 -msgid "TX" -msgstr "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "RX Rate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:467 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "Nerhastighet" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 -msgid "RX Rate" -msgstr "RX Rate" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:476 -msgid "Up Rate" -msgstr "Upphastighet" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:479 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "TX Rate" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "Upphastighet" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "Stoppa alla torrents och I2P-tunneln" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "Stoppa alla" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "Starta alla stannade torrentar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:510 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "Starta alla" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "Starta alla torrents och I2P-tunneln" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "Inga torrents laddade." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Totalt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "1 torrent" msgstr[1] "{0} torrentar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "1 ansluten klient" msgstr[1] "{0} anslutna klienter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "1 DHT klient" msgstr[1] "{0} DHT klienter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "Destination" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "Första" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "Första sidan" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "Bakåt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "Föregående sida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "Nästa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "Nästa sida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "Sista" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "Sista sidan" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "Data directory kan inte skapas" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "Kan inte lägga till torrent{0} inuti annan torrent:{1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "Ogiltig adress: Måste inledas med \"http://\", \"{0}\" eller \"{1}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:785 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet borttagen: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:820 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "Torrentfil borttagen: {0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "Hämtning borttagen: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "Datafil borttagen: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "Datafil kunde inte tas bort: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:854 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "Katalogen kunde inta tas bort: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "Katalogen bort tagen: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "Kan inte lägga till en torrent som slutar på \".torrent\":{0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "Torrent med detta namn kör redan: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "Kan inte lägga till en torrent som inkluderar en I2P directory:{0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "Kan inte lägga till en torrent{0} som inkluderar en annan torrent{1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "Fel - Kan inte inkludera alternativa trackers utan en primär tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "Fel - Kan inte blanda privata och publika trackers i samma torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "Torrent skapad för \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:968 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "Många I2P trackers kräver att du registrerar nya torrentar innan uppladdningen påbörjas - gör det innan \"{0}\" startas" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:970 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "Misslyckades med att skapa torrent för \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "Kan ej skapa torrent för data som ej finns: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "Misslyckades med att skapa torrent - en fil eller mapp måste anges" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2018 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "Ta bort valda" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2019 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "Spara tracker konfiguration" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1025 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "Borttagen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1054 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "Lägg till tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "Ange giltigt namn och adresser för trackern " #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2021 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "Återställ standardvärden" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1085 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "Återställ standard trackers " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1207 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "Kontrollerar " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1209 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "Allokerar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Trackerfel" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1226 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1254 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "1 klient" msgstr[1] "{0} klienter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1234 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "Startar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "Uppladdning" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1247 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1261 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2369 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2483 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Färdig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1266 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1267 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1272 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1273 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "Ok" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1277 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1278 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1283 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Avstannad" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1289 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "Inga klienter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1296 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Stoppad" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "Torrentdetaljer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Se filer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Öppna fil" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "Stoppa torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1404 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Stoppa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "Starta torrenten" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1418 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Starta" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "Ta bort torrenten från den aktiva listan, tar bort .torrent filen" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1435 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "Är du säker på att du vill radera filen \\''{0}\\' (hämtad data kommer ej raderas) ?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1438 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Ta bort" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "Ta bort .torrent filen och tillhörande datafil(er)" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "Är du säker på att du vill ta bort torrenten \"{0}\" och all hämtad data?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1458 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Ta bort" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Okänd" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "Källa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1528 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "Ointressant (klienten har inga delar vi behöver)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "Strypt (klienten låter oss inte be om delar)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "Ointresserad (vi har inga delar klienten behöver)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1552 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "Stryper (vi låter inte klienten be om delar)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1607 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Detaljer för {0} tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1624 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Info" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "Lägg till torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1677 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "Adress" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "Ange torrentfilens adress (enbart I2P), magnet-länk, maggot-länk eller infohash" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1685 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "Lägg till torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1688 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "Data dir" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "Ange katalogen att spara datan i (förval {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "Du kan även kopiera .torrent filer till: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1690 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "Borttagning av .torrent fil kommer stanna den." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1713 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "Skapa torrent" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "Data att ladda upp" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1720 -msgid "File or directory to seed (must be within the specified path)" -msgstr "Fil eller mapp att ladda upp (måste finnas på angiven plats)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "Fil eller katalog att seeda (fullständig sökväg eller inom katalog {0})" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1966 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "Primär" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "Alternativ" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "Skapa torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1747 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "inga" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2033 -msgid "Configuration" -msgstr "Inställningar" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1784 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "Datamapp" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1788 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "Filer läsbara för alla" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "Välj detta för att ge andra användare tillgång till hämtade filer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1796 -msgid "Auto start" -msgstr "Automatisk start" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "Starta torrents automatiskt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1800 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "Välj detta för att automatiskt starta tillagda torrentfiler" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1804 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "Smart torrent-sortering" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "Om valt, ignorera ord som \"the\" vid sortering" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "Tema" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1817 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "Uppdateringsintervall" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1830 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "Aldrig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1836 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "Fördröjning av uppstart" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "minuter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "Per sida" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1844 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "torrentar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1868 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "Gräns för totalt antal uppladdare" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "klienter" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1875 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Gräns för bandbredd uppåt" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "Hälften av tillgänglig bandbredd rekommenderas." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "Se eller ändra routerns bandbredd" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "Använd också publika trackers" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1888 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "Välj detta för att annonsera torrentar till publika trackers såväl som de listade i torrentfilen" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1892 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "Aktivera DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1896 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "Välj detta för att använda DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1912 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "Inställningar för inkommande" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1918 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "Inställningar för utgående" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1926 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "I2CP-värd" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1931 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "I2CP-port" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1946 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "Alternativ för I2CP" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1951 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Spara inställningar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "Namn" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1973 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "Webbplatsadress" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "Standard" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Publik" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "Privat" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "Annonseringsadress" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2009 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "Lägg till" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2049 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "Ogiltig magnet-adress {0}" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2057 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "1 hopp" msgstr[1] "{0} hopp" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2058 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "1 tunnel" msgstr[1] "{0} tunnlar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2265 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Torrentfil" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "Plats för data" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "Info hash" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "Primär tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Trackerlista" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2311 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "Kommentar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2320 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "Skapad" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2330 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "Skapad av" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2340 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "Tillagd" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "Färdig" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Magnet länk" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2347 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "Privat torrent" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2357 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2421 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2423 -msgid "Size" -msgstr "Storlek" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2364 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "Färdigställning" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "Kvar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2381 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Filer" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2386 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Delar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2390 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Delstorlek" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2413 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2417 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "Ladda om sidan för resultat" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "Tvinga omkontroll" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Mapp" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Prioritet" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "Upp till högre mappnivå" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "Torrent hittades ej?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2480 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "Fil hittades ej i torrent?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "färdig" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2494 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "kvar" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2543 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Hög" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2548 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Normal" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Hoppa över" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2562 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "Sätt alla höga" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "Sätt alla normala" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "Hoppa över alla" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "Spara prioriteter" diff --git a/apps/i2psnark/locale/messages_vi.po b/apps/i2psnark/locale/messages_vi.po index 9d4bf81d6..0894f625a 100644 --- a/apps/i2psnark/locale/messages_vi.po +++ b/apps/i2psnark/locale/messages_vi.po @@ -9,232 +9,245 @@ msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 20:06+0000\n" -"PO-Revision-Date: 2013-11-19 23:52+0000\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 17:17+0000\n" "Last-Translator: kytv \n" -"Language-Team: Vietnamese (http://www.transifex.com/projects/p/I2P/language/vi/)\n" +"Language-Team: Vietnamese (http://www.transifex.com/otf/I2P/language/vi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: vi\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "Đường hầm I2P đóng lại." #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" msgstr "Giới hạn băng thông lên đổi thành {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" msgstr "Tối thiểu băng thông lên là {0}KBps" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "Nối kết vào I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "" #. TODO - if the existing one is a magnet, delete it and add the metainfo #. instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" " DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " @@ -242,34 +255,46 @@ msgid "" "torrent." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" +msgid "Torrent added and started: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" +msgid "Torrent added: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " @@ -277,962 +302,1092 @@ msgid "" "DHT." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" +msgid "Too many files in \"{0}\" ({1})!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" +msgid "No pieces in \"{0}\"!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" +msgid "Too many pieces in \"{0}\", limit is {1}!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." +msgid "Pieces are too large in \"{0}\" ({1}B)!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" +msgid "Torrent \"{0}\" has no data!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" +msgid "Torrent stopped: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "" -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "Cấu hình" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "Nạp lại trang" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "Diễn đàn" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "Tình trạng" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "Đã tải xuống" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "Đã tải xuống" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "Kích thước" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "Đã tải lên" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "Tổng cộng" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "" #. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. value=\"").append(_t("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "Hoàn tất" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" msgstr "OK" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "Khựng" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "Ngưng" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "Xem tập tin" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "Mở tập tin" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "Ngưng" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "Bắt đầu" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "Bỏ" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "Xóa" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "Không rõ" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "Thông tin" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" "Enter the torrent file download URL (I2P only), magnet link, maggot link, or" " info hash" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "" #. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "Cấu hình" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "Tự động bắt đầu" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "phút" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "Giới hạn băng thông lên" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" "If checked, announce torrents to open trackers as well as the tracker listed" " in the torrent file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "Lưu cấu hình" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "Mở" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "Kích thước" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "Tập tin" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "Mảnh" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "Kích thước mảnh" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "Danh mục" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "Ưu tiên" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "hoàn tất" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "Cao" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "Thường" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "Lờ" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "" diff --git a/apps/i2psnark/locale/messages_zh.po b/apps/i2psnark/locale/messages_zh.po index 3ec74024a..4a78516fc 100644 --- a/apps/i2psnark/locale/messages_zh.po +++ b/apps/i2psnark/locale/messages_zh.po @@ -2,1247 +2,1396 @@ # Copyright (C) 2009 The I2P Project # This file is distributed under the same license as the i2psnark package. # To contribute translations, see http://www.i2p2.de/newdevelopers -# +# # Translators: # ducki2p , 2011 # foo , 2009 # walking , 2013 # wwj402 , 2013 +# YF , 2014-2015 msgid "" msgstr "" "Project-Id-Version: I2P\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-01 19:56+0000\n" -"PO-Revision-Date: 2013-11-22 05:46+0000\n" -"Last-Translator: wwj402 \n" -"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/I2P/" -"language/zh_CN/)\n" -"Language: zh_CN\n" +"POT-Creation-Date: 2015-11-05 17:12+0000\n" +"PO-Revision-Date: 2015-11-05 19:20+0000\n" +"Last-Translator: YF \n" +"Language-Team: Chinese (China) (http://www.transifex.com/otf/I2P/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../java/src/org/klomp/snark/IdleChecker.java:69 -#: ../java/src/org/klomp/snark/SnarkManager.java:1938 -#: ../java/src/org/klomp/snark/SnarkManager.java:1949 +#: ../java/src/org/klomp/snark/IdleChecker.java:75 +msgid "No more torrents running." +msgstr "没有更多种子正在运行。" + +#: ../java/src/org/klomp/snark/IdleChecker.java:76 +#: ../java/src/org/klomp/snark/SnarkManager.java:2539 +#: ../java/src/org/klomp/snark/SnarkManager.java:2550 msgid "I2P tunnel closed." msgstr "I2P隧道已关闭" #: ../java/src/org/klomp/snark/MagnetURI.java:42 #: ../java/src/org/klomp/snark/MagnetURI.java:52 -#: ../java/src/org/klomp/snark/SnarkManager.java:1644 +#: ../java/src/org/klomp/snark/SnarkManager.java:2221 msgid "Magnet" msgstr "Magnet" -#: ../java/src/org/klomp/snark/SnarkManager.java:504 +#: ../java/src/org/klomp/snark/SnarkManager.java:791 #, java-format msgid "Total uploaders limit changed to {0}" msgstr "总上传种子数限制已更新为{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:506 +#: ../java/src/org/klomp/snark/SnarkManager.java:793 #, java-format msgid "Minimum total uploaders limit is {0}" msgstr "最低上传种子数限制为{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:518 +#: ../java/src/org/klomp/snark/SnarkManager.java:805 #, java-format msgid "Up BW limit changed to {0}KBps" -msgstr "上传带宽限制改为 {0} KBps" +msgstr "上传带宽限制改为 {0} KB/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:520 +#: ../java/src/org/klomp/snark/SnarkManager.java:807 #, java-format msgid "Minimum up bandwidth limit is {0}KBps" -msgstr "最小上传带宽限制为 {0} KBps" +msgstr "最小上传带宽限制为 {0} KB/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:532 +#: ../java/src/org/klomp/snark/SnarkManager.java:819 #, java-format msgid "Startup delay changed to {0}" msgstr "下载前的延迟已更新为{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:543 +#: ../java/src/org/klomp/snark/SnarkManager.java:830 #, java-format msgid "Refresh time changed to {0}" msgstr "刷新时间更新为{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:545 +#: ../java/src/org/klomp/snark/SnarkManager.java:832 msgid "Refresh disabled" msgstr "刷新已禁用" -#: ../java/src/org/klomp/snark/SnarkManager.java:561 +#: ../java/src/org/klomp/snark/SnarkManager.java:848 #, java-format msgid "Page size changed to {0}" msgstr "页面容量更新为{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:570 +#: ../java/src/org/klomp/snark/SnarkManager.java:857 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:958 msgid "Data directory must be an absolute path" msgstr "数据存放目录必须是绝对路径" -#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#: ../java/src/org/klomp/snark/SnarkManager.java:859 msgid "Data directory does not exist" msgstr "数据存放目录不存在" -#: ../java/src/org/klomp/snark/SnarkManager.java:574 +#: ../java/src/org/klomp/snark/SnarkManager.java:861 msgid "Not a directory" msgstr "不是文件夹" -#: ../java/src/org/klomp/snark/SnarkManager.java:576 +#: ../java/src/org/klomp/snark/SnarkManager.java:863 msgid "Unreadable" msgstr "不可读" -#: ../java/src/org/klomp/snark/SnarkManager.java:581 +#: ../java/src/org/klomp/snark/SnarkManager.java:868 #, java-format msgid "Data directory changed to {0}" msgstr "数据存放目录更新至{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:636 +#: ../java/src/org/klomp/snark/SnarkManager.java:923 msgid "I2CP and tunnel changes will take effect after stopping all torrents" msgstr "I2CP与隧道设置的变化在所有种子停止后才能生效" -#: ../java/src/org/klomp/snark/SnarkManager.java:640 +#: ../java/src/org/klomp/snark/SnarkManager.java:927 #, java-format msgid "I2CP options changed to {0}" msgstr "I2CP 选项改为 {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:646 +#: ../java/src/org/klomp/snark/SnarkManager.java:933 msgid "Disconnecting old I2CP destination" msgstr "正在断开旧的I2CP目标" -#: ../java/src/org/klomp/snark/SnarkManager.java:648 +#: ../java/src/org/klomp/snark/SnarkManager.java:935 #, java-format msgid "I2CP settings changed to {0}" msgstr "I2CP设置改为{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:653 +#: ../java/src/org/klomp/snark/SnarkManager.java:940 msgid "" "Unable to connect with the new settings, reverting to the old I2CP settings" msgstr "无法通过新设置连接,恢复I2CP的旧设置" -#: ../java/src/org/klomp/snark/SnarkManager.java:657 +#: ../java/src/org/klomp/snark/SnarkManager.java:944 msgid "Unable to reconnect with the old settings!" msgstr "旧设置也无法连接!" -#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#: ../java/src/org/klomp/snark/SnarkManager.java:946 msgid "Reconnected on the new I2CP destination" msgstr "重新连接新I2CP目标" -#: ../java/src/org/klomp/snark/SnarkManager.java:666 +#: ../java/src/org/klomp/snark/SnarkManager.java:953 #, java-format msgid "I2CP listener restarted for \"{0}\"" msgstr "\"{0}\"的I2CP监听端口已启动" -#: ../java/src/org/klomp/snark/SnarkManager.java:680 +#: ../java/src/org/klomp/snark/SnarkManager.java:967 msgid "New files will be publicly readable" msgstr "新文件将对公共可读" -#: ../java/src/org/klomp/snark/SnarkManager.java:682 +#: ../java/src/org/klomp/snark/SnarkManager.java:969 msgid "New files will not be publicly readable" msgstr "新文件不会对公共可读" -#: ../java/src/org/klomp/snark/SnarkManager.java:689 +#: ../java/src/org/klomp/snark/SnarkManager.java:976 msgid "Enabled autostart" msgstr "启用自动启动" -#: ../java/src/org/klomp/snark/SnarkManager.java:691 +#: ../java/src/org/klomp/snark/SnarkManager.java:978 msgid "Disabled autostart" msgstr "禁用自动启动" -#: ../java/src/org/klomp/snark/SnarkManager.java:697 +#: ../java/src/org/klomp/snark/SnarkManager.java:985 +msgid "Enabled smart sort" +msgstr "已启用智能排序" + +#: ../java/src/org/klomp/snark/SnarkManager.java:987 +msgid "Disabled smart sort" +msgstr "已禁用智能排序" + +#: ../java/src/org/klomp/snark/SnarkManager.java:994 msgid "Enabled open trackers - torrent restart required to take effect." msgstr "启用OpenTracker-重新启动种子后生效" -#: ../java/src/org/klomp/snark/SnarkManager.java:699 +#: ../java/src/org/klomp/snark/SnarkManager.java:996 msgid "Disabled open trackers - torrent restart required to take effect." msgstr "禁用OpenTracker - 重新启动种子后生效" -#: ../java/src/org/klomp/snark/SnarkManager.java:706 +#: ../java/src/org/klomp/snark/SnarkManager.java:1003 msgid "Enabled DHT." msgstr "DHT 已启用" -#: ../java/src/org/klomp/snark/SnarkManager.java:708 +#: ../java/src/org/klomp/snark/SnarkManager.java:1005 msgid "Disabled DHT." msgstr "DHT 已禁用" -#: ../java/src/org/klomp/snark/SnarkManager.java:710 +#: ../java/src/org/klomp/snark/SnarkManager.java:1007 msgid "DHT change requires tunnel shutdown and reopen" msgstr "DHT 修改生效需要关闭或重启。" -#: ../java/src/org/klomp/snark/SnarkManager.java:717 +#: ../java/src/org/klomp/snark/SnarkManager.java:1014 #, java-format msgid "{0} theme loaded, return to main i2psnark page to view." msgstr "{0} 主题已加载,浏览效果请到 i2psnark 主页。" -#: ../java/src/org/klomp/snark/SnarkManager.java:727 +#: ../java/src/org/klomp/snark/SnarkManager.java:1024 msgid "Configuration unchanged." msgstr "设置未改变" -#: ../java/src/org/klomp/snark/SnarkManager.java:759 +#: ../java/src/org/klomp/snark/SnarkManager.java:1056 msgid "Open Tracker list changed - torrent restart required to take effect." msgstr "OpenTracker列表已改变 - 重新启动种子后生效" -#: ../java/src/org/klomp/snark/SnarkManager.java:769 +#: ../java/src/org/klomp/snark/SnarkManager.java:1066 msgid "Private tracker list changed - affects newly created torrents only." msgstr "PT 列表已更改 - 仅对新创建的种子有效" -#: ../java/src/org/klomp/snark/SnarkManager.java:815 +#: ../java/src/org/klomp/snark/SnarkManager.java:1112 #, java-format msgid "Unable to save the config to {0}" msgstr "无法保存设置到{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:893 +#: ../java/src/org/klomp/snark/SnarkManager.java:1193 msgid "Connecting to I2P" msgstr "正在连接到I2P" -#: ../java/src/org/klomp/snark/SnarkManager.java:896 +#: ../java/src/org/klomp/snark/SnarkManager.java:1196 msgid "Error connecting to I2P - check your I2CP settings!" msgstr "连接I2P时发生错误 - 请检查I2CP设置!" -#: ../java/src/org/klomp/snark/SnarkManager.java:905 -#: ../java/src/org/klomp/snark/SnarkManager.java:1681 +#: ../java/src/org/klomp/snark/SnarkManager.java:1205 +#: ../java/src/org/klomp/snark/SnarkManager.java:2270 #, java-format msgid "Error: Could not add the torrent {0}" msgstr "错误:无法添加种子{0}" #. catch this here so we don't try do delete it below -#: ../java/src/org/klomp/snark/SnarkManager.java:927 +#: ../java/src/org/klomp/snark/SnarkManager.java:1228 #, java-format msgid "Cannot open \"{0}\"" msgstr "无法打开 \"{0}\"" -#. TODO - if the existing one is a magnet, delete it and add the metainfo instead? -#: ../java/src/org/klomp/snark/SnarkManager.java:946 -#: ../java/src/org/klomp/snark/SnarkManager.java:1047 -#: ../java/src/org/klomp/snark/SnarkManager.java:1129 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:159 +#. TODO - if the existing one is a magnet, delete it and add the metainfo +#. instead? +#: ../java/src/org/klomp/snark/SnarkManager.java:1247 +#: ../java/src/org/klomp/snark/SnarkManager.java:1388 +#: ../java/src/org/klomp/snark/SnarkManager.java:1476 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:166 #, java-format msgid "Torrent with this info hash is already running: {0}" msgstr "具有相同Hash链接的种子已在下载中:{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:952 +#: ../java/src/org/klomp/snark/SnarkManager.java:1253 #, java-format msgid "ERROR - No I2P trackers in private torrent \"{0}\"" msgstr "错误 - 私有种子\"{0}\"中缺少 I2P Tracker" -#: ../java/src/org/klomp/snark/SnarkManager.java:954 +#: ../java/src/org/klomp/snark/SnarkManager.java:1255 #, java-format msgid "" -"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and " -"DHT only." -msgstr "" -"警告 - \"{0}\"中缺少 I2P Tracker,程序将仅通过 I2P 中的开放式 Tracker 和 DHT " -"下载。" +"Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and" +" DHT only." +msgstr "警告 - \"{0}\"中缺少 I2P Tracker,程序将仅通过 I2P 中的开放式 Tracker 和 DHT 下载。" -#: ../java/src/org/klomp/snark/SnarkManager.java:957 +#: ../java/src/org/klomp/snark/SnarkManager.java:1258 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will " "announce to DHT only." -msgstr "" -"警告 - \"{0}\"中缺少 I2P Tracker,已禁用 I2P Open Tracker,程序将仅通过 DHT " -"下载。" +msgstr "警告 - \"{0}\"中缺少 I2P Tracker,已禁用 I2P Open Tracker,程序将仅通过 DHT 下载。" -#: ../java/src/org/klomp/snark/SnarkManager.java:959 +#: ../java/src/org/klomp/snark/SnarkManager.java:1260 #, java-format msgid "" "Warning - No I2P trackers in \"{0}\", and DHT and open trackers are " -"disabled, you should enable open trackers or DHT before starting the torrent." -msgstr "" -"警告 - \"{0}\"中缺少 I2P Tracker,已禁用 I2P Open Tracker 和 DHT,下载先您需" -"要先启用 OpenTracker 或 DHT 。" +"disabled, you should enable open trackers or DHT before starting the " +"torrent." +msgstr "警告 - \"{0}\"中缺少 I2P Tracker,已禁用 I2P Open Tracker 和 DHT,下载先您需要先启用 OpenTracker 或 DHT 。" -#: ../java/src/org/klomp/snark/SnarkManager.java:981 +#: ../java/src/org/klomp/snark/SnarkManager.java:1286 #, java-format msgid "Torrent in \"{0}\" is invalid" msgstr "无效种子 \"{0}\" " -#: ../java/src/org/klomp/snark/SnarkManager.java:988 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:183 +#: ../java/src/org/klomp/snark/SnarkManager.java:1292 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1042 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1069 +#, java-format +msgid "Torrent file deleted: {0}" +msgstr "种子文件已删除:{0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1295 +#, java-format +msgid "Torrent file moved from {0} to {1}" +msgstr "种子文件已从 {0} 移动到 {1}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1299 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:193 #, java-format msgid "ERROR - Out of memory, cannot create torrent from {0}" msgstr "错误: 内存不足,无法为 {0} 创建种子。" -#: ../java/src/org/klomp/snark/SnarkManager.java:1000 +#: ../java/src/org/klomp/snark/SnarkManager.java:1321 #, java-format -msgid "Torrent added and started: \"{0}\"" -msgstr "已添加并启动种子:\"{0}\"" +msgid "Torrent added and started: {0}" +msgstr "种子已添加并开始:{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1002 +#: ../java/src/org/klomp/snark/SnarkManager.java:1323 #, java-format -msgid "Torrent added: \"{0}\"" -msgstr "已添加种子:\"{0}\"" +msgid "Torrent added: {0}" +msgstr "种子已添加:{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1058 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:87 +#: ../java/src/org/klomp/snark/SnarkManager.java:1399 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:93 #, java-format msgid "Fetching {0}" msgstr "正在获取{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1064 +#: ../java/src/org/klomp/snark/SnarkManager.java:1405 #, java-format msgid "" "Open trackers are disabled and we have no DHT peers. Fetch of {0} may not " -"succeed until you start another torrent, enable open trackers, or enable DHT." -msgstr "" -"OpenTracker被禁用,程序目前没有DHT节点。{0}的下载不会成功,直到您启动另一个种" -"子的下载、重新启用OpenTracker或DHT。" +"succeed until you start another torrent, enable open trackers, or enable " +"DHT." +msgstr "OpenTracker被禁用,程序目前没有DHT节点。{0}的下载不会成功,直到您启动另一个种子的下载、重新启用OpenTracker或DHT。" -#: ../java/src/org/klomp/snark/SnarkManager.java:1068 +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 #, java-format msgid "Adding {0}" msgstr "正在添加{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1100 +#: ../java/src/org/klomp/snark/SnarkManager.java:1442 #, java-format msgid "Download already running: {0}" msgstr "已经在下载中:{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1139 -#: ../java/src/org/klomp/snark/SnarkManager.java:1162 -#: ../java/src/org/klomp/snark/SnarkManager.java:1600 +#: ../java/src/org/klomp/snark/SnarkManager.java:1487 +#: ../java/src/org/klomp/snark/SnarkManager.java:1513 +#: ../java/src/org/klomp/snark/SnarkManager.java:2151 #, java-format msgid "Failed to copy torrent file to {0}" msgstr "无法复制种子文件到{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1389 +#: ../java/src/org/klomp/snark/SnarkManager.java:1927 #, java-format -msgid "Too many files in \"{0}\" ({1}), deleting it!" -msgstr "\"{0}\" ({1}) 含有太多文件,删除之!" +msgid "Too many files in \"{0}\" ({1})!" +msgstr "\"{0}\" ({1}) 含有太多文件!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1391 +#: ../java/src/org/klomp/snark/SnarkManager.java:1929 #, java-format -msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" -msgstr "种子文件 \"{0}\" 不以 \".torrent\"结尾,正在删除!" +msgid "Torrent file \"{0}\" cannot end in \".torrent\"!" +msgstr "种子文件 \"{0}\" 不以 \".torrent\"结尾!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1393 +#: ../java/src/org/klomp/snark/SnarkManager.java:1931 #, java-format -msgid "No pieces in \"{0}\", deleting it!" -msgstr "\"{0}\" 中没有数据片,删除之!" +msgid "No pieces in \"{0}\"!" +msgstr "\"{0}\" 中没有文件分片!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1395 +#: ../java/src/org/klomp/snark/SnarkManager.java:1933 #, java-format -msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" -msgstr "\"{0}\" 中文件分片太多,限额为{1},删除之!" +msgid "Too many pieces in \"{0}\", limit is {1}!" +msgstr "\"{0}\" 中文件分片太多,限额为{1}!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1397 +#: ../java/src/org/klomp/snark/SnarkManager.java:1935 #, java-format -msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." -msgstr "\"{0}\" ({1}B) 中文件分片过大,删除之。" +msgid "Pieces are too large in \"{0}\" ({1}B)!" +msgstr "\"{0}\"({1}B)中分片过大!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1398 +#: ../java/src/org/klomp/snark/SnarkManager.java:1936 #, java-format msgid "Limit is {0}B" msgstr "限额为 {0}B" -#: ../java/src/org/klomp/snark/SnarkManager.java:1400 +#: ../java/src/org/klomp/snark/SnarkManager.java:1938 #, java-format -msgid "Torrent \"{0}\" has no data, deleting it!" -msgstr "种子\"{0}\"中无数据,正在删除!" +msgid "Torrent \"{0}\" has no data!" +msgstr "种子 \"{0}\" 中无数据!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#: ../java/src/org/klomp/snark/SnarkManager.java:1946 #, java-format -msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" -msgstr "目前不支持大于{0}B 的种子,正在删除\"{1}\"" +msgid "Torrents larger than {0}B are not supported yet \"{1}\"!" +msgstr "目前不支持大于 {0}B 的种子 \"{1}\"!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1424 +#: ../java/src/org/klomp/snark/SnarkManager.java:1963 #, java-format msgid "Error: Could not remove the torrent {0}" msgstr "错误:无法删除种子{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1445 -#: ../java/src/org/klomp/snark/SnarkManager.java:1463 +#: ../java/src/org/klomp/snark/SnarkManager.java:1986 +#: ../java/src/org/klomp/snark/SnarkManager.java:2005 #, java-format -msgid "Torrent stopped: \"{0}\"" -msgstr "种子已停止:\"{0}\"" +msgid "Torrent stopped: {0}" +msgstr "种子已停止:{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1484 +#: ../java/src/org/klomp/snark/SnarkManager.java:2025 #, java-format msgid "Torrent removed: \"{0}\"" msgstr "种子已删除:\"{0}\"" -#: ../java/src/org/klomp/snark/SnarkManager.java:1492 +#: ../java/src/org/klomp/snark/SnarkManager.java:2033 #, java-format msgid "Adding torrents in {0}" msgstr "{0} 分钟内完成添加" -#: ../java/src/org/klomp/snark/SnarkManager.java:1523 +#: ../java/src/org/klomp/snark/SnarkManager.java:2067 #, java-format msgid "Up bandwidth limit is {0} KBps" -msgstr "最小上传带宽限制为 {0} KBps" +msgstr "上传带宽限制为 {0} KB/s" -#: ../java/src/org/klomp/snark/SnarkManager.java:1545 +#: ../java/src/org/klomp/snark/SnarkManager.java:2092 #, java-format msgid "Download finished: {0}" msgstr "下载已完成: {0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1596 +#: ../java/src/org/klomp/snark/SnarkManager.java:2147 #, java-format msgid "Metainfo received for {0}" msgstr "已获得 {0} 的 Metainfo" -#: ../java/src/org/klomp/snark/SnarkManager.java:1597 -#: ../java/src/org/klomp/snark/SnarkManager.java:1826 +#: ../java/src/org/klomp/snark/SnarkManager.java:2148 +#: ../java/src/org/klomp/snark/SnarkManager.java:2431 #, java-format msgid "Starting up torrent {0}" msgstr "正在启动种子{0}" -#: ../java/src/org/klomp/snark/SnarkManager.java:1612 +#: ../java/src/org/klomp/snark/SnarkManager.java:2163 #, java-format msgid "Error on torrent {0}" msgstr "种子 {0} 发生错误" -#: ../java/src/org/klomp/snark/SnarkManager.java:1675 +#: ../java/src/org/klomp/snark/SnarkManager.java:2264 msgid "Unable to connect to I2P!" msgstr "无法连接至I2P!" -#: ../java/src/org/klomp/snark/SnarkManager.java:1825 -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:124 +#: ../java/src/org/klomp/snark/SnarkManager.java:2430 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:130 msgid "Opening the I2P tunnel" msgstr "正在建立 I2P 隧道" -#: ../java/src/org/klomp/snark/SnarkManager.java:1849 +#: ../java/src/org/klomp/snark/SnarkManager.java:2450 msgid "Opening the I2P tunnel and starting all torrents." msgstr "正在打开I2P隧道并启动所有种子" -#: ../java/src/org/klomp/snark/SnarkManager.java:1912 +#: ../java/src/org/klomp/snark/SnarkManager.java:2513 msgid "Stopping all torrents and closing the I2P tunnel." msgstr "正在停用所有种子并关闭I2P隧道。" -#: ../java/src/org/klomp/snark/SnarkManager.java:1931 +#: ../java/src/org/klomp/snark/SnarkManager.java:2532 msgid "Closing I2P tunnel after notifying trackers." msgstr "正在关闭 I2P 隧道,已通知 Tracker。" -#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#: ../java/src/org/klomp/snark/SnarkManager.java:2594 +#, java-format +msgid "Finished recheck of torrent {0}, now {1} complete" +msgstr "已完成对种子 {0} 的重新检查,现在 {1} 已完成" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2596 +#, java-format +msgid "Finished recheck of torrent {0}, unchanged" +msgstr "已完成对种子 {0} 的重新检查,未变更" + +#: ../java/src/org/klomp/snark/SnarkManager.java:2600 +#, java-format +msgid "Error checking the torrent {0}" +msgstr "检查种子 {0} 时出错" + +#: ../java/src/org/klomp/snark/TrackerClient.java:245 #, java-format msgid "No valid trackers for {0} - enable opentrackers or DHT?" msgstr "{0} 中 Tracker 无效 - 要启用 opentrackers 或 DHT 吗?" #: ../java/src/org/klomp/snark/UpdateHandler.java:49 -#: ../java/src/org/klomp/snark/UpdateRunner.java:227 +#: ../java/src/org/klomp/snark/UpdateRunner.java:228 msgid "Updating" msgstr "正在更新" -#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#: ../java/src/org/klomp/snark/UpdateRunner.java:115 #, java-format msgid "Updating from {0}" msgstr "正在从 {0} 获取更新" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:75 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:80 #, java-format msgid "Download torrent file from {0}" msgstr "正在从 {0} 处下载种子文件" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:97 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:103 #, java-format msgid "Torrent was not retrieved from {0}" msgstr "从{0}获得种子失败" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:150 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:157 #, java-format msgid "Torrent fetched from {0}" msgstr "从{0}获取种子成功" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:171 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:178 #, java-format msgid "Torrent already running: {0}" msgstr "种子已启动:{0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:173 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:180 #, java-format msgid "Torrent already in the queue: {0}" msgstr "种子排队中:{0}" -#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:181 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:191 #, java-format msgid "Torrent at {0} was not valid" msgstr "{0}的种子中有错误" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:254 -msgid "I2PSnark - Anonymous BitTorrent Client" -msgstr "I2PSnark - 匿名BitTorrent客户端" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:267 -msgid "Router is down" -msgstr "路由器已关闭" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:284 -msgid "Torrents" -msgstr "种子" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:288 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2255 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:270 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:313 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1778 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2698 msgid "I2PSnark" msgstr "I2PSnark" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:294 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:275 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2165 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2446 +msgid "Configuration" +msgstr "设置" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:277 +msgid "Anonymous BitTorrent Client" +msgstr "匿名的 BitTorrent 客户端" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:291 +msgid "Router is down" +msgstr "路由器已关闭" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +msgid "Torrents" +msgstr "种子" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:319 msgid "Refresh page" msgstr "刷新页面" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:328 msgid "Forum" msgstr "论坛" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:315 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:343 msgid "Click \"Add torrent\" button to fetch torrent" msgstr "点击 \"添加种子\" 按钮来获取种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:352 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:396 msgid "clear messages" msgstr "清除消息" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:405 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:407 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2440 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:451 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3072 msgid "Status" msgstr "状态" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:418 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:420 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3086 +#, java-format +msgid "Sort by {0}" +msgstr "排序按 {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:464 msgid "Hide Peers" msgstr "隐藏用户" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:430 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:432 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:470 msgid "Show Peers" msgstr "显示用户" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:439 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:441 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2249 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2269 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2718 msgid "Torrent" msgstr "种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:495 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 +msgid "File type" +msgstr "文件类型" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:511 +msgid "ETA" +msgstr "预计剩余时间" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:513 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:514 msgid "Estimated time remaining" msgstr "预计剩余时间" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:452 -msgid "ETA" -msgstr "预计剩余时间" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:457 -msgid "Downloaded" -msgstr "已下载" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:460 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:537 msgid "RX" msgstr "已接收" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:465 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:540 +msgid "Downloaded" +msgstr "已下载" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2878 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3060 +msgid "Size" +msgstr "大小" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +msgid "TX" +msgstr "已发送" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2896 +msgid "Upload ratio" +msgstr "上传率" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:570 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:571 msgid "Uploaded" msgstr "已上传" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:468 -msgid "TX" -msgstr "已发送" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:583 +msgid "RX Rate" +msgstr "接收速度" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:474 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:585 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:586 msgid "Down Rate" msgstr "下载速度" #. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:477 -msgid "RX Rate" -msgstr "接收速度" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:483 -msgid "Up Rate" -msgstr "上传速度" - -#. Translators: Please keep short or translate as " " -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:598 msgid "TX Rate" msgstr "发送速度" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:501 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:600 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:601 +msgid "Up Rate" +msgstr "上传速度" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:617 msgid "Stop all torrents and the I2P tunnel" msgstr "停止全部种子及I2P隧道" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:503 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:619 msgid "Stop All" msgstr "停止全部" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:515 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:631 msgid "Start all stopped torrents" msgstr "启动所有已停止的种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:517 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:531 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:647 msgid "Start All" msgstr "启动全部" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:529 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:645 msgid "Start all torrents and the I2P tunnel" msgstr "启动全部种子及I2P隧道" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:670 msgid "No torrents loaded." msgstr "未载入任何种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:676 msgid "Totals" msgstr "总计" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:563 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:678 #, java-format msgid "1 torrent" msgid_plural "{0} torrents" msgstr[0] "{0}个种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:683 #, java-format msgid "1 connected peer" msgid_plural "{0} connected peers" msgstr[0] "{0}个已连接用户" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:690 #, java-format msgid "1 DHT peer" msgid_plural "{0} DHT peers" msgstr[0] "{0}个DHT节点" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:697 +msgid "Dest" +msgstr "目标" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First" msgstr "首页" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:611 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:825 msgid "First page" msgstr "第一页" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Prev" msgstr "前页" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:622 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 msgid "Previous page" msgstr "上一页" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next" msgstr "下页" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:657 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:868 msgid "Next page" msgstr "下一页" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last" msgstr "末页" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:667 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:876 msgid "Last page" msgstr "最后一页" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:750 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:962 +msgid "Data directory cannot be created" +msgstr "无法创建数据目录" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:972 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1185 +#, java-format +msgid "Cannot add torrent {0} inside another torrent: {1}" +msgstr "无法添加内含另一个种子的种子 {0}:{1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:993 #, java-format msgid "Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"" msgstr "无效链接 - 链接必须以“http://”,“{0}”或“{1}”开头" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:793 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:823 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 #, java-format msgid "Magnet deleted: {0}" msgstr "Magnet 已删除:{0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:801 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:829 -#, java-format -msgid "Torrent file deleted: {0}" -msgstr "种子文件已删除:{0}" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:821 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1061 #, java-format msgid "Download deleted: {0}" msgstr "下载已删除: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:835 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1078 #, java-format msgid "Data file deleted: {0}" msgstr "数据文件已删除:{0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:837 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:848 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 #, java-format msgid "Data file could not be deleted: {0}" msgstr "无法删除数据文件:{0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:872 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1105 #, java-format msgid "Directory could not be deleted: {0}" msgstr "无法删除目录:{0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:870 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1112 #, java-format msgid "Directory deleted: {0}" msgstr "目录已经删除: {0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:942 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1164 +#, java-format +msgid "Cannot add a torrent ending in \".torrent\": {0}" +msgstr "无法添加一个以 \".torrent\" 结尾的种子: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1169 +#, java-format +msgid "Torrent with this name is already running: {0}" +msgstr "此名称的种子已在运行:{0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1175 +#, java-format +msgid "Cannot add a torrent including an I2P directory: {0}" +msgstr "无法添加包含一个 I2P 目录的种子:{0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1190 +#, java-format +msgid "Cannot add torrent {0} including another torrent: {1}" +msgstr "无法添加包含另一个种子的种子 {0}:{1}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 msgid "Error - Cannot include alternate trackers without a primary tracker" msgstr "错误 - 缺少主Tracker则无法添加替换Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1229 msgid "Error - Cannot mix private and public trackers in a torrent" msgstr "错误 - PT和公共Tracker无法在同一种子中混用。" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1251 #, java-format msgid "Torrent created for \"{0}\"" msgstr "种子创建成功\"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:977 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1253 #, java-format msgid "" "Many I2P trackers require you to register new torrents before seeding - " "please do so before starting \"{0}\"" -msgstr "" -"多数I2PTracker需要用户在做种前注册新种子 - 请在启动 \"{0}\"前到所使用的" -"Tracker进行注册。" +msgstr "多数I2PTracker需要用户在做种前注册新种子 - 请在启动 \"{0}\"前到所使用的Tracker进行注册。" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:979 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1255 #, java-format msgid "Error creating a torrent for \"{0}\"" msgstr "创建种子时发生错误 \"{0}\"" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:983 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1259 #, java-format msgid "Cannot create a torrent for the nonexistent data: {0}" msgstr "无法为不存在的数据文件创建种子:{0}" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1262 msgid "Error creating torrent - you must enter a file or directory" msgstr "创建种子时发生错误 - 必须指定文件或文件夹" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2031 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 msgid "Delete selected" msgstr "删除选中项目" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1017 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2032 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2432 msgid "Save tracker configuration" msgstr "保存 Tracker 设置" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1034 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1310 msgid "Removed" msgstr "已删除" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1063 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2030 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2035 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1342 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2429 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2431 msgid "Add tracker" msgstr "添加 Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1086 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1089 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1365 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1368 msgid "Enter valid tracker name and URLs" msgstr "请输入有效的 Tracker 名称与链接" -#. "\n" + -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1091 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2034 +#. "\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1370 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 msgid "Restore defaults" msgstr "恢复默认值" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1094 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1373 msgid "Restored default trackers" msgstr "恢复默认 Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1215 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1216 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1486 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2949 msgid "Checking" msgstr "正在检查" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1218 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1219 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1489 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1490 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2956 msgid "Allocating" msgstr "正在分配空间" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1233 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1240 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 msgid "Tracker Error" msgstr "Tracker错误" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1263 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1268 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1279 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1284 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1290 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1542 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1553 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1558 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1564 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1569 #, java-format msgid "1 peer" msgid_plural "{0} peers" msgstr[0] "{0}个用户" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1244 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1517 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1518 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2954 msgid "Starting" msgstr "正在启动" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1252 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1526 msgid "Seeding" msgstr "正做种" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1256 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1270 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1271 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2382 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2496 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1544 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1545 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2891 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3139 msgid "Complete" msgstr "完成" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1275 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1276 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1281 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1282 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1549 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1555 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1556 msgid "OK" -msgstr "确定" +msgstr "正常" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1286 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1287 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1292 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1293 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1560 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1567 msgid "Stalled" msgstr "等待" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1297 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1298 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1301 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1302 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1571 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1572 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1576 msgid "No Peers" msgstr "没有用户" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1304 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1305 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1578 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1579 msgid "Stopped" msgstr "已停用" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1338 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1608 msgid "Torrent details" msgstr "种子详情" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1367 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1643 msgid "View files" msgstr "浏览文件" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1369 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1645 msgid "Open file" msgstr "打开文件" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 msgid "Stop the torrent" msgstr "停止种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2961 msgid "Stop" msgstr "停止" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1425 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1712 msgid "Start the torrent" msgstr "启动种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1427 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1714 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2963 msgid "Start" msgstr "启动" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1439 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1727 msgid "Remove the torrent from the active list, deleting the .torrent file" msgstr "取消下载任务并删除对应种子文件。" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1444 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1732 #, java-format msgid "" "Are you sure you want to delete the file \\''{0}\\'' (downloaded data will " "not be deleted) ?" msgstr "你确定你要删除文件 \\“{0} \\” (下载的数据不会被删除)?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1447 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1736 msgid "Remove" msgstr "移除" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1459 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1749 msgid "Delete the .torrent file and the associated data file(s)" msgstr "删除种子及所下载的文件" #. Can't figure out how to escape double quotes inside the onclick string. #. Single quotes in translate strings with parameters must be doubled. #. Then the remaining single quote must be escaped -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1464 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1754 #, java-format msgid "" "Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded " "data?" msgstr "您确定要删除种子“{0}”(下载的数据文件会一并被删除)?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1467 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1997 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1758 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2388 msgid "Delete" msgstr "删除" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1502 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1794 msgid "Unknown" msgstr "未知" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1514 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1806 msgid "Seed" msgstr "种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1537 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1829 msgid "Uninteresting (The peer has no pieces we need)" msgstr "无需要部分" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1539 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1831 msgid "Choked (The peer is not allowing us to request pieces)" msgstr "拒绝请求" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1559 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 msgid "Uninterested (We have no pieces the peer needs)" msgstr "无需要部分" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 msgid "Choking (We are not allowing the peer to request pieces)" msgstr "拒绝请求" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1616 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1969 #, java-format msgid "Details at {0} tracker" msgstr "Tracker {0} 上的详细信息" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1633 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 msgid "Info" msgstr "信息" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1684 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2059 msgid "Add Torrent" msgstr "添加种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1686 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 msgid "From URL" msgstr "从URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1689 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2065 msgid "" -"Enter the torrent file download URL (I2P only), magnet link, maggot link, or " -"info hash" -msgstr "" -"输入种子文件的下载链接(仅支持I2P内网链接),magnet, maggot 链接或信息散列值" +"Enter the torrent file download URL (I2P only), magnet link, maggot link, or" +" info hash" +msgstr "输入种子文件的下载链接(仅支持I2P内网链接),magnet, maggot 链接或信息散列值" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1694 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 msgid "Add torrent" msgstr "添加种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1697 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2074 +msgid "Data dir" +msgstr "数据目录" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2077 +#, java-format +msgid "Enter the directory to save the data in (default {0})" +msgstr "请输入保存数据的目录(默认 {0})" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2081 #, java-format msgid "You can also copy .torrent files to: {0}." msgstr "您也可以将.torrent文件复制到: {0}." -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1699 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2083 msgid "Removing a .torrent will cause it to stop." -msgstr "删除种子文件将导致该下载任务中止。" +msgstr "移除一个种子文件 (.torrent) 将导致它中止。" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2096 msgid "Create Torrent" msgstr "创建种子" -#. out.write("From file:
\n"); -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1725 +#. out.write("From file:
\n"); +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2099 msgid "Data to seed" msgstr "做种数据" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 -msgid "File or directory to seed (must be within the specified path)" -msgstr "做种文件或文件夹(必须下面为Snark指定的文件夹中)" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2103 +#, java-format +msgid "File or directory to seed (full path or within the directory {0} )" +msgstr "要做种的文件或目录(完整路径或包含在 {0} 目录中)" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1731 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2106 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2361 msgid "Trackers" msgstr "Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1733 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2108 msgid "Primary" msgstr "主 Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1735 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2110 msgid "Alternates" msgstr "备选 Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1738 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2113 msgid "Create torrent" msgstr "创建种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1756 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2131 msgid "none" msgstr "无" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1789 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2046 -msgid "Configuration" -msgstr "设置" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1793 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2169 msgid "Data directory" msgstr "数据文件夹" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1797 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2174 msgid "Files readable by all" msgstr "文件对所有人可读" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1801 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2178 msgid "If checked, other users may access the downloaded files" msgstr "选中后,其他用户可以访问您下载的文件。" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1805 -msgid "Auto start" -msgstr "自动启动" +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2182 +msgid "Auto start torrents" +msgstr "自动开始种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1809 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2186 msgid "If checked, automatically start torrents that are added" msgstr "选中后Snark将自动启动已添加的所有种子。" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1813 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2190 +msgid "Smart torrent sorting" +msgstr "智能种子排序" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2194 +msgid "If checked, ignore words such as 'the' when sorting" +msgstr "如果选中,排序时忽略诸如 'the' 的单词" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2198 msgid "Theme" msgstr "主题" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1826 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2212 msgid "Refresh time" msgstr "刷新时间" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1839 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2225 msgid "Never" msgstr "从不" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1845 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2231 msgid "Startup delay" msgstr "启动延迟" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1847 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2233 msgid "minutes" msgstr "分" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1851 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2237 msgid "Page size" msgstr "页面容量" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1853 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2239 msgid "torrents" msgstr "种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1877 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2263 msgid "Total uploader limit" msgstr "限制总上传种子数为" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2266 msgid "peers" msgstr "用户" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2270 msgid "Up bandwidth limit" msgstr "上传带宽限制" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1887 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2273 msgid "Half available bandwidth recommended." msgstr "推荐设置为可用带宽的一半。" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1889 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2275 msgid "View or change router bandwidth" msgstr "浏览或修改路由器带宽" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1893 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2279 msgid "Use open trackers also" msgstr "同时使用OpenTracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1897 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2283 msgid "" -"If checked, announce torrents to open trackers as well as the tracker listed " -"in the torrent file" +"If checked, announce torrents to open trackers as well as the tracker listed" +" in the torrent file" msgstr "选择后在OpenTracker及种子文件中的Tracker上同时发布。" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1901 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 msgid "Enable DHT" msgstr "启用 DHT" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1905 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 msgid "If checked, use DHT" msgstr "如果选中,则使用 DHT。" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1921 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2307 msgid "Inbound Settings" msgstr "入站设置" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1927 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2313 msgid "Outbound Settings" msgstr "出站设置" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1935 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2321 msgid "I2CP host" msgstr "I2CP主机" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1940 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2326 msgid "I2CP port" msgstr "I2CP端口" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1955 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2341 msgid "I2CP options" msgstr "I2CP选项" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1960 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2346 msgid "Save configuration" msgstr "保存设置" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1980 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2366 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3045 msgid "Name" msgstr "名称" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1982 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2368 msgid "Website URL" msgstr "网站 URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1984 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2530 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 +msgid "Standard" +msgstr "标准" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2372 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3172 msgid "Open" msgstr "打开" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1986 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 msgid "Private" msgstr "私有" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2376 msgid "Announce URL" msgstr "发布 URL" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2022 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2420 msgid "Add" msgstr "添加" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2062 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2463 #, java-format msgid "Invalid magnet URL {0}" msgstr "磁性链接 {0} 无效" #. * dummies for translation -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2070 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2471 #, java-format msgid "1 hop" msgid_plural "{0} hops" msgstr[0] "{0}跳" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2071 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 #, java-format msgid "1 tunnel" msgid_plural "{0} tunnels" msgstr[0] "{0}隧道" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2728 msgid "Torrent file" msgstr "Torrent文件" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2291 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2736 +msgid "Data location" +msgstr "数据位置" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2745 +msgid "Info hash" +msgstr "信息哈希" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2764 msgid "Primary Tracker" msgstr "主 Tracker" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2300 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2773 msgid "Tracker List" msgstr "Tracker 列表" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2324 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2798 msgid "Comment" msgstr "评论" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2333 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2812 msgid "Created" msgstr "已创建" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2343 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2823 msgid "Created By" msgstr "创建者" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2353 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2833 +msgid "Added" +msgstr "已添加" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2842 +msgid "Completed" +msgstr "已完成" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2854 msgid "Magnet link" msgstr "Magnet磁性链接" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2360 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2867 msgid "Private torrent" msgstr "私有种子" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2370 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 -msgid "Size" -msgstr "大小" - -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2377 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2887 msgid "Completion" msgstr "完成" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2387 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2916 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3074 msgid "Remaining" msgstr "剩余" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2394 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2926 msgid "Files" msgstr "文件" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2399 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2933 msgid "Pieces" msgstr "分块数量" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2403 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2939 msgid "Piece size" msgstr "分块大小" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2426 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2430 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2952 +msgid "Refresh page for results" +msgstr "刷新页面获取结果" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2964 +msgid "Force Recheck" +msgstr "强制重新检查" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3025 msgid "Directory" msgstr "文件夹" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2447 -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2449 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3084 msgid "Priority" msgstr "优先级" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2455 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3096 msgid "Up to higher level directory" msgstr "上一层文件夹" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2485 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3130 msgid "Torrent not found?" msgstr "种子未找到" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3136 msgid "File not found in torrent?" msgstr "种子中没有发现文件?" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2506 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3149 msgid "complete" msgstr "完成" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2507 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3150 msgid "remaining" msgstr "剩余" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2556 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3196 msgid "High" msgstr "高" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2561 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3201 msgid "Normal" msgstr "普通" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2566 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3206 msgid "Skip" msgstr "跳过" -#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2575 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3216 +msgid "Set all high" +msgstr "设置所有为高" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3218 +msgid "Set all normal" +msgstr "设置所有为正常" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3220 +msgid "Skip all" +msgstr "忽略所有" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:3221 msgid "Save priorities" msgstr "保存优先级" diff --git a/apps/i2psnark/mime.properties b/apps/i2psnark/mime.properties index 927155d9a..8c884cfed 100644 --- a/apps/i2psnark/mime.properties +++ b/apps/i2psnark/mime.properties @@ -3,13 +3,16 @@ 7z = application/x-7z-compressed ape = audio/x-monkeys-audio bz2 = application/x-bzip2 +cue = application/x-cue dmg = application/apple-diskimage epub = application/epub+zip flac = audio/flac flv = video/x-flv iso = application/x-iso9660-image m4a = audio/mp4a-latm +m4b = audio/mp4a-latm m4v = video/x-m4v +mka = audio/x-matroska mkv = video/x-matroska mobi = application/x-mobipocket-ebook mp4 = video/mp4 @@ -24,8 +27,10 @@ su2 = application/zip su3 = application/zip sud = application/zip tbz = application/x-bzip2 +torrent = application/x-bittorrent txt = text/plain war = application/java-archive webm = video/webm wma = audio/x-ms-wma wmv = video/x-ms-wmv +xz = application/x-xz diff --git a/apps/i2psnark/readme.txt.snark b/apps/i2psnark/readme-snark.txt similarity index 100% rename from apps/i2psnark/readme.txt.snark rename to apps/i2psnark/readme-snark.txt diff --git a/apps/i2psnark/readme-standalone.txt b/apps/i2psnark/readme-standalone.txt index 9bc1ddf66..ced04e941 100644 --- a/apps/i2psnark/readme-standalone.txt +++ b/apps/i2psnark/readme-standalone.txt @@ -1,6 +1,4 @@ -To run I2PSnark from the command line, run "java -jar lib/i2psnark.jar", but -to run it with the web UI, run "launch-i2psnark". I2PSnark is -GPL'ed software, based on Snark (http://www.klomp.org/) to run on top of I2P -(http://www.i2p2.de/) within a webserver (such as the bundled Jetty from -http://jetty.mortbay.org/). For more information about I2PSnark, get in touch -with the folks at http://forum.i2p2.de/ +i2psnark is packaged as a webapp running in the router console. +Command line and standalone operation of i2psnark are not currently supported. +See http://trac.i2p2.i2p/ticket/1191 or http://trac.i2p2.de/ticket/1191 +for the status of restoring standalone support. diff --git a/apps/i2psnark/readme.txt b/apps/i2psnark/readme.txt index 3970e3cba..2680442fa 100644 --- a/apps/i2psnark/readme.txt +++ b/apps/i2psnark/readme.txt @@ -1,11 +1,9 @@ -This is an I2P port of snark [http://klomp.org/snark], a GPL'ed bittorrent client +This is i2psnark, an I2P port of snark http://klomp.org/snark/ , a GPLv2 bittorrent client. +It contains significant enhancements including a web UI and support for +multitorrent, magnet, PEX and DHT. -The build in tracker has been removed for simplicity. +i2psnark is packaged as a webapp running in the router console. -Example usage: - java -jar lib/i2psnark.jar myFile.torrent - -or, a more verbose setting: - java -jar lib/i2psnark.jar --eepproxy 127.0.0.1 4444 \ - --i2cp 127.0.0.1 7654 "inbound.length=2 outbound.length=2" \ - --debug 6 myFile.torrent +See http://i2p-projekt.i2p/en/docs/applications/bittorrent +or https://geti2p.net/en/docs/applications/bittorrent +for the specification of the protocols for bittorrent over I2P. diff --git a/apps/i2psnark/icons/application.png b/apps/i2psnark/resources/icons/application.png similarity index 100% rename from apps/i2psnark/icons/application.png rename to apps/i2psnark/resources/icons/application.png diff --git a/apps/i2psnark/icons/basket_put.png b/apps/i2psnark/resources/icons/basket_put.png similarity index 100% rename from apps/i2psnark/icons/basket_put.png rename to apps/i2psnark/resources/icons/basket_put.png diff --git a/apps/i2psnark/icons/cancel.png b/apps/i2psnark/resources/icons/cancel.png similarity index 100% rename from apps/i2psnark/icons/cancel.png rename to apps/i2psnark/resources/icons/cancel.png diff --git a/apps/i2psnark/icons/cd.png b/apps/i2psnark/resources/icons/cd.png similarity index 100% rename from apps/i2psnark/icons/cd.png rename to apps/i2psnark/resources/icons/cd.png diff --git a/apps/i2psnark/icons/clock.png b/apps/i2psnark/resources/icons/clock.png similarity index 100% rename from apps/i2psnark/icons/clock.png rename to apps/i2psnark/resources/icons/clock.png diff --git a/apps/i2psnark/icons/clock_red.png b/apps/i2psnark/resources/icons/clock_red.png similarity index 100% rename from apps/i2psnark/icons/clock_red.png rename to apps/i2psnark/resources/icons/clock_red.png diff --git a/apps/i2psnark/icons/compress.png b/apps/i2psnark/resources/icons/compress.png similarity index 100% rename from apps/i2psnark/icons/compress.png rename to apps/i2psnark/resources/icons/compress.png diff --git a/apps/i2psnark/icons/film.png b/apps/i2psnark/resources/icons/film.png similarity index 100% rename from apps/i2psnark/icons/film.png rename to apps/i2psnark/resources/icons/film.png diff --git a/apps/i2psnark/icons/folder.png b/apps/i2psnark/resources/icons/folder.png similarity index 100% rename from apps/i2psnark/icons/folder.png rename to apps/i2psnark/resources/icons/folder.png diff --git a/apps/i2psnark/icons/html.png b/apps/i2psnark/resources/icons/html.png similarity index 100% rename from apps/i2psnark/icons/html.png rename to apps/i2psnark/resources/icons/html.png diff --git a/apps/i2psnark/resources/icons/itoopie_xxsm.png b/apps/i2psnark/resources/icons/itoopie_xxsm.png new file mode 100644 index 000000000..0cec9e5c9 Binary files /dev/null and b/apps/i2psnark/resources/icons/itoopie_xxsm.png differ diff --git a/apps/i2psnark/icons/magnet.png b/apps/i2psnark/resources/icons/magnet.png similarity index 100% rename from apps/i2psnark/icons/magnet.png rename to apps/i2psnark/resources/icons/magnet.png diff --git a/apps/i2psnark/icons/music.png b/apps/i2psnark/resources/icons/music.png similarity index 100% rename from apps/i2psnark/icons/music.png rename to apps/i2psnark/resources/icons/music.png diff --git a/apps/i2psnark/icons/package.png b/apps/i2psnark/resources/icons/package.png similarity index 100% rename from apps/i2psnark/icons/package.png rename to apps/i2psnark/resources/icons/package.png diff --git a/apps/i2psnark/icons/page.png b/apps/i2psnark/resources/icons/page.png similarity index 100% rename from apps/i2psnark/icons/page.png rename to apps/i2psnark/resources/icons/page.png diff --git a/apps/i2psnark/icons/page_white.png b/apps/i2psnark/resources/icons/page_white.png similarity index 100% rename from apps/i2psnark/icons/page_white.png rename to apps/i2psnark/resources/icons/page_white.png diff --git a/apps/i2psnark/icons/page_white_acrobat.png b/apps/i2psnark/resources/icons/page_white_acrobat.png similarity index 100% rename from apps/i2psnark/icons/page_white_acrobat.png rename to apps/i2psnark/resources/icons/page_white_acrobat.png diff --git a/apps/i2psnark/icons/photo.png b/apps/i2psnark/resources/icons/photo.png similarity index 100% rename from apps/i2psnark/icons/photo.png rename to apps/i2psnark/resources/icons/photo.png diff --git a/apps/i2psnark/icons/plugin.png b/apps/i2psnark/resources/icons/plugin.png similarity index 100% rename from apps/i2psnark/icons/plugin.png rename to apps/i2psnark/resources/icons/plugin.png diff --git a/apps/i2psnark/icons/tick.png b/apps/i2psnark/resources/icons/tick.png similarity index 100% rename from apps/i2psnark/icons/tick.png rename to apps/i2psnark/resources/icons/tick.png diff --git a/apps/i2psnark/resources/js/folder.js b/apps/i2psnark/resources/js/folder.js new file mode 100644 index 000000000..fbc906bf9 --- /dev/null +++ b/apps/i2psnark/resources/js/folder.js @@ -0,0 +1,93 @@ +function setupbuttons() { + updatesetallbuttons(); + var form = document.forms[0]; + form.savepri.disabled = true; + form.savepri.className = 'disabled'; +} + +function priorityclicked() { + updatesetallbuttons(); + var form = document.forms[0]; + form.savepri.disabled = false; + form.savepri.className = 'accept'; +} + +function updatesetallbuttons() { + var notNorm = false; + var notHigh = false; + var notSkip = false; + var form = document.forms[0]; + for(i = 0; i < form.elements.length; i++) { + var elem = form.elements[i]; + if (elem.type == 'radio') { + if (!elem.checked) { + if (elem.className == 'prinorm') + notNorm = true; + else if (elem.className == 'prihigh') + notHigh = true; + else + notSkip = true; + } + } + } + if (notNorm) + document.getElementById('setallnorm').className = 'control'; + else + document.getElementById('setallnorm').className = 'controld'; + if (notHigh) + document.getElementById('setallhigh').className = 'control'; + else + document.getElementById('setallhigh').className = 'controld'; + if (notSkip) + document.getElementById('setallskip').className = 'control'; + else + document.getElementById('setallskip').className = 'controld'; +} + +function setallnorm() { + var form = document.forms[0]; + for(i = 0; i < form.elements.length; i++) { + var elem = form.elements[i]; + if (elem.type == 'radio') { + if (elem.className === 'prinorm') + elem.checked = true; + } + } + document.getElementById('setallnorm').className = 'controld'; + document.getElementById('setallhigh').className = 'control'; + document.getElementById('setallskip').className = 'control'; + form.savepri.disabled = false; + form.savepri.className = 'accept'; +} + +function setallhigh() { + var form = document.forms[0]; + for(i = 0; i < form.elements.length; i++) { + var elem = form.elements[i]; + if (elem.type == 'radio') { + if (elem.className === 'prihigh') + elem.checked = true; + } + } + document.getElementById('setallnorm').className = 'control'; + document.getElementById('setallhigh').className = 'controld'; + document.getElementById('setallskip').className = 'control'; + form.savepri.disabled = false; + form.savepri.className = 'accept'; +} + +function setallskip() { + var form = document.forms[0]; + for(i = 0; i < form.elements.length; i++) { + var elem = form.elements[i]; + if (elem.type == 'radio') { + if (elem.className === 'priskip') + elem.checked = true; + } + } + document.getElementById('setallnorm').className = 'control'; + document.getElementById('setallhigh').className = 'control'; + document.getElementById('setallskip').className = 'controld'; + form.savepri.disabled = false; + form.savepri.className = 'accept'; +} diff --git a/apps/i2psnark/web.xml b/apps/i2psnark/web.xml index 2925ff00e..d98f63733 100644 --- a/apps/i2psnark/web.xml +++ b/apps/i2psnark/web.xml @@ -4,6 +4,15 @@ "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"> + + XSSFilter + net.i2p.servlet.filters.XSSFilter + + + XSSFilter + /* + + org.klomp.snark.web.I2PSnarkServlet org.klomp.snark.web.I2PSnarkServlet @@ -17,73 +26,14 @@ / + 30 + + true + - - - - - mkv - video/x-matroska - - - - wmv - video/x-ms-wmv - - - - flv - video/x-flv - - - - mp4 - video/mp4 - - - - rar - application/rar - - - - 7z - application/x-7z-compressed - - - - iso - application/x-iso9660-image - - - - ico - image/x-icon - - - - exe - application/x-msdos-program - - - - flac - audio/flac - - - - m4a - audio/mpeg - - - - wma - audio/x-ms-wma - - diff --git a/apps/i2ptunnel/java/build.xml b/apps/i2ptunnel/java/build.xml index c7bd9af95..b4be255cc 100644 --- a/apps/i2ptunnel/java/build.xml +++ b/apps/i2ptunnel/java/build.xml @@ -62,7 +62,7 @@ - + @@ -73,7 +73,7 @@ - + @@ -90,6 +90,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $TMPFILE xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\ - --keyword=_ \ + --keyword=_t \ -o ${i}t if [ $? -ne 0 ] then diff --git a/apps/i2ptunnel/java/bundle-messages.sh b/apps/i2ptunnel/java/bundle-messages.sh index 9d38feebb..0b426cb4d 100755 --- a/apps/i2ptunnel/java/bundle-messages.sh +++ b/apps/i2ptunnel/java/bundle-messages.sh @@ -24,12 +24,12 @@ then fi # on windows, one must specify the path of commnad find -# since windows has its own retarded version of find. +# since windows has its own version of find. if which find|grep -q -i windows ; then export PATH=.:/bin:/usr/local/bin:$PATH fi # Fast mode - update ondemond -# set LG2 to the language you need in envrionment varibales to enable this +# set LG2 to the language you need in environment variables to enable this # add ../java/ so the refs will work in the po file JPATHS="../java/src/net/i2p/i2ptunnel/web ../jsp/WEB-INF" @@ -61,16 +61,16 @@ do echo "Updating the $i file from the tags..." # extract strings from java and jsp files, and update messages.po files # translate calls must be one of the forms: - # _("foo") + # _t("foo") # _x("foo") - # intl._("foo") + # intl._t("foo") # intl.title("foo") # In a jsp, you must use a helper or handler that has the context set. # To start a new translation, copy the header from an old translation to the new .po file, # then ant distclean updater. find $JPATHS -name *.java > $TMPFILE xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\ - --keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \ + --keyword=_t --keyword=_x --keyword=intl._ --keyword=intl.title \ -o ${i}t if [ $? -ne 0 ] then diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ConnThrottler.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ConnThrottler.java index c802a9995..26c46e431 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ConnThrottler.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ConnThrottler.java @@ -7,14 +7,13 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.TimeZone; -import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.util.Clock; import net.i2p.util.Log; import net.i2p.util.SimpleTimer2; +import net.i2p.util.SystemVersion; /** * Count how often something happens with a particular peer and all peers. @@ -57,9 +56,7 @@ class ConnThrottler { _log = log; // for logging _fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM); - String systemTimeZone = I2PAppContext.getGlobalContext().getProperty("i2p.systemTimeZone"); - if (systemTimeZone != null) - _fmt.setTimeZone(TimeZone.getTimeZone(systemTimeZone)); + _fmt.setTimeZone(SystemVersion.getSystemTimeZone()); new Cleaner(); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/GunzipOutputStream.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/GunzipOutputStream.java new file mode 100644 index 000000000..6f5a4c3a7 --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/GunzipOutputStream.java @@ -0,0 +1,372 @@ +package net.i2p.i2ptunnel; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.CRC32; +import java.util.zip.Inflater; +import java.util.zip.InflaterOutputStream; + +import net.i2p.data.DataHelper; + +/** + * Gunzip implementation per + * RFC 1952, reusing + * java's standard CRC32 and Inflater and InflaterOutputStream implementations. + * + * Note that the underlying InflaterOutputStream cannot be reused after close(), + * so we don't have a Reusable version of this. + * + * Modified from net.i2p.util.ResettableGZIPInputStream to use Java 6 InflaterOutputstream + * @since 0.9.21 + */ +class GunzipOutputStream extends InflaterOutputStream { + private static final int FOOTER_SIZE = 8; // CRC32 + ISIZE + private final CRC32 _crc32; + private final byte _buf1[] = new byte[1]; + private boolean _complete; + private final byte _footer[] = new byte[FOOTER_SIZE]; + private long _bytesReceived; + private long _bytesReceivedAtCompletion; + + private enum HeaderState { MB1, MB2, CF, MT0, MT1, MT2, MT3, EF, OS, FLAGS, + EH1, EH2, EHDATA, NAME, COMMENT, CRC1, CRC2, DONE } + private HeaderState _state = HeaderState.MB1; + private int _flags; + private int _extHdrToRead; + + /** + * Build a new Gunzip stream + */ + public GunzipOutputStream(OutputStream uncompressedStream) throws IOException { + super(uncompressedStream, new Inflater(true)); + _crc32 = new CRC32(); + } + + @Override + public void write(int b) throws IOException { + _buf1[0] = (byte) b; + write(_buf1, 0, 1); + } + + @Override + public void write(byte buf[]) throws IOException { + write(buf, 0, buf.length); + } + + @Override + public void write(byte buf[], int off, int len) throws IOException { + if (_complete) { + // shortcircuit so the inflater doesn't try to refill + // with the footer's data (which would fail, causing ZLIB err) + return; + } + boolean isFinished = inf.finished(); + for (int i = off; i < off + len; i++) { + if (!isFinished) { + if (_state != HeaderState.DONE) { + verifyHeader(buf[i]); + continue; + } + // ensure we call the same method variant so we don't depend on underlying implementation + super.write(buf, i, 1); + if (inf.finished()) { + isFinished = true; + _bytesReceivedAtCompletion = _bytesReceived; + } + } + _footer[(int) (_bytesReceived++ % FOOTER_SIZE)] = buf[i]; + if (isFinished) { + long footerSize = _bytesReceivedAtCompletion - _bytesReceived; + // could be at 7 or 8... + // we write the first byte of the footer to the Inflater if necessary... + // see comments in ResettableGZIPInputStream for details + if (footerSize >= FOOTER_SIZE - 1) { + try { + verifyFooter(); + inf.reset(); // so it doesn't bitch about missing data... + _complete = true; + return; + } catch (IOException ioe) { + // failed at 7, retry at 8 + if (footerSize == FOOTER_SIZE - 1 && i < off + len - 1) + continue; + _complete = true; + throw ioe; + } + } + } + } + } + + /** + * Inflater statistic + */ + public long getTotalRead() { + try { + return inf.getBytesRead(); + } catch (RuntimeException e) { + return 0; + } + } + + /** + * Inflater statistic + */ + public long getTotalExpanded() { + try { + return inf.getBytesWritten(); + } catch (RuntimeException e) { + // possible NPE in some implementations + return 0; + } + } + + /** + * Inflater statistic + */ + public long getRemaining() { + try { + return inf.getRemaining(); + } catch (RuntimeException e) { + // possible NPE in some implementations + return 0; + } + } + + /** + * Inflater statistic + */ + public boolean getFinished() { + try { + return inf.finished(); + } catch (RuntimeException e) { + // possible NPE in some implementations + return true; + } + } + + @Override + public void close() throws IOException { + _complete = true; + _state = HeaderState.DONE; + super.close(); + } + + @Override + public String toString() { + return "GOS read: " + getTotalRead() + " expanded: " + getTotalExpanded() + " remaining: " + getRemaining() + " finished: " + getFinished(); + } + + /** + * @throws IOException on CRC or length check fail + */ + private void verifyFooter() throws IOException { + int idx = (int) (_bytesReceivedAtCompletion % FOOTER_SIZE); + byte[] footer; + if (idx == 0) { + footer = _footer; + } else { + footer = new byte[FOOTER_SIZE]; + for (int i = 0; i < FOOTER_SIZE; i++) { + footer[i] = _footer[(int) ((_bytesReceivedAtCompletion + i) % FOOTER_SIZE)]; + } + } + + long actualSize = inf.getTotalOut(); + long expectedSize = DataHelper.fromLongLE(footer, 4, 4); + if (expectedSize != actualSize) + throw new IOException("gunzip expected " + expectedSize + " bytes, got " + actualSize); + + long actualCRC = _crc32.getValue(); + long expectedCRC = DataHelper.fromLongLE(footer, 0, 4); + if (expectedCRC != actualCRC) + throw new IOException("gunzip CRC fail expected 0x" + Long.toHexString(expectedCRC) + + " bytes, got 0x" + Long.toHexString(actualCRC)); + } + + /** + * Make sure the header is valid, throwing an IOException if it is bad. + * Pushes through the state machine, checking as we go. + * Call for each byte until HeaderState is DONE. + */ + private void verifyHeader(byte b) throws IOException { + int c = b & 0xff; + switch (_state) { + case MB1: + if (c != 0x1F) throw new IOException("First magic byte was wrong [" + c + "]"); + _state = HeaderState.MB2; + break; + + case MB2: + if (c != 0x8B) throw new IOException("Second magic byte was wrong [" + c + "]"); + _state = HeaderState.CF; + break; + + case CF: + if (c != 0x08) throw new IOException("Compression format is invalid [" + c + "]"); + _state = HeaderState.FLAGS; + break; + + case FLAGS: + _flags = c; + _state = HeaderState.MT0; + break; + + case MT0: + // ignore + _state = HeaderState.MT1; + break; + + case MT1: + // ignore + _state = HeaderState.MT2; + break; + + case MT2: + // ignore + _state = HeaderState.MT3; + break; + + case MT3: + // ignore + _state = HeaderState.EF; + break; + + case EF: + if ( (c != 0x00) && (c != 0x02) && (c != 0x04) ) + throw new IOException("Invalid extended flags [" + c + "]"); + _state = HeaderState.OS; + break; + + case OS: + // ignore + if (0 != (_flags & (1<<5))) + _state = HeaderState.EH1; + else if (0 != (_flags & (1<<4))) + _state = HeaderState.NAME; + else if (0 != (_flags & (1<<3))) + _state = HeaderState.COMMENT; + else if (0 != (_flags & (1<<6))) + _state = HeaderState.CRC1; + else + _state = HeaderState.DONE; + break; + + case EH1: + _extHdrToRead = c; + _state = HeaderState.EH2; + break; + + case EH2: + _extHdrToRead += (c << 8); + if (_extHdrToRead > 0) + _state = HeaderState.EHDATA; + else if (0 != (_flags & (1<<4))) + _state = HeaderState.NAME; + if (0 != (_flags & (1<<3))) + _state = HeaderState.COMMENT; + else if (0 != (_flags & (1<<6))) + _state = HeaderState.CRC1; + else + _state = HeaderState.DONE; + break; + + case EHDATA: + // ignore + if (--_extHdrToRead <= 0) { + if (0 != (_flags & (1<<4))) + _state = HeaderState.NAME; + if (0 != (_flags & (1<<3))) + _state = HeaderState.COMMENT; + else if (0 != (_flags & (1<<6))) + _state = HeaderState.CRC1; + else + _state = HeaderState.DONE; + } + break; + + case NAME: + // ignore + if (c == 0) { + if (0 != (_flags & (1<<3))) + _state = HeaderState.COMMENT; + else if (0 != (_flags & (1<<6))) + _state = HeaderState.CRC1; + else + _state = HeaderState.DONE; + } + break; + + case COMMENT: + // ignore + if (c == 0) { + if (0 != (_flags & (1<<6))) + _state = HeaderState.CRC1; + else + _state = HeaderState.DONE; + } + break; + + case CRC1: + // ignore + _state = HeaderState.CRC2; + break; + + case CRC2: + // ignore + _state = HeaderState.DONE; + break; + + case DONE: + default: + break; + } + } + +/**** + public static void main(String args[]) { + java.util.Random r = new java.util.Random(); + for (int i = 0; i < 1050; i++) { + byte[] b = new byte[i]; + r.nextBytes(b); + if (!test(b)) return; + } + for (int i = 1; i < 64*1024; i+= 29) { + byte[] b = new byte[i]; + r.nextBytes(b); + if (!test(b)) return; + } + } + + private static boolean test(byte[] b) { + int size = b.length; + try { + java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(size); + java.util.zip.GZIPOutputStream o = new java.util.zip.GZIPOutputStream(baos); + o.write(b); + o.finish(); + o.flush(); + byte compressed[] = baos.toByteArray(); + + java.io.ByteArrayOutputStream baos2 = new java.io.ByteArrayOutputStream(size); + GunzipOutputStream out = new GunzipOutputStream(baos2); + out.write(compressed); + byte rv[] = baos2.toByteArray(); + if (rv.length != b.length) + throw new RuntimeException("read length: " + rv.length + " expected: " + b.length); + + if (!net.i2p.data.DataHelper.eq(rv, 0, b, 0, b.length)) { + throw new RuntimeException("foo, read=" + rv.length); + } else { + System.out.println("match, w00t @ " + size); + return true; + } + } catch (Exception e) { + System.out.println("Error dealing with size=" + size + ": " + e.getMessage()); + e.printStackTrace(); + return false; + } + } +****/ +} diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/HTTPResponseOutputStream.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/HTTPResponseOutputStream.java index 244e76c6e..2fc344a71 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/HTTPResponseOutputStream.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/HTTPResponseOutputStream.java @@ -10,19 +10,14 @@ package net.i2p.i2ptunnel; import java.io.FilterOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; import java.util.Locale; -import java.util.concurrent.RejectedExecutionException; import net.i2p.I2PAppContext; import net.i2p.data.ByteArray; -import net.i2p.util.BigPipedInputStream; +import net.i2p.data.DataHelper; import net.i2p.util.ByteCache; import net.i2p.util.Log; -import net.i2p.util.ReusableGZIPInputStream; /** * This does the transparent gzip decompression on the client side. @@ -44,7 +39,10 @@ class HTTPResponseOutputStream extends FilterOutputStream { private final byte _buf1[]; protected boolean _gzip; protected long _dataExpected; + /** lower-case, trimmed */ protected String _contentType; + /** lower-case, trimmed */ + protected String _contentEncoding; private static final int CACHE_SIZE = 8*1024; private static final ByteCache _cache = ByteCache.getInstance(8, CACHE_SIZE); @@ -151,10 +149,12 @@ class HTTPResponseOutputStream extends FilterOutputStream { for (int i = 0; i < _headerBuffer.getValid(); i++) { if (isNL(_headerBuffer.getData()[i])) { if (lastEnd == -1) { - responseLine = new String(_headerBuffer.getData(), 0, i+1); // includes NL + responseLine = DataHelper.getUTF8(_headerBuffer.getData(), 0, i+1); // includes NL responseLine = filterResponseLine(responseLine); responseLine = (responseLine.trim() + "\r\n"); - out.write(responseLine.getBytes()); + if (_log.shouldLog(Log.INFO)) + _log.info("Response: " + responseLine.trim()); + out.write(DataHelper.getUTF8(responseLine)); } else { for (int j = lastEnd+1; j < i; j++) { if (_headerBuffer.getData()[j] == ':') { @@ -162,22 +162,22 @@ class HTTPResponseOutputStream extends FilterOutputStream { int valLen = i-(j+1); if ( (keyLen <= 0) || (valLen < 0) ) throw new IOException("Invalid header @ " + j); - String key = new String(_headerBuffer.getData(), lastEnd+1, keyLen); - String val = null; + String key = DataHelper.getUTF8(_headerBuffer.getData(), lastEnd+1, keyLen); + String val; if (valLen == 0) val = ""; else - val = new String(_headerBuffer.getData(), j+2, valLen).trim(); + val = DataHelper.getUTF8(_headerBuffer.getData(), j+2, valLen).trim(); if (_log.shouldLog(Log.INFO)) _log.info("Response header [" + key + "] = [" + val + "]"); String lcKey = key.toLowerCase(Locale.US); if ("connection".equals(lcKey)) { - out.write("Connection: close\r\n".getBytes()); + out.write(DataHelper.getASCII("Connection: close\r\n")); connectionSent = true; } else if ("proxy-connection".equals(lcKey)) { - out.write("Proxy-Connection: close\r\n".getBytes()); + out.write(DataHelper.getASCII("Proxy-Connection: close\r\n")); proxyConnectionSent = true; } else if ("content-encoding".equals(lcKey) && "x-i2p-gzip".equals(val.toLowerCase(Locale.US))) { _gzip = true; @@ -192,20 +192,24 @@ class HTTPResponseOutputStream extends FilterOutputStream { } catch (NumberFormatException nfe) {} } else if ("content-type".equals(lcKey)) { // save for compress decision on server side - _contentType = val; + _contentType = val.toLowerCase(Locale.US); + } else if ("content-encoding".equals(lcKey)) { + // save for compress decision on server side + _contentEncoding = val.toLowerCase(Locale.US); } else if ("set-cookie".equals(lcKey)) { String lcVal = val.toLowerCase(Locale.US); if (lcVal.contains("domain=b32.i2p") || - lcVal.contains("domain=.b32.i2p")) { - // Strip privacy-damaging "supercookie" for b32.i2p - // Let's presume the user agent ignores a cookie for "i2p" + lcVal.contains("domain=.b32.i2p") || + lcVal.contains("domain=i2p") || + lcVal.contains("domain=.i2p")) { + // Strip privacy-damaging "supercookies" for i2p and b32.i2p // See RFC 6265 and http://publicsuffix.org/ if (_log.shouldLog(Log.INFO)) _log.info("Stripping \"" + key + ": " + val + "\" from response "); break; } } - out.write((key.trim() + ": " + val.trim() + "\r\n").getBytes()); + out.write(DataHelper.getUTF8(key.trim() + ": " + val + "\r\n")); } break; } @@ -216,9 +220,9 @@ class HTTPResponseOutputStream extends FilterOutputStream { } if (!connectionSent) - out.write("Connection: close\r\n".getBytes()); + out.write(DataHelper.getASCII("Connection: close\r\n")); if (!proxyConnectionSent) - out.write("Proxy-Connection: close\r\n".getBytes()); + out.write(DataHelper.getASCII("Proxy-Connection: close\r\n")); finishHeaders(); @@ -239,88 +243,24 @@ class HTTPResponseOutputStream extends FilterOutputStream { protected boolean shouldCompress() { return _gzip; } protected void finishHeaders() throws IOException { - out.write("\r\n".getBytes()); // end of the headers + out.write(DataHelper.getASCII("\r\n")); // end of the headers } @Override public void close() throws IOException { - out.close(); + if (_log.shouldLog(Log.INFO)) + _log.info("Closing " + out + " threaded?? " + shouldCompress(), new Exception("I did it")); + synchronized(this) { + // synch with changing out field below + super.close(); + } } protected void beginProcessing() throws IOException { //out.flush(); - PipedInputStream pi = BigPipedInputStream.getInstance(); - PipedOutputStream po = new PipedOutputStream(pi); - // Run in the client thread pool, as there should be an unused thread - // there after the accept(). - // Overridden in I2PTunnelHTTPServer, where it does not use the client pool. - try { - I2PTunnelClientBase.getClientExecutor().execute(new Pusher(pi, out)); - } catch (RejectedExecutionException ree) { - // shouldn't happen - throw ree; - } - out = po; - } - - private class Pusher implements Runnable { - private final InputStream _inRaw; - private final OutputStream _out; - - public Pusher(InputStream in, OutputStream out) { - _inRaw = in; - _out = out; - } - - public void run() { - ReusableGZIPInputStream _in = ReusableGZIPInputStream.acquire(); - long written = 0; - ByteArray ba = null; - try { - // blocking - _in.initialize(_inRaw); - ba = _cache.acquire(); - byte buf[] = ba.getData(); - int read = -1; - while ( (read = _in.read(buf)) != -1) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Read " + read + " and writing it to the browser/streams"); - _out.write(buf, 0, read); - _out.flush(); - written += read; - } - if (_log.shouldLog(Log.INFO)) - _log.info("Decompressed: " + written + ", " + _in.getTotalRead() + "/" + _in.getTotalExpanded()); - } catch (IOException ioe) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Error decompressing: " + written + ", " + _in.getTotalRead() + "/" + _in.getTotalExpanded(), ioe); - } catch (OutOfMemoryError oom) { - _log.error("OOM in HTTP Decompressor", oom); - } finally { - if (_log.shouldLog(Log.INFO) && (_in != null)) - _log.info("After decompression, written=" + written + - " read=" + _in.getTotalRead() - + ", expanded=" + _in.getTotalExpanded() + ", remaining=" + _in.getRemaining() - + ", finished=" + _in.getFinished()); - if (ba != null) - _cache.release(ba); - if (_out != null) try { - _out.close(); - } catch (IOException ioe) {} - } - - if (_in != null) { - double compressed = _in.getTotalRead(); - double expanded = _in.getTotalExpanded(); - ReusableGZIPInputStream.release(_in); - if (compressed > 0 && expanded > 0) { - // only update the stats if we did something - double ratio = compressed/expanded; - _context.statManager().addRateData("i2ptunnel.httpCompressionRatio", (int)(100d*ratio), 0); - _context.statManager().addRateData("i2ptunnel.httpCompressed", (long)compressed, 0); - _context.statManager().addRateData("i2ptunnel.httpExpanded", (long)expanded, 0); - } - } + OutputStream po = new GunzipOutputStream(out); + synchronized(this) { + out = po; } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java index eb5195d2e..e8680e3d3 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java @@ -35,14 +35,15 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.lang.reflect.Constructor; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -50,6 +51,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicLong; @@ -80,7 +82,7 @@ import net.i2p.util.OrderedProperties; * An I2PTunnel tracks one or more I2PTunnelTasks and one or more I2PSessions. * Usually one of each. * - * Todo: Most events are not listened to elsewhere, so error propagation is poor + * TODO: Most events are not listened to elsewhere, so error propagation is poor */ public class I2PTunnel extends EventDispatcherImpl implements Logging { private final Log _log; @@ -105,7 +107,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { private static final String nocli_args[] = { "-nocli", "-die"}; - private final List tasks = new ArrayList(); + private final List tasks = new CopyOnWriteArrayList(); private int next_task_id = 1; private final Set listeners = new CopyOnWriteArraySet(); @@ -121,6 +123,9 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { new LongOpt("wait", LongOpt.NO_ARGUMENT, null, 'w') }; + /** @since 0.9.17 */ + private enum CloseMode { NORMAL, FORCED, DESTROY } + public static void main(String[] args) { try { new I2PTunnel(args); @@ -255,7 +260,15 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { } if (gui) { - new I2PTunnelGUI(this); + // removed from source, now in i2p.scripts + //new I2PTunnelGUI(this); + try { + Class cls = Class.forName("net.i2p.i2ptunnel.I2PTunnelGUI"); + Constructor con = cls.getConstructor(I2PTunnel.class); + con.newInstance(this); + } catch (Throwable t) { + throw new UnsupportedOperationException("GUI is not available, try -cli", t); + } } else if (cli) { try { System.out.println("Enter 'help' for help."); @@ -306,19 +319,33 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { " -w, -wait, --wait : do not run the command line interface or GUI"; } - /** @return A copy, non-null */ + /** + * @return A copy, unmodifiable, non-null + */ List getSessions() { - return new ArrayList(_sessions); + if (_sessions.isEmpty()) + return Collections.emptyList(); + return new ArrayList(_sessions); } + /** + * @param session null ok + */ void addSession(I2PSession session) { if (session == null) return; - _sessions.add(session); + boolean added = _sessions.add(session); + if (added && _log.shouldLog(Log.INFO)) + _log.info(getPrefix() + " session added: " + session, new Exception()); } + /** + * @param session null ok + */ void removeSession(I2PSession session) { if (session == null) return; - _sessions.remove(session); + boolean removed = _sessions.remove(session); + if (removed && _log.shouldLog(Log.INFO)) + _log.info(getPrefix() + " session removed: " + session, new Exception()); } /** @@ -334,6 +361,11 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { tsk.setId(next_task_id); next_task_id++; tasks.add(tsk); + if (_log.shouldLog(Log.INFO)) + _log.info(getPrefix() + " adding task: " + tsk); + } else { + if (_log.shouldLog(Log.INFO)) + _log.info(getPrefix() + " not adding task that isn't open: " + tsk); } } @@ -426,7 +458,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { " auth \n" + " client [, []\n" + " clientoptions [-acx] [key=value ]*\n" + - " close [forced] |all\n" + + " close [forced|destroy] |all\n" + " config [-s] \n" + " connectclient [] []\n" + " genkeys []\n" + @@ -507,6 +539,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { * This DOES update a running TunnelTask, but NOT the session. * A more efficient runClientOptions(). * + * Defaults in opts properties are not recommended, they may or may not be honored. + * * @param opts non-null * @since 0.9.1 */ @@ -852,13 +886,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (portNum <= 0) throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]); - I2PTunnelTask task; ownDest = !isShared; try { String privateKeyFile = null; if (args.length >= 4) privateKeyFile = args[3]; - task = new I2PTunnelClient(portNum, args[1], l, ownDest, this, this, privateKeyFile); + I2PTunnelClientBase task = new I2PTunnelClient(portNum, args[1], l, ownDest, this, this, privateKeyFile); + task.startRunning(); addtask(task); notifyEvent("clientTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -931,10 +965,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { } } - I2PTunnelTask task; ownDest = !isShared; try { - task = new I2PTunnelHTTPClient(clientPort, l, ownDest, proxy, this, this); + I2PTunnelClientBase task = new I2PTunnelHTTPClient(clientPort, l, ownDest, proxy, this, this); + task.startRunning(); addtask(task); notifyEvent("httpclientTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -1000,10 +1034,10 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { } } - I2PTunnelTask task; ownDest = !isShared; try { - task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, this, this); + I2PTunnelClientBase task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, this, this); + task.startRunning(); addtask(task); } catch (IllegalArgumentException iae) { String msg = "Invalid I2PTunnel configuration to create a CONNECT client connecting to the router at " + host + ':'+ port + @@ -1062,13 +1096,13 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { } } - I2PTunnelTask task; ownDest = !isShared; try { String privateKeyFile = null; if (args.length >= 4) privateKeyFile = args[3]; - task = new I2PTunnelIRCClient(_port, args[1], l, ownDest, this, this, privateKeyFile); + I2PTunnelClientBase task = new I2PTunnelIRCClient(_port, args[1], l, ownDest, this, this, privateKeyFile); + task.startRunning(); addtask(task); notifyEvent("ircclientTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -1125,7 +1159,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (args.length == 3) privateKeyFile = args[2]; try { - I2PTunnelTask task = new I2PSOCKSTunnel(_port, l, ownDest, this, this, privateKeyFile); + I2PTunnelClientBase task = new I2PSOCKSTunnel(_port, l, ownDest, this, this, privateKeyFile); + task.startRunning(); addtask(task); notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -1172,7 +1207,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (args.length == 3) privateKeyFile = args[2]; try { - I2PTunnelTask task = new I2PSOCKSIRCTunnel(_port, l, ownDest, this, this, privateKeyFile); + I2PTunnelClientBase task = new I2PSOCKSIRCTunnel(_port, l, ownDest, this, this, privateKeyFile); + task.startRunning(); addtask(task); notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { @@ -1291,25 +1327,30 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { * @param l logger to receive events and output */ private void runConfig(String args[], Logging l) { - if (args.length >= 2) { + if (args.length >= 1) { int i = 0; - if (args[0].equals("-s")) { + boolean ssl = args[0].equals("-s"); + if (ssl) { _clientOptions.setProperty("i2cp.SSL", "true"); i++; } else { _clientOptions.remove("i2cp.SSL"); } - host = args[i++]; - listenHost = host; - port = args[i]; + if (i < args.length) { + host = args[i++]; + listenHost = host; + } + if (i < args.length) + port = args[i]; + l.log("New setting: " + host + ' ' + port + (ssl ? " SSL" : " non-SSL")); notifyEvent("configResult", "ok"); } else { boolean ssl = Boolean.parseBoolean(_clientOptions.getProperty("i2cp.SSL")); l.log("Usage:\n" + - " config [-s] \n" + - " sets the connection to the i2p router.\n" + - "Current setting:\n" + - " " + host + ' ' + port + (ssl ? " SSL" : "")); + " config [-s] [] []\n" + + " Sets the address and port of the I2P router.\n" + + " Use -s for SSL.\n" + + "Current setting: " + host + ' ' + port + (ssl ? " SSL" : " non-SSL")); notifyEvent("configResult", "error"); } } @@ -1475,7 +1516,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (tasks.isEmpty()) { System.exit(0); } - l.log("There are running tasks. Try 'list'."); + l.log("There are running tasks. Try 'list' or 'close all'."); //notifyEvent("quitResult", "error"); } @@ -1502,27 +1543,34 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { * * Sets the event "closeResult" = "ok" after the closing is complete * - * @param args {jobNumber}, {"forced", jobNumber}, {"forced", "all"} + * @param args {jobNumber}, {"forced", jobNumber}, {"forced", "all"}, {"destroy", jobNumber}, {"destroy", "all"} * @param l logger to receive events and output */ public void runClose(String args[], Logging l) { if (args.length == 0 || args.length > 2) { - l.log("close [forced] |all\n" + + l.log("close [forced|destroy] |all\n" + " stop running tasks. either only one or all.\n" + " use 'forced' to also stop tasks with active connections.\n" + " use the 'list' command to show the job numbers"); notifyEvent("closeResult", "error"); } else { int argindex = 0; // parse optional 'forced' keyword - boolean forced = false; + CloseMode mode = CloseMode.NORMAL; if (args[argindex].equalsIgnoreCase("forced")) { - forced = true; + mode = CloseMode.FORCED; + argindex++; + } else if (args[argindex].equalsIgnoreCase("destroy")) { + mode = CloseMode.DESTROY; argindex++; } if (args[argindex].equalsIgnoreCase("all")) { boolean error = false; + if (tasks.isEmpty()) { + if (_log.shouldLog(Log.INFO)) + _log.info(getPrefix() + " runClose(all) no tasks"); + } for (I2PTunnelTask t : tasks) { - if (!closetask(t, forced, l)) { + if (!closetask(t, mode, l)) { notifyEvent("closeResult", "error"); error = true; } else if (!error) { // If there's an error, don't hide it @@ -1531,7 +1579,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { } } else { try { - if (!closetask(Integer.parseInt(args[argindex]), forced, l)) { + if (!closetask(Integer.parseInt(args[argindex]), mode, l)) { notifyEvent("closeResult", "error"); } else { notifyEvent("closeResult", "ok"); @@ -1556,7 +1604,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { private void runRun(String args[], Logging l) { if (args.length == 1) { try { - BufferedReader br = new BufferedReader(new FileReader(args[0])); + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(args[0]), "UTF-8")); String line; while ((line = br.readLine()) != null) { runCommand(line, l); @@ -1622,7 +1670,14 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { private void runPing(String allargs, Logging l) { if (allargs.length() != 0) { _clientOptions.setProperty(I2Ping.PROP_COMMAND, allargs); - I2PTunnelTask task = new I2Ping(l, ownDest, this, this); + if (ownDest) { + if (!_clientOptions.containsKey("inbound.nickname")) + _clientOptions.setProperty("inbound.nickname", "I2Ping"); + if (!_clientOptions.containsKey("outbound.nickname")) + _clientOptions.setProperty("outbound.nickname", "I2Ping"); + } + I2PTunnelClientBase task = new I2Ping(l, ownDest, this, this); + task.startRunning(); addtask(task); notifyEvent("pingTaskId", Integer.valueOf(task.getId())); } else { @@ -1636,7 +1691,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { * closure) * */ - private boolean closetask(int num, boolean forced, Logging l) { + private boolean closetask(int num, CloseMode mode, Logging l) { boolean closed = false; _log.debug(getPrefix() + "closetask(): looking for task " + num); @@ -1645,7 +1700,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "closetask(): parsing task " + id + " (" + t.toString() + ")"); if (id == num) { - closed = closetask(t, forced, l); + closed = closetask(t, mode, l); break; } else if (id > num) { break; @@ -1659,17 +1714,23 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { * (optionally forcing closure) * */ - private boolean closetask(I2PTunnelTask t, boolean forced, Logging l) { + private boolean closetask(I2PTunnelTask t, CloseMode mode, Logging l) { if (_log.shouldLog(Log.INFO)) - _log.info("Closing task " + t.getId() + (forced ? " forced..." : "...")); + _log.info("Closing task " + t.getId() + " mode: " + mode); //l.log("Closing task " + t.getId() + (forced ? " forced..." : "...")); - if (t.close(forced)) { + boolean success; + if (mode == CloseMode.NORMAL) + success = t.close(false); + else if (mode == CloseMode.FORCED) + success = t.close(true); + else // DESTROY + success = t.destroy(); + if (success) { if (_log.shouldLog(Log.INFO)) _log.info("Task " + t.getId() + " closed."); //l.log("Task " + t.getId() + " closed."); - return true; } - return false; + return success; } /** @@ -1693,7 +1754,8 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { */ public void log(String s) { System.out.println(s); - _log.info(getPrefix() + "Display: " + s); + //if (_log.shouldLog(Log.INFO)) + // _log.info(getPrefix() + "Display: " + s); } /** @@ -1711,8 +1773,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { l.log("Generating new keys..."); I2PClient client = I2PClientFactory.createClient(); Destination d = client.createDestination(writeTo); - l.log("Secret key saved.\n" + - "Public key: " + d.toBase64()); + l.log("New destination: " + d.toBase32()); writeTo.flush(); writeTo.close(); writePubKey(d, pubDest, l); @@ -1735,7 +1796,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { try { Destination d = new Destination(); d.readBytes(readFrom); - l.log("Public key: " + d.toBase64()); + l.log("Destination: " + d.toBase32()); readFrom.close(); writePubKey(d, pubDest, l); } catch (I2PException ex) { @@ -1750,7 +1811,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { * Deprecated - only used by CLI * * @param d Destination to write - * @param o stream to write the destination to + * @param o stream to write the destination to, or null for noop * @param l logger to send messages to */ private static void writePubKey(Destination d, OutputStream o, Logging l) throws I2PException, IOException { @@ -1812,7 +1873,7 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging { try { result.fromByteArray(content); return result; - } catch (Exception ex) { + } catch (RuntimeException ex) { if (log.shouldLog(Log.INFO)) log.info("File is not a binary destination - trying base64"); try { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java index 2c448d946..4b1284cfe 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java @@ -3,6 +3,7 @@ */ package net.i2p.i2ptunnel; +import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.util.ArrayList; @@ -10,6 +11,7 @@ import java.util.List; import java.util.Properties; import java.util.StringTokenizer; +import net.i2p.I2PException; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketAddress; import net.i2p.data.Destination; @@ -32,6 +34,9 @@ public class I2PTunnelClient extends I2PTunnelClientBase { protected long readTimeout = DEFAULT_READ_TIMEOUT; /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @param destinations peers we target, comma- or space-separated. Since 0.9.9, each dest may be appended with :port * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router @@ -44,11 +49,6 @@ public class I2PTunnelClient extends I2PTunnelClientBase { tunnel, pkf); _addrs = new ArrayList(1); - if (waitEventValue("openBaseClientResult").equals("error")) { - notifyEvent("openClientResult", "error"); - return; - } - dests = new ArrayList(1); buildAddresses(destinations); @@ -68,9 +68,6 @@ public class I2PTunnelClient extends I2PTunnelClientBase { } setName(getLocalPort() + " -> " + destinations); - - startRunning(); - notifyEvent("openClientResult", "ok"); } @@ -122,10 +119,22 @@ public class I2PTunnelClient extends I2PTunnelClientBase { int port = addr.getPort(); i2ps = createI2PSocket(clientDest, port); i2ps.setReadTimeout(readTimeout); - Thread t = new I2PTunnelRunner(s, i2ps, sockLock, null, null, mySockets, + I2PTunnelRunner t = new I2PTunnelRunner(s, i2ps, sockLock, null, null, mySockets, (I2PTunnelRunner.FailCallback) null); - t.start(); - } catch (Exception ex) { + // we are called from an unlimited thread pool, so run inline + //t.start(); + t.run(); + } catch (IOException ex) { + if (_log.shouldLog(Log.INFO)) + _log.info("Error connecting", ex); + //l.log("Error connecting: " + ex.getMessage()); + closeSocket(s); + if (i2ps != null) { + synchronized (sockLock) { + mySockets.remove(sockLock); + } + } + } catch (I2PException ex) { if (_log.shouldLog(Log.INFO)) _log.info("Error connecting", ex); //l.log("Error connecting: " + ex.getMessage()); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java index 5b06e271b..32f8213c6 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java @@ -16,24 +16,27 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Properties; -import java.util.concurrent.Executors; -import java.util.concurrent.SynchronousQueue; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicLong; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; + import net.i2p.I2PAppContext; import net.i2p.I2PException; +import net.i2p.client.I2PClient; import net.i2p.client.I2PSession; +import net.i2p.client.I2PSessionException; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManagerFactory; import net.i2p.client.streaming.I2PSocketOptions; +import net.i2p.crypto.SigType; import net.i2p.data.Destination; import net.i2p.util.EventDispatcher; import net.i2p.util.I2PAppThread; +import net.i2p.util.I2PSSLSocketFactory; import net.i2p.util.Log; public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runnable { @@ -52,7 +55,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna protected boolean _ownDest; protected Destination dest; - private int localPort; + private volatile int localPort; + private final String _handlerName; /** * Protected for I2Ping since 0.9.11. Not for use outside package. @@ -73,22 +77,26 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna // true if we are chained from a server. private boolean chained; - /** how long to wait before dropping an idle thread */ - private static final long HANDLER_KEEPALIVE_MS = 2*60*1000; + private volatile ThreadPoolExecutor _executor; + + /** this is ONLY for shared clients */ + private static I2PSocketManager socketManager; /** - * We keep a static pool of socket handlers for all clients, - * as there is no need for isolation on the client side. - * Extending classes may use it for other purposes. - * Not for use by servers, as there is no limit on threads. + * Only destroy and replace a static shared client socket manager if it's been connected before + * @since 0.9.20 */ - private static volatile ThreadPoolExecutor _executor; - private static int _executorThreadCount; - private static final Object _executorLock = new Object(); + private enum SocketManagerState { INIT, CONNECTED } + private static SocketManagerState _socketManagerState = SocketManagerState.INIT; + + public static final String PROP_USE_SSL = I2PTunnelServer.PROP_USE_SSL; /** - * This constructor always starts the tunnel (ignoring the i2cp.delayOpen option). - * It is used to add a client to an existing socket manager. + * This constructor is used to add a client to an existing socket manager. + *

+ * As of 0.9.21 this does NOT open the local socket. You MUST call + * {@link #startRunning()} for that. The local socket will be opened + * immediately (ignoring the i2cp.delayOpen option). * * @param localPort if 0, use any port, get actual port selected with getLocalPort() * @param sktMgr the existing socket manager @@ -100,46 +108,24 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna chained = true; sockMgr = sktMgr; _clientId = clientId; + _handlerName = "chained"; this.localPort = localPort; this.l = l; _ownDest = true; // == ! shared client _context = tunnel.getContext(); - _context.statManager().createRateStat("i2ptunnel.client.closeBacklog", "How many pending sockets remain when we close one due to backlog?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); - _context.statManager().createRateStat("i2ptunnel.client.closeNoBacklog", "How many pending sockets remain when it was removed prior to backlog timeout?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); - _context.statManager().createRateStat("i2ptunnel.client.manageTime", "How long it takes to accept a socket and fire it into an i2ptunnel runner (or queue it for the pool)?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); - _context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); + initStats(); _log = _context.logManager().getLog(getClass()); - - synchronized (_executorLock) { - if (_executor == null) - _executor = new CustomThreadPoolExecutor(); - } - - Thread t = new I2PAppThread(this, "Client " + tunnel.listenHost + ':' + localPort); - t.start(); - open = true; - synchronized (this) { - while (!listenerReady && open) { - try { - wait(); - } catch (InterruptedException e) { - // ignore - } - } - } - - if (open && listenerReady) { - l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort); - notifyEvent("openBaseClientResult", "ok"); - } else { - l.log("Client error for " + tunnel.listenHost + ':' + localPort + ", check logs"); - notifyEvent("openBaseClientResult", "error"); - } } /** * The main constructor. - * This may take a LONG time if building and starting a new manager. + *

+ * As of 0.9.21 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + *

+ * (0.9.20 claimed to be fast, but due to a bug it DID connect the manager + * to the router. It did NOT open the local socket however, so it was still + * necessary to call startRunning() for that.) * * @param localPort if 0, use any port, get actual port selected with getLocalPort() * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -153,7 +139,13 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * Use this to build a client with a persistent private key. - * This may take a LONG time if building and starting a new manager. + *

+ * As of 0.9.21 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + *

+ * (0.9.20 claimed to be fast, but due to a bug it DID connect the manager + * to the router. It did NOT open the local socket however, so it was still + * necessary to call startRunning() for that.) * * @param localPort if 0, use any port, get actual port selected with getLocalPort() * @param pkf Path to the private key file, or null to generate a transient key @@ -169,20 +161,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna this.localPort = localPort; this.l = l; _ownDest = ownDest; // == ! shared client - + _handlerName = handlerName; _context = tunnel.getContext(); - _context.statManager().createRateStat("i2ptunnel.client.closeBacklog", "How many pending sockets remain when we close one due to backlog?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); - _context.statManager().createRateStat("i2ptunnel.client.closeNoBacklog", "How many pending sockets remain when it was removed prior to backlog timeout?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); - _context.statManager().createRateStat("i2ptunnel.client.manageTime", "How long it takes to accept a socket and fire it into an i2ptunnel runner (or queue it for the pool)?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); - _context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); + initStats(); _log = _context.logManager().getLog(getClass()); - synchronized (_executorLock) { - if (_executor == null) - _executor = new CustomThreadPoolExecutor(); - } - // normalize path so we can find it if (pkf != null) { File keyFile = new File(pkf); @@ -199,54 +183,19 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna tunnel.getClientOptions().setProperty("i2cp.dontPublishLeaseSet", "true"); if (tunnel.getClientOptions().getProperty("i2p.streaming.answerPings") == null) tunnel.getClientOptions().setProperty("i2p.streaming.answerPings", "false"); - - boolean openNow = !Boolean.parseBoolean(tunnel.getClientOptions().getProperty("i2cp.delayOpen")); - if (openNow) { - while (sockMgr == null) { - verifySocketManager(); - if (sockMgr == null) { - _log.error("Unable to connect to router and build tunnels for " + handlerName); - // FIXME there is a loop in buildSocketManager(), do we really need another one here? - // no matter, buildSocketManager() now throws an IllegalArgumentException - try { Thread.sleep(10*1000); } catch (InterruptedException ie) {} - } - } - // can't be null unless we limit the loop above - //if (sockMgr == null) { - // l.log("Invalid I2CP configuration"); - // throw new IllegalArgumentException("Socket manager could not be created"); - //} - l.log("Tunnels ready for client: " + handlerName); - - } // else delay creating session until createI2PSocket() is called - - Thread t = new I2PAppThread(this); - t.setName("Client " + _clientId); - t.start(); - open = true; - synchronized (this) { - while (!listenerReady && open) { - try { - wait(); - } catch (InterruptedException e) { - // ignore - } - } - } - - if (open && listenerReady) { - if (openNow) - l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort); - else - l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort + ", delaying tunnel open until required"); - notifyEvent("openBaseClientResult", "ok"); - } else { - l.log("Client error for " + tunnel.listenHost + ':' + localPort + ", check logs"); - notifyEvent("openBaseClientResult", "error"); - } } - + + private void initStats() { + _context.statManager().createRateStat("i2ptunnel.client.closeBacklog", "How many pending sockets remain when we close one due to backlog?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); + _context.statManager().createRateStat("i2ptunnel.client.closeNoBacklog", "How many pending sockets remain when it was removed prior to backlog timeout?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); + _context.statManager().createRateStat("i2ptunnel.client.manageTime", "How long it takes to accept a socket and fire it into an i2ptunnel runner (or queue it for the pool)?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); + _context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); + } + /** + * Create the manager if it doesn't exist, AND connect it to the router and + * build tunnels. + * * Sets the this.sockMgr field if it is null, or if we want a new one. * This may take a LONG time if building a new manager. * @@ -288,15 +237,13 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna this.sockMgr = getSocketManager(); } } + connectManager(); } - /** this is ONLY for shared clients */ - private static I2PSocketManager socketManager; - - /** * This is ONLY for shared clients. - * This may take a LONG time if building a new manager. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -308,7 +255,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * This is ONLY for shared clients. - * This may take a LONG time if building a new manager. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -320,7 +268,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * This is ONLY for shared clients. - * This may take a LONG time if building a new manager. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -331,28 +280,81 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna Log _log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class); if (socketManager != null && !socketManager.isDestroyed()) { I2PSession s = socketManager.getSession(); - if (s.isClosed()) { + if (s.isClosed() && _socketManagerState != SocketManagerState.INIT) { if (_log.shouldLog(Log.INFO)) _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since the old one closed [s=" + s + "]"); tunnel.removeSession(s); // make sure the old one is closed socketManager.destroySocketManager(); + _socketManagerState = SocketManagerState.INIT; // We could be here a LONG time, holding the lock socketManager = buildSocketManager(tunnel, pkf); + // FIXME may not be the right place for this + I2PSession sub = addSubsession(tunnel); + if (sub != null && _log.shouldLog(Log.WARN)) + _log.warn("Added subsession " + sub); } else { if (_log.shouldLog(Log.INFO)) _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Not building a new socket manager since the old one is open [s=" + s + "]"); + // If some other tunnel created the session, we need to add it + // as our session too. + // It's a Set in I2PTunnel + tunnel.addSession(s); } } else { if (_log.shouldLog(Log.INFO)) _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since there is no other one"); socketManager = buildSocketManager(tunnel, pkf); + I2PSession sub = addSubsession(tunnel); + if (sub != null && _log.shouldLog(Log.WARN)) + _log.warn("Added subsession " + sub); } return socketManager; } /** - * This may take a LONG time. + * Add a subsession to a shared client if necessary. + * + * @since 0.9.20 + */ + protected static synchronized I2PSession addSubsession(I2PTunnel tunnel) { + I2PSession sess = socketManager.getSession(); + if (sess.getMyDestination().getSigType() == SigType.DSA_SHA1) + return null; + Properties props = new Properties(); + props.putAll(tunnel.getClientOptions()); + String name = props.getProperty("inbound.nickname"); + if (name != null) + props.setProperty("inbound.nickname", name + " (DSA)"); + name = props.getProperty("outbound.nickname"); + if (name != null) + props.setProperty("outbound.nickname", name + " (DSA)"); + props.setProperty(I2PClient.PROP_SIGTYPE, "DSA_SHA1"); + try { + return socketManager.addSubsession(null, props); + } catch (I2PSessionException ise) { + Log log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class); + if (log.shouldLog(Log.WARN)) + log.warn("Failed to add subssession", ise); + return null; + } + } + + /** + * Kill the shared client, so that on restart in android + * we won't latch onto the old one + * + * @since 0.9.18 + */ + protected static synchronized void killSharedClient() { + socketManager = null; + } + + /** + * For NON-SHARED clients (ownDest = true). + * + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -361,8 +363,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna protected I2PSocketManager buildSocketManager() { return buildSocketManager(getTunnel(), this.privKeyFile, this.l); } + /** - * This may take a LONG time. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @return non-null * @throws IllegalArgumentException if the I2CP configuration is b0rked so @@ -376,7 +380,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna private static final int MAX_RETRIES = 4; /** - * This may take a LONG time. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @param pkf absolute path or null * @return non-null @@ -388,7 +393,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } /** - * This may take a LONG time. + * As of 0.9.20 this is fast, and does NOT connect the manager to the router. + * Call verifySocketManager() for that. * * @param pkf absolute path or null * @return non-null @@ -405,51 +411,30 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna try { portNum = Integer.parseInt(tunnel.port); } catch (NumberFormatException nfe) { - _log.log(Log.CRIT, "Invalid port specified [" + tunnel.port + "], reverting to " + portNum); + throw new IllegalArgumentException("Invalid port specified [" + tunnel.port + "]", nfe); } } I2PSocketManager sockManager = null; - // FIXME: Can't stop a tunnel from the UI while it's in this loop (no session yet) - int retries = 0; - while (sockManager == null) { + FileInputStream fis = null; + try { if (pkf != null) { // Persistent client dest - FileInputStream fis = null; - try { - fis = new FileInputStream(pkf); - sockManager = I2PSocketManagerFactory.createManager(fis, tunnel.host, portNum, props); - } catch (IOException ioe) { - if (log != null) - log.log("Error opening key file " + ioe); - _log.error("Error opening key file", ioe); - throw new IllegalArgumentException("Error opening key file " + ioe); - } finally { - if (fis != null) - try { fis.close(); } catch (IOException ioe) {} - } + fis = new FileInputStream(pkf); + sockManager = I2PSocketManagerFactory.createDisconnectedManager(fis, tunnel.host, portNum, props); } else { - sockManager = I2PSocketManagerFactory.createManager(tunnel.host, portNum, props); - } - - if (sockManager == null) { - // try to make this error sensible as it will happen... sadly we can't get to the listenPort, only the listenHost - String msg = "Unable to connect to the router at " + tunnel.host + ':' + portNum + - " and build tunnels for the client"; - if (++retries < MAX_RETRIES) { - if (log != null) - log.log(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds"); - _log.error(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds"); - } else { - if (log != null) - log.log(msg + ", giving up"); - _log.log(Log.CRIT, msg + ", giving up"); - // not clear if callers can handle null - //return null; - throw new IllegalArgumentException(msg); - } - try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException ie) {} + sockManager = I2PSocketManagerFactory.createDisconnectedManager(null, tunnel.host, portNum, props); } + } catch (I2PSessionException ise) { + throw new IllegalArgumentException("Can't create socket manager", ise); + } catch (IOException ioe) { + if (log != null) + log.log("Error opening key file " + ioe); + _log.error("Error opening key file", ioe); + throw new IllegalArgumentException("Error opening key file", ioe); + } finally { + if (fis != null) + try { fis.close(); } catch (IOException ioe) {} } sockManager.setName("Client"); if (_log.shouldLog(Log.INFO)) @@ -458,6 +443,53 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna return sockManager; } + + /** + * Warning, blocks while connecting to router and building tunnels; + * This may take a LONG time. + * + * @throws IllegalArgumentException if the I2CP configuration is b0rked so + * badly that we cant create a socketManager + * @since 0.9.20 + */ + private void connectManager() { + int retries = 0; + while (sockMgr.getSession().isClosed()) { + try { + sockMgr.getSession().connect(); + synchronized(I2PTunnelClientBase.class) { + if (sockMgr == socketManager) + _socketManagerState = SocketManagerState.CONNECTED; + } + } catch (I2PSessionException ise) { + // shadows instance _log + Log _log = getTunnel().getContext().logManager().getLog(I2PTunnelClientBase.class); + Logging log = this.l; + // try to make this error sensible as it will happen... + String portNum = getTunnel().port; + if (portNum == null) + portNum = "7654"; + String msg; + if (getTunnel().getContext().isRouterContext()) + msg = "Unable to connect to the router at " + getTunnel().host + ':' + portNum + + " and build tunnels for the client"; + else + msg = "Unable to build tunnels for the client"; + if (++retries < MAX_RETRIES) { + if (log != null) + log.log(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds"); + _log.error(msg + ", retrying in " + (RETRY_DELAY / 1000) + " seconds", ise); + } else { + if (log != null) + log.log(msg + ", giving up"); + _log.log(Log.CRIT, msg + ", giving up", ise); + throw new IllegalArgumentException(msg, ise); + } + try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException ie) {} + } + } + } + public final int getLocalPort() { return localPort; } @@ -474,11 +506,71 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } /** - * Actually start working on incoming connections. *Must* be + * Actually open the local socket and start working on incoming connections. *Must* be * called by derived classes after initialization. * + * (this wasn't actually true until 0.9.20) + * + * This will be fast if i2cp.delayOpen is true, but could take + * a LONG TIME if it is false, as it connects to the router and builds tunnels. + * + * Extending classes must check the value of boolean open after calling + * super.startRunning(), if false then something went wrong. + * */ public void startRunning() { + boolean openNow = !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty("i2cp.delayOpen")); + if (openNow) { + while (sockMgr == null) { + verifySocketManager(); + if (sockMgr == null) { + _log.error("Unable to connect to router and build tunnels for " + _handlerName); + // FIXME there is a loop in buildSocketManager(), do we really need another one here? + // no matter, buildSocketManager() now throws an IllegalArgumentException + try { Thread.sleep(10*1000); } catch (InterruptedException ie) {} + } else { + l.log("Tunnels ready for client: " + _handlerName); + } + } + // can't be null unless we limit the loop above + //if (sockMgr == null) { + // l.log("Invalid I2CP configuration"); + // throw new IllegalArgumentException("Socket manager could not be created"); + //} + + } // else delay creating session until createI2PSocket() is called + startup(); + } + + private void startup() { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("startup " + _clientId, new Exception("I did it")); + // prevent JVM exit when running outside the router + boolean isDaemon = getTunnel().getContext().isRouterContext(); + open = true; + Thread t = new I2PAppThread(this, "I2PTunnel Client " + getTunnel().listenHost + ':' + localPort, isDaemon); + t.start(); + synchronized (this) { + while (!listenerReady && open) { + try { + wait(); + } catch (InterruptedException e) { + // ignore + } + } + } + + if (open && listenerReady) { + boolean openNow = !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty("i2cp.delayOpen")); + if (openNow || chained) + l.log("Client ready, listening on " + getTunnel().listenHost + ':' + localPort); + else + l.log("Client ready, listening on " + getTunnel().listenHost + ':' + localPort + ", delaying tunnel open until required"); + notifyEvent("openBaseClientResult", "ok"); + } else { + l.log("Client error for " + getTunnel().listenHost + ':' + localPort + ", check logs"); + notifyEvent("openBaseClientResult", "error"); + } synchronized (startLock) { startRunning = true; startLock.notify(); @@ -587,19 +679,40 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * Non-final since 0.9.11. - * Any overrides must set listenerReady = true. + * open will be true before being called. + * Any overrides must set listenerReady = true and then notifyAll() if setup is successful, + * and must call close() and then notifyAll() on failure or termination. */ public void run() { - try { - InetAddress addr = getListenHost(l); - if (addr == null) { - open = false; - synchronized (this) { - notifyAll(); - } - return; + InetAddress addr = getListenHost(l); + if (addr == null) { + close(true); + open = false; + synchronized (this) { + notifyAll(); + } + return; + } + try { + Properties opts = getTunnel().getClientOptions(); + boolean useSSL = Boolean.parseBoolean(opts.getProperty(PROP_USE_SSL)); + if (useSSL) { + // was already done in web/IndexBean.java when saving the config + boolean wasCreated = SSLClientUtil.verifyKeyStore(opts); + if (wasCreated) { + // From here, we can't save the config. + // We shouldn't get here, as SSL isn't the default, so it would + // be enabled via the GUI only. + // If it was done manually, the keys will be regenerated at every startup, + // which is bad. + _log.logAlways(Log.WARN, "Created new i2ptunnel SSL keys but can't save the config, disable and enable via i2ptunnel GUI"); + } + SSLServerSocketFactory fact = SSLClientUtil.initializeFactory(opts); + ss = fact.createServerSocket(localPort, 0, addr); + I2PSSLSocketFactory.setProtocolsAndCiphers((SSLServerSocket) ss); + } else { + ss = new ServerSocket(localPort, 0, addr); } - ss = new ServerSocket(localPort, 0, addr); // If a free port was requested, find out what we got if (localPort == 0) { @@ -612,7 +725,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna // Notify constructor that port is ready synchronized (this) { listenerReady = true; - notify(); + notifyAll(); } // Wait until we are authorized to process data @@ -625,49 +738,36 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } } + TunnelControllerGroup tcg = TunnelControllerGroup.getInstance(); + if (tcg != null) { + _executor = tcg.getClientExecutor(); + } else { + // Fallback in case TCG.getInstance() is null, never instantiated + // and we were not started by TCG. + // Maybe a plugin loaded before TCG? Should be rare. + // Never shut down. + _executor = new TunnelControllerGroup.CustomThreadPoolExecutor(); + } while (open) { Socket s = ss.accept(); manageConnection(s); } } catch (IOException ex) { - if (open) { - _log.error("Error listening for connections on " + localPort, ex); - notifyEvent("openBaseClientResult", "error"); - } synchronized (sockLock) { mySockets.clear(); } - open = false; + if (open) { + _log.error("Error listening for connections on " + addr + " port " + localPort, ex); + l.log("Error listening for connections on " + addr + " port " + localPort + ": " + ex); + notifyEvent("openBaseClientResult", "error"); + close(true); + } synchronized (this) { notifyAll(); } } } - /** - * @return may be null if no class has been instantiated - * @since 0.8.8 - */ - static ThreadPoolExecutor getClientExecutor() { - return _executor; - } - - /** - * @since 0.8.8 - */ - static void killClientExecutor() { - synchronized (_executorLock) { - if (_executor != null) { - _executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); - _executor.shutdownNow(); - _executor = null; - } - // kill the shared client, so that on restart in android - // we won't latch onto the old one - socketManager = null; - } - } - /** * Manage the connection just opened on the specified socket * @@ -693,37 +793,36 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna } } - /** - * Not really needed for now but in case we want to add some hooks like afterExecute(). - */ - private static class CustomThreadPoolExecutor extends ThreadPoolExecutor { - public CustomThreadPoolExecutor() { - super(0, Integer.MAX_VALUE, HANDLER_KEEPALIVE_MS, TimeUnit.MILLISECONDS, - new SynchronousQueue(), new CustomThreadFactory()); - } - } - - /** just to set the name and set Daemon */ - private static class CustomThreadFactory implements ThreadFactory { - public Thread newThread(Runnable r) { - Thread rv = Executors.defaultThreadFactory().newThread(r); - rv.setName("I2PTunnel Client Runner " + (++_executorThreadCount)); - rv.setDaemon(true); - return rv; - } - } - /** * Blocking runner, used during the connection establishment */ private class BlockingRunner implements Runnable { - private Socket _s; + private final Socket _s; public BlockingRunner(Socket s) { _s = s; } public void run() { - clientConnectionRun(_s); + try { + clientConnectionRun(_s); + } catch (Throwable t) { + // probably an IllegalArgumentException from + // connecting to the router in a delay-open or + // close-on-idle tunnel (in connectManager() above) + _log.error("Uncaught error in i2ptunnel client", t); + } } } + /** + * Note that the tunnel can be reopened after this by calling startRunning(). + * This may not release all resources. In particular, the I2PSocketManager remains + * and it may have timer threads that continue running. + * + * To release all resources permanently, call destroy(). + * + * Does nothing if open is already false. + * Sets open = false but does not notifyAll(). + * + * @return success + */ public boolean close(boolean forced) { if (_log.shouldLog(Log.INFO)) _log.info("close() called: forced = " + forced + " open = " + open + " sockMgr = " + sockMgr); @@ -746,6 +845,12 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna if (!chained) { I2PSession session = sockMgr.getSession(); getTunnel().removeSession(session); + if (_ownDest) { + try { + session.destroySession(); + } catch (I2PException ex) {} + } + // TCG will try to destroy it too } // else the app chaining to this one closes it! } l.log("Stopping client " + toString()); @@ -753,8 +858,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna try { if (ss != null) ss.close(); } catch (IOException ex) { - if (_log.shouldLog(Log.WARN)) - _log.warn("error closing", ex); + if (_log.shouldDebug()) + _log.debug("error closing", ex); return false; } //l.log("Client closed."); @@ -762,6 +867,22 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna return true; } + /** + * Note that the tunnel cannot be reopened after this by calling startRunning(), + * as it will destroy the underlying socket manager. + * This releases all resources if not a shared client. + * For shared client, the router will kill all the remaining streaming timers at shutdown. + * + * @since 0.9.17 + */ + @Override + public synchronized boolean destroy() { + close(true); + if (_ownDest) + sockMgr.destroySocketManager(); + return true; + } + public static void closeSocket(Socket s) { try { s.close(); @@ -772,7 +893,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna /** * Manage a connection in a separate thread. This only works if - * you do not override manageConnection() + * you do not override manageConnection(). + * + * This is run in a thread from an unlimited-size thread pool, + * so it may block or run indefinitely. */ protected abstract void clientConnectionRun(Socket s); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java index 7690e2c65..0f5b5dcce 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java @@ -59,26 +59,31 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R public static final String AUTH_REALM = "I2P SSL Proxy"; - private final static byte[] ERR_BAD_PROTOCOL = - ("HTTP/1.1 405 Bad Method\r\n"+ + private final static String ERR_BAD_PROTOCOL = + "HTTP/1.1 405 Bad Method\r\n"+ "Content-Type: text/html; charset=iso-8859-1\r\n"+ "Cache-control: no-cache\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n"+ "

I2P ERROR: METHOD NOT ALLOWED

"+ "The request uses a bad protocol. "+ - "The Connect Proxy supports CONNECT requests ONLY. Other methods such as GET are not allowed - Maybe you wanted the HTTP Proxy?.
") - .getBytes(); + "The Connect Proxy supports CONNECT requests ONLY. Other methods such as GET are not allowed - Maybe you wanted the HTTP Proxy?.
"; - private final static byte[] ERR_LOCALHOST = - ("HTTP/1.1 403 Access Denied\r\n"+ + private final static String ERR_LOCALHOST = + "HTTP/1.1 403 Access Denied\r\n"+ "Content-Type: text/html; charset=iso-8859-1\r\n"+ "Cache-control: no-cache\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n"+ "

I2P ERROR: REQUEST DENIED

"+ - "Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.
") - .getBytes(); + "Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.
"; /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router */ @@ -87,11 +92,6 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R I2PTunnel tunnel) throws IllegalArgumentException { super(localPort, ownDest, l, notifyThis, "HTTPS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel); - if (waitEventValue("openBaseClientResult").equals("error")) { - notifyEvent("openConnectClientResult", "error"); - return; - } - if (wwwProxy != null) { StringTokenizer tok = new StringTokenizer(wwwProxy, ", "); while (tok.hasMoreTokens()) @@ -99,8 +99,6 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R } setName("HTTPS Proxy on " + tunnel.listenHost + ':' + localPort); - - startRunning(); } /** @@ -126,7 +124,8 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R @Override public void startRunning() { super.startRunning(); - _context.portMapper().register(PortMapper.SVC_HTTPS_PROXY, getLocalPort()); + if (open) + _context.portMapper().register(PortMapper.SVC_HTTPS_PROXY, getLocalPort()); } @Override @@ -241,7 +240,7 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R } if (user != null && pw != null) { newRequest.append("Proxy-Authorization: Basic ") - .append(Base64.encode((user + ':' + pw).getBytes(), true)) // true = use standard alphabet + .append(Base64.encode(DataHelper.getUTF8(user + ':' + pw), true)) // true = use standard alphabet .append("\r\n"); } } @@ -266,14 +265,14 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R else _log.warn(getPrefix(requestId) + "Auth required, sending 407"); } - out.write(getAuthError(result == AuthResult.AUTH_STALE).getBytes()); + out.write(DataHelper.getASCII(getAuthError(result == AuthResult.AUTH_STALE))); s.close(); return; } Destination clientDest = _context.namingService().lookup(destination); if (clientDest == null) { - byte[] header; + String header; if (usingWWWProxy) header = getErrorPage("dnfp", ERR_DESTINATION_UNKNOWN); else @@ -289,10 +288,12 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R if (usingWWWProxy) data = newRequest.toString().getBytes("ISO-8859-1"); else - response = SUCCESS_RESPONSE; + response = SUCCESS_RESPONSE.getBytes("UTF-8"); OnTimeout onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId); Thread t = new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout); - t.start(); + // we are called from an unlimited thread pool, so run inline + //t.start(); + t.run(); } catch (IOException ex) { _log.info(getPrefix(requestId) + "Error trying to connect", ex); handleClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId); @@ -309,10 +310,10 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R } } - private static void writeErrorMessage(byte[] errMessage, OutputStream out) throws IOException { + private static void writeErrorMessage(String errMessage, OutputStream out) throws IOException { if (out == null) return; - out.write(errMessage); + out.write(errMessage.getBytes("UTF-8")); writeFooter(out); } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelGUI.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelGUI.java deleted file mode 100644 index 7dd730845..000000000 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelGUI.java +++ /dev/null @@ -1,48 +0,0 @@ -/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java) - * (c) 2003 - 2004 mihi - */ -package net.i2p.i2ptunnel; - -import java.awt.BorderLayout; -import java.awt.Font; -import java.awt.Frame; -import java.awt.TextArea; -import java.awt.TextField; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * AWT gui since kaffe doesn't support swing yet - */ -public class I2PTunnelGUI extends Frame implements ActionListener, Logging { - - TextField input; - TextArea log; - I2PTunnel t; - - public I2PTunnelGUI(I2PTunnel t) { - super("I2PTunnel control panel"); - this.t = t; - setLayout(new BorderLayout()); - add("South", input = new TextField()); - input.addActionListener(this); - Font font = new Font("Monospaced", Font.PLAIN, 12); - add("Center", log = new TextArea("", 20, 80, TextArea.SCROLLBARS_VERTICAL_ONLY)); - log.setFont(font); - log.setEditable(false); - log("enter 'help' for help."); - pack(); - setVisible(true); - } - - public void log(String s) { - log.append(s + "\n"); - } - - public void actionPerformed(ActionEvent evt) { - log("I2PTunnel>" + input.getText()); - t.runCommand(input.getText(), this); - log("---"); - input.setText(""); - } -} \ No newline at end of file diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirProxy.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirProxy.java index 56c2e7550..4dbd5e654 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirProxy.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirProxy.java @@ -30,6 +30,9 @@ public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runn /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router */ @@ -38,8 +41,6 @@ public class I2PTunnelHTTPBidirProxy extends I2PTunnelHTTPClient implements Runn // proxyList = new ArrayList(); setName(getLocalPort() + " -> HTTPClient [NO PROXIES]"); - startRunning(); - notifyEvent("openHTTPClientResult", "ok"); } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirServer.java index d97482e04..2a3118567 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPBidirServer.java @@ -32,7 +32,9 @@ public class I2PTunnelHTTPBidirServer extends I2PTunnelHTTPServer { bidir = true; /* start the httpclient */ - task = new I2PTunnelHTTPBidirProxy(localPort, l, sockMgr, getTunnel(), getEventDispatcher(), __serverId); + I2PTunnelClientBase client = new I2PTunnelHTTPBidirProxy(localPort, l, sockMgr, getTunnel(), getEventDispatcher(), __serverId); + client.startRunning(); + task = client; sockMgr.setName("Server"); // TO-DO: Need to change this to "Bidir"! getTunnel().addSession(sockMgr.getSession()); l.log("Ready!"); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 625ae863a..19ebd8b7c 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -3,9 +3,12 @@ */ package net.i2p.i2ptunnel; +import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.net.Socket; import java.net.SocketException; import java.net.URI; @@ -84,13 +87,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn /** * These are backups if the xxx.ht error page is missing. */ - private final static byte[] ERR_REQUEST_DENIED = - ("HTTP/1.1 403 Access Denied\r\n" + + private final static String ERR_REQUEST_DENIED = + "HTTP/1.1 403 Access Denied\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: REQUEST DENIED

" + - "You attempted to connect to a non-I2P website or location.
").getBytes(); + "You attempted to connect to a non-I2P website or location.
"; /***** private final static byte[] ERR_TIMEOUT = @@ -105,90 +110,109 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn "the following Destination:

") .getBytes(); *****/ - private final static byte[] ERR_NO_OUTPROXY = - ("HTTP/1.1 503 Service Unavailable\r\n" + + private final static String ERR_NO_OUTPROXY = + "HTTP/1.1 503 Service Unavailable\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: No outproxy found

" + "Your request was for a site outside of I2P, but you have no " + - "HTTP outproxy configured. Please configure an outproxy in I2PTunnel").getBytes(); + "HTTP outproxy configured. Please configure an outproxy in I2PTunnel"; - private final static byte[] ERR_AHELPER_CONFLICT = - ("HTTP/1.1 409 Conflict\r\n" + + private final static String ERR_AHELPER_CONFLICT = + "HTTP/1.1 409 Conflict\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: Destination key conflict

" + "The addresshelper link you followed specifies a different destination key " + "than a host entry in your host database. " + - "Someone could be trying to impersonate another eepsite, " + - "or people have given two eepsites identical names.

" + + "Someone could be trying to impersonate another website, " + + "or people have given two websites identical names.

" + "You can resolve the conflict by considering which key you trust, " + "and either discarding the addresshelper link, " + "discarding the host entry from your host database, " + - "or naming one of them differently.

").getBytes(); + "or naming one of them differently.

"; - private final static byte[] ERR_AHELPER_NOTFOUND = - ("HTTP/1.1 404 Not Found\r\n" + + private final static String ERR_AHELPER_NOTFOUND = + "HTTP/1.1 404 Not Found\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: Helper key not resolvable.

" + "The helper key you put for i2paddresshelper= is not resolvable. " + "It seems to be garbage data, or a mistyped b32. Check your URL " + - "to try and fix the helper key to be either a b32 or a base64.").getBytes(); + "to try and fix the helper key to be either a b32 or a base64."; - private final static byte[] ERR_AHELPER_NEW = - ("HTTP/1.1 409 New Address\r\n" + + private final static String ERR_AHELPER_NEW = + "HTTP/1.1 409 New Address\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

New Host Name with Address Helper

" + "The address helper link you followed is for a new host name that is not in your address book. " + "You may either save the destination for this host name to your address book, or remember it only until your router restarts. " + "If you save it to your address book, you will not see this message again. " + - "If you do not wish to visit this host, click the \"back\" button on your browser.").getBytes(); + "If you do not wish to visit this host, click the \"back\" button on your browser."; - private final static byte[] ERR_BAD_PROTOCOL = - ("HTTP/1.1 403 Bad Protocol\r\n" + + private final static String ERR_BAD_PROTOCOL = + "HTTP/1.1 403 Bad Protocol\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: NON-HTTP PROTOCOL

" + "The request uses a bad protocol. " + - "The I2P HTTP Proxy supports HTTP and HTTPS requests only. Other protocols such as FTP are not allowed.
").getBytes(); + "The I2P HTTP Proxy supports HTTP and HTTPS requests only. Other protocols such as FTP are not allowed.
"; - private final static byte[] ERR_BAD_URI = - ("HTTP/1.1 403 Bad URI\r\n" + + private final static String ERR_BAD_URI = + "HTTP/1.1 403 Bad URI\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: INVALID REQUEST URI

" + "The request URI is invalid, and probably contains illegal characters. " + - "If you clicked e.g. a forum link, check the end of the URI for any characters the browser has mistakenly added on.
").getBytes(); + "If you clicked e.g. a forum link, check the end of the URI for any characters the browser has mistakenly added on.
"; - private final static byte[] ERR_LOCALHOST = - ("HTTP/1.1 403 Access Denied\r\n" + + private final static String ERR_LOCALHOST = + "HTTP/1.1 403 Access Denied\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: REQUEST DENIED

" + - "Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.
").getBytes(); + "Your browser is misconfigured. Do not use the proxy to access the router console or other localhost destinations.
"; - private final static byte[] ERR_INTERNAL_SSL = - ("HTTP/1.1 403 SSL Rejected\r\n" + + private final static String ERR_INTERNAL_SSL = + "HTTP/1.1 403 SSL Rejected\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: SSL to I2P address rejected

" + "SSL for to .i2p addresses denied by configuration." + - "You may change the configuration in I2PTunnel").getBytes(); + "You may change the configuration in I2PTunnel"; /** * This constructor always starts the tunnel (ignoring the i2cp.delayOpen option). * It is used to add a client to an existing socket manager. * + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @param sockMgr the existing socket manager */ public I2PTunnelHTTPClient(int localPort, Logging l, I2PSocketManager sockMgr, I2PTunnel tunnel, EventDispatcher notifyThis, long clientId) { @@ -197,12 +221,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // proxyList = new ArrayList(); setName("HTTP Proxy on " + getTunnel().listenHost + ':' + localPort); - startRunning(); - notifyEvent("openHTTPClientResult", "ok"); } /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router */ @@ -213,10 +238,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn _proxyNonce = Long.toString(_context.random().nextLong()); //proxyList = new ArrayList(); // We won't use outside of i2p - if(waitEventValue("openBaseClientResult").equals("error")) { - notifyEvent("openHTTPClientResult", "error"); - return; - } if(wwwProxy != null) { StringTokenizer tok = new StringTokenizer(wwwProxy, ", "); @@ -226,9 +247,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn } setName("HTTP Proxy on " + tunnel.listenHost + ':' + localPort); - - startRunning(); - notifyEvent("openHTTPClientResult", "ok"); } @@ -293,9 +311,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn _context.statManager().createRateStat("i2ptunnel.httpCompressed", "compressed size transferred", "I2PTunnel", new long[] { 60*60*1000 }); _context.statManager().createRateStat("i2ptunnel.httpExpanded", "size transferred after expansion", "I2PTunnel", new long[] { 60*60*1000 }); super.startRunning(); - this.isr = new InternalSocketRunner(this); - this.isr.start(); - _context.portMapper().register(PortMapper.SVC_HTTP_PROXY, getLocalPort()); + if (open) { + this.isr = new InternalSocketRunner(this); + this.isr.start(); + int port = getLocalPort(); + _context.portMapper().register(PortMapper.SVC_HTTP_PROXY, port); + _context.portMapper().register(PortMapper.SVC_HTTPS_PROXY, port); + } } /** @@ -303,10 +325,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn */ @Override public boolean close(boolean forced) { + int port = getLocalPort(); int reg = _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY); - if(reg == getLocalPort()) { + if (reg == port) { _context.portMapper().unregister(PortMapper.SVC_HTTP_PROXY); } + reg = _context.portMapper().getPort(PortMapper.SVC_HTTPS_PROXY); + if (reg == port) { + _context.portMapper().unregister(PortMapper.SVC_HTTPS_PROXY); + } boolean rv = super.close(forced); if(this.isr != null) { this.isr.stopRunning(); @@ -387,7 +414,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn _log.debug(getPrefix(requestId) + "First line [" + line + "]"); } - String[] params = line.split(" ", 3); + String[] params = DataHelper.split(line, " ", 3); if(params.length != 3) { break; } @@ -464,10 +491,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(_log.shouldLog(Log.WARN)) { _log.warn(getPrefix(requestId) + "Bad request [" + request + "]", use); } - out.write(getErrorPage("baduri", ERR_BAD_URI)); - writeFooter(out); - reader.drain(); - s.close(); + try { + out.write(getErrorPage("baduri", ERR_BAD_URI).getBytes("UTF-8")); + writeFooter(out); + reader.drain(); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } @@ -596,12 +628,20 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(_log.shouldLog(Log.WARN)) { _log.warn(getPrefix(requestId) + "Could not find destination for " + ahelperKey); } - byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND); - out.write(header); - out.write(("

" + _("This seems to be a bad destination:") + " " + ahelperKey + " " + _("i2paddresshelper cannot help you with a destination like that!") + "

").getBytes("UTF-8")); - writeFooter(out); - // XXX: should closeSocket(s) be in a finally block? - closeSocket(s); + String header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND); + try { + out.write(header.getBytes("UTF-8")); + out.write(("

" + _t("This seems to be a bad destination:") + " " + ahelperKey + " " + + _t("i2paddresshelper cannot help you with a destination like that!") + + "

").getBytes("UTF-8")); + writeFooter(out); + reader.drain(); + // XXX: should closeSocket(s) be in a finally block? + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } ahelperKey = _dest.toBase64(); @@ -614,7 +654,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // Store in local HashMap unless there is conflict String old = addressHelpers.putIfAbsent(destination.toLowerCase(Locale.US), ahelperKey); ahelperNew = old == null; - if((!ahelperNew) && !old.equals(ahelperKey)) { + // inr address helper links without trailing '=', so omit from comparison + if ((!ahelperNew) && !old.replace("=", "").equals(ahelperKey.replace("=", ""))) { // Conflict: handle when URL reconstruction done ahelperConflict = true; if(_log.shouldLog(Log.WARN)) { @@ -644,11 +685,12 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // Did addresshelper key conflict? if(ahelperConflict) { + try { // convert ahelperKey to b32 String alias = getHostName(ahelperKey); if(alias.equals("i2p")) { // bad ahelperKey - byte[] header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN); + String header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN); writeErrorMessage(header, out, targetRequest, false, destination); } else { String trustedURL = requestURI.toASCIIString(); @@ -662,14 +704,19 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn break; } String conflictURL = conflictURI.toASCIIString(); - byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT); - out.write(header); - out.write(_("To visit the destination in your host database, click here. To visit the conflicting addresshelper destination, click here.", trustedURL, conflictURL).getBytes("UTF-8")); - out.write(("

").getBytes()); + String header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT); + out.write(header.getBytes("UTF-8")); + out.write(_t("To visit the destination in your host database, click here. To visit the conflicting addresshelper destination, click here.", + trustedURL, conflictURL).getBytes("UTF-8")); + out.write("

".getBytes("UTF-8")); writeFooter(out); + } + reader.drain(); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); } - reader.drain(); - s.close(); return; } } // end query processing @@ -699,10 +746,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn } else if(hostLowerCase.equals("localhost") || host.equals("127.0.0.1") || host.startsWith("192.168.") || host.equals("[::1]")) { // if somebody is trying to get to 192.168.example.com, oh well - out.write(getErrorPage("localhost", ERR_LOCALHOST)); - writeFooter(out); - reader.drain(); - s.close(); + try { + out.write(getErrorPage("localhost", ERR_LOCALHOST).getBytes("UTF-8")); + writeFooter(out); + reader.drain(); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } else if(host.contains(".") || host.startsWith("[")) { if (Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USE_OUTPROXY_PLUGIN, "true"))) { @@ -747,10 +799,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn _log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!"); } l.log("No outproxy found for the request."); - out.write(getErrorPage("noproxy", ERR_NO_OUTPROXY)); - writeFooter(out); - reader.drain(); - s.close(); + try { + out.write(getErrorPage("noproxy", ERR_NO_OUTPROXY).getBytes("UTF-8")); + writeFooter(out); + reader.drain(); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } destination = currentProxy; @@ -768,10 +825,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(_log.shouldLog(Log.WARN)) { _log.warn("NODOTS, NOI2P: " + request); } - out.write(getErrorPage("denied", ERR_REQUEST_DENIED)); - writeFooter(out); - reader.drain(); - s.close(); + try { + out.write(getErrorPage("denied", ERR_REQUEST_DENIED).getBytes("UTF-8")); + writeFooter(out); + reader.drain(); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } // end host name processing @@ -819,7 +881,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn } else if(lowercaseLine.startsWith("accept")) { // strip the accept-blah headers, as they vary dramatically from // browser to browser - if(!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_ACCEPT))) { + // But allow Accept-Encoding: gzip, deflate + if(!lowercaseLine.startsWith("accept-encoding: ") && + !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_ACCEPT))) { line = null; continue; } @@ -871,8 +935,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn // according to rfc2616 s14.3, this *should* force identity, even if // an explicit q=0 for gzip doesn't. tested against orion.i2p, and it // seems to work. - if(!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_ACCEPT))) - newRequest.append("Accept-Encoding: \r\n"); + //if (!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_ACCEPT))) + // newRequest.append("Accept-Encoding: \r\n"); if (!usingInternalOutproxy) newRequest.append("X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n"); } @@ -897,7 +961,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW); } if(user != null && pw != null) { - newRequest.append("Proxy-Authorization: Basic ").append(Base64.encode((user + ':' + pw).getBytes(), true)) // true = use standard alphabet + newRequest.append("Proxy-Authorization: Basic ") + .append(Base64.encode((user + ':' + pw).getBytes("UTF-8"), true)) // true = use standard alphabet .append("\r\n"); } } @@ -914,13 +979,18 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(method == null || (destination == null && !usingInternalOutproxy)) { //l.log("No HTTP method found in the request."); - if (protocol != null && "http".equals(protocol.toLowerCase(Locale.US))) { - out.write(getErrorPage("denied", ERR_REQUEST_DENIED)); - } else { - out.write(getErrorPage("protocol", ERR_BAD_PROTOCOL)); + try { + if (protocol != null && "http".equals(protocol.toLowerCase(Locale.US))) { + out.write(getErrorPage("denied", ERR_REQUEST_DENIED).getBytes("UTF-8")); + } else { + out.write(getErrorPage("protocol", ERR_BAD_PROTOCOL).getBytes("UTF-8")); + } + writeFooter(out); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); } - writeFooter(out); - s.close(); return; } @@ -938,23 +1008,33 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn _log.warn(getPrefix(requestId) + "Auth required, sending 407"); } } - out.write(getAuthError(result == AuthResult.AUTH_STALE).getBytes()); - writeFooter(out); - s.close(); + try { + out.write(getAuthError(result == AuthResult.AUTH_STALE).getBytes("UTF-8")); + writeFooter(out); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } // Serve local proxy files (images, css linked from error pages) // Ignore all the headers - if(usingInternalServer) { - // disable the add form if address helper is disabled - if(internalPath.equals("/add") && - Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) { - out.write(ERR_HELPER_DISABLED); - } else { - LocalHTTPServer.serveLocalFile(out, method, internalPath, internalRawQuery, _proxyNonce); + if (usingInternalServer) { + try { + // disable the add form if address helper is disabled + if(internalPath.equals("/add") && + Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) { + out.write(ERR_HELPER_DISABLED.getBytes("UTF-8")); + } else { + LocalHTTPServer.serveLocalFile(out, method, internalPath, internalRawQuery, _proxyNonce); + } + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); } - s.close(); return; } @@ -966,13 +1046,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn byte[] response; if (method.toUpperCase(Locale.US).equals("CONNECT")) { data = null; - response = SUCCESS_RESPONSE; + response = SUCCESS_RESPONSE.getBytes("UTF-8"); } else { data = newRequest.toString().getBytes("ISO-8859-1"); response = null; } Thread t = new I2PTunnelOutproxyRunner(s, outSocket, sockLock, data, response, onTimeout); - t.start(); + // we are called from an unlimited thread pool, so run inline + //t.start(); + t.run(); return; } @@ -990,9 +1072,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(_log.shouldLog(Log.WARN)) { _log.warn(getPrefix(requestId) + "Could not find destination for " + addressHelper); } - byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND); - writeErrorMessage(header, out, targetRequest, false, destination); - s.close(); + String header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND); + try { + writeErrorMessage(header, out, targetRequest, false, destination); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } } else if("i2p".equals(host)) { @@ -1022,7 +1109,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(_log.shouldLog(Log.WARN)) { _log.warn("Unable to resolve " + destination + " (proxy? " + usingWWWProxy + ", request: " + targetRequest); } - byte[] header; + String header; String jumpServers = null; String extraMessage = null; if(usingWWWProxy) { @@ -1031,7 +1118,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN); } else if(destination.length() == 60 && destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) { header = getErrorPage("nols", ERR_DESTINATION_UNKNOWN); - extraMessage = _("Destination lease set not found"); + extraMessage = _t("Destination lease set not found"); } else { header = getErrorPage("dnfh", ERR_DESTINATION_UNKNOWN); jumpServers = getTunnel().getClientOptions().getProperty(PROP_JUMP_SERVERS); @@ -1039,16 +1126,26 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn jumpServers = DEFAULT_JUMP_SERVERS; } } - writeErrorMessage(header, extraMessage, out, targetRequest, usingWWWProxy, destination, jumpServers); - s.close(); + try { + writeErrorMessage(header, extraMessage, out, targetRequest, usingWWWProxy, destination, jumpServers); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } if (method.toUpperCase(Locale.US).equals("CONNECT") && !usingWWWProxy && !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_INTERNAL_SSL))) { - writeErrorMessage(ERR_INTERNAL_SSL, out, targetRequest, false, destination); - s.close(); + try { + writeErrorMessage(ERR_INTERNAL_SSL, out, targetRequest, false, destination); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } if (_log.shouldLog(Log.WARN)) _log.warn("SSL to i2p destinations denied by configuration: " + targetRequest); return; @@ -1060,8 +1157,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(ahelperNew && "GET".equals(method) && (userAgent == null || !userAgent.startsWith("Wget")) && !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) { - writeHelperSaveForm(out, destination, ahelperKey, targetRequest, referer); - s.close(); + try { + writeHelperSaveForm(out, destination, ahelperKey, targetRequest, referer); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } @@ -1074,10 +1176,17 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn if(_log.shouldLog(Log.DEBUG)) { _log.debug("Auto redirecting to " + uri); } - out.write(("HTTP/1.1 301 Address Helper Accepted\r\n" + + try { + out.write(("HTTP/1.1 301 Address Helper Accepted\r\n" + "Location: " + uri + "\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n").getBytes("UTF-8")); - s.close(); + } catch (IOException ioe) { + // ignore + } finally { + closeSocket(s); + } return; } @@ -1091,6 +1200,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn sktOpts.setPort(remotePort); I2PSocket i2ps = createI2PSocket(clientDest, sktOpts); OnTimeout onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId); + Thread t; if (method.toUpperCase(Locale.US).equals("CONNECT")) { byte[] data; byte[] response; @@ -1099,15 +1209,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn response = null; } else { data = null; - response = SUCCESS_RESPONSE; + response = SUCCESS_RESPONSE.getBytes("UTF-8"); } - Thread t = new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout); - t.start(); + t = new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout); } else { byte[] data = newRequest.toString().getBytes("ISO-8859-1"); - Thread t = new I2PTunnelHTTPClientRunner(s, i2ps, sockLock, data, mySockets, onTimeout); - t.start(); + t = new I2PTunnelHTTPClientRunner(s, i2ps, sockLock, data, mySockets, onTimeout); } + // we are called from an unlimited thread pool, so run inline + //t.start(); + t.run(); } catch(IOException ex) { if(_log.shouldLog(Log.INFO)) { _log.info(getPrefix(requestId) + "Error trying to connect", ex); @@ -1141,7 +1252,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn String s = getTunnel().getClientOptions().getProperty(PROP_SSL_OUTPROXIES); if (s == null) return null; - String[] p = s.split(", "); + String[] p = DataHelper.split(s, "[,; \r\n\t]"); if (p.length == 0) return null; // todo doesn't check for "" @@ -1152,44 +1263,45 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn } /** @since 0.8.7 */ - private void writeHelperSaveForm(OutputStream out, String destination, String ahelperKey, + private void writeHelperSaveForm(OutputStream outs, String destination, String ahelperKey, String targetRequest, String referer) throws IOException { - if(out == null) { + if(outs == null) return; - } - byte[] header = getErrorPage("ahelper-new", ERR_AHELPER_NEW); + Writer out = new BufferedWriter(new OutputStreamWriter(outs, "UTF-8")); + String header = getErrorPage("ahelper-new", ERR_AHELPER_NEW); out.write(header); - out.write(("\n").getBytes()); + out.write("
" + _("Host") + - "" + destination + "
\n"); try { String b32 = Base32.encode(SHA256Generator.getInstance().calculateHash(Base64.decode(ahelperKey)).getData()); - out.write(("" + - "").getBytes()); + out.write("" + + ""); } catch(Exception e) { } - out.write(("
" + _t("Host") + + "" + destination + "
" + _("Base 32") + "" + b32 + ".b32.i2p
" + _t("Base 32") + "" + b32 + ".b32.i2p
" + _("Destination") + "" + + out.write("
" + _t("Destination") + "" + "
\n" + "
" + // FIXME if there is a query remaining it is lost "
" + - "" + + "" + "
\n
" + "\n" + "\n" + "\n" + - "
\n").getBytes("UTF-8")); + "
\n"); if(_context.namingService().getName().equals("BlockfileNamingService")) { // only blockfile supports multiple books - out.write(("

\n").getBytes("UTF-8")); - out.write(("\n").getBytes("UTF-8")); + out.write("

\n"); + out.write("\n"); } // Firefox (and others?) don't send referer to meta refresh target, which is // what the jump servers use, so this isn't that useful. if (referer != null) - out.write(("\n").getBytes("UTF-8")); - out.write(("\n" + - "
").getBytes()); + out.write("\n"); + out.write("\n" + + ""); writeFooter(out); } @@ -1291,11 +1403,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn return lc.equals("http") || lc.equals("https"); } - private final static byte[] ERR_HELPER_DISABLED = - ("HTTP/1.1 403 Disabled\r\n" + + private final static String ERR_HELPER_DISABLED = + "HTTP/1.1 403 Disabled\r\n" + "Content-Type: text/plain\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + - "Address helpers disabled").getBytes(); + "Address helpers disabled"; /** * Change various parts of the URI. @@ -1384,7 +1498,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn } keystart = i + 1; valstart = -1; - } else if(c == '=') { + } else if (c == '=' && valstart < 0) { // end of key key = query.substring(keystart, i); valstart = i + 1; @@ -1394,28 +1508,33 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn } /**** private static String[] tests = { - "", "foo", "foo=bar", "&", "&=&", "===", "&&", - "i2paddresshelper=foo", - "i2paddresshelpe=foo", - "2paddresshelper=foo", - "i2paddresshelper=%66oo", - "%692paddresshelper=foo", - "i2paddresshelper=foo&a=b", - "a=b&i2paddresshelper=foo", - "a=b&i2paddresshelper&c=d", - "a=b&i2paddresshelper=foo&c=d", - "a=b;i2paddresshelper=foo;c=d", - "a=b&i2paddresshelper=foo&c" + "", "foo", "foo=bar", "&", "&=&", "===", "&&", + "i2paddresshelper=foo", + "i2paddresshelpe=foo", + "2paddresshelper=foo", + "i2paddresshelper=%66oo", + "%692paddresshelper=foo", + "i2paddresshelper=foo&a=b", + "a=b&i2paddresshelper=foo", + "a=b&i2paddresshelper&c=d", + "a=b&i2paddresshelper=foo&c=d", + "a=b;i2paddresshelper=foo;c=d", + "a=b&i2paddresshelper=foo&c", + "a=b&i2paddresshelper=foo==&c", + "a=b&i2paddresshelper=foo%3d%3d&c", + "a=b&i2paddresshelper=f%6f%6F==&c", + "a=b&i2paddresshelper=foo&i2paddresshelper=bar&c", + "a=b&i2paddresshelper=foo&c%3F%3f%26%3b%3B%3d%3Dc=x%3F%3f%26%3b%3B%3d%3Dx" }; public static void main(String[] args) { - for (int i = 0; i < tests.length; i++) { - String[] s = removeHelper(tests[i]); - if (s != null) - System.out.println("Test \"" + tests[i] + "\" q=\"" + s[0] + "\" h=\"" + s[1] + "\""); - else - System.out.println("Test \"" + tests[i] + "\" no match"); - } + for (int i = 0; i < tests.length; i++) { + String[] s = removeHelper(tests[i]); + if (s != null) + System.out.println("Test \"" + tests[i] + "\" q=\"" + s[0] + "\" h=\"" + s[1] + "\""); + else + System.out.println("Test \"" + tests[i] + "\" no match"); + } } ****/ } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java index 4813fa2a1..e68e38d6b 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientBase.java @@ -3,12 +3,15 @@ */ package net.i2p.i2ptunnel; +import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.Reader; import java.io.UnsupportedEncodingException; +import java.io.Writer; import java.net.Socket; import java.net.URI; import java.net.URISyntaxException; @@ -60,6 +63,8 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem "HTTP/1.1 407 Proxy Authentication Required\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.5\r\n" + // try to get a UTF-8-encoded response back for the password "Proxy-Authenticate: "; // put the auth type and realm in between @@ -71,33 +76,35 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem protected final List _proxyList; - protected final static byte[] ERR_NO_OUTPROXY = - ("HTTP/1.1 503 Service Unavailable\r\n"+ + protected final static String ERR_NO_OUTPROXY = + "HTTP/1.1 503 Service Unavailable\r\n"+ "Content-Type: text/html; charset=iso-8859-1\r\n"+ "Cache-control: no-cache\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n"+ "

I2P ERROR: No outproxy found

"+ "Your request was for a site outside of I2P, but you have no "+ - "HTTP outproxy configured. Please configure an outproxy in I2PTunnel") - .getBytes(); + "HTTP outproxy configured. Please configure an outproxy in I2PTunnel"; - protected final static byte[] ERR_DESTINATION_UNKNOWN = - ("HTTP/1.1 503 Service Unavailable\r\n" + + protected final static String ERR_DESTINATION_UNKNOWN = + "HTTP/1.1 503 Service Unavailable\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n" + "Cache-control: no-cache\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n" + "

I2P ERROR: DESTINATION NOT FOUND

" + "That I2P Destination was not found. Perhaps you pasted in the " + "wrong BASE64 I2P Destination or the link you are following is " + "bad. The host (or the WWW proxy, if you're using one) could also " + "be temporarily offline. You may want to retry. " + - "Could not find the following Destination:

").getBytes(); + "Could not find the following Destination:

"; - protected final static byte[] SUCCESS_RESPONSE = - ("HTTP/1.1 200 Connection Established\r\n"+ + protected final static String SUCCESS_RESPONSE = + "HTTP/1.1 200 Connection Established\r\n"+ "Proxy-agent: I2P\r\n"+ - "\r\n") - .getBytes(); + "\r\n"; private final byte[] _proxyNonce; private final ConcurrentHashMap _nonces; @@ -214,11 +221,14 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem // see TunnelController.setSessionOptions() String proxies = props.getProperty("proxyList"); if (proxies != null) { - StringTokenizer tok = new StringTokenizer(proxies, ", "); + StringTokenizer tok = new StringTokenizer(proxies, ",; \r\n\t"); synchronized(_proxyList) { _proxyList.clear(); - while (tok.hasMoreTokens()) - _proxyList.add(tok.nextToken().trim()); + while (tok.hasMoreTokens()) { + String p = tok.nextToken().trim(); + if (p.length() > 0) + _proxyList.add(p); + } } } else { synchronized(_proxyList) { @@ -275,7 +285,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem // We send Accept-Charset: UTF-8 in the 407 so hopefully it comes back that way inside the B64 ? try { String dec = new String(decoded, "UTF-8"); - String[] parts = dec.split(":"); + String[] parts = DataHelper.split(dec, ":"); String user = parts[0]; String pw = parts[1]; // first try pw for that user @@ -484,7 +494,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem * @return non-null * @since 0.9.4 moved from I2PTunnelHTTPClient */ - protected byte[] getErrorPage(String base, byte[] backup) { + protected String getErrorPage(String base, String backup) { return getErrorPage(_context, base, backup); } @@ -499,7 +509,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem * @return non-null * @since 0.9.4 moved from I2PTunnelHTTPClient */ - protected static byte[] getErrorPage(I2PAppContext ctx, String base, byte[] backup) { + protected static String getErrorPage(I2PAppContext ctx, String base, String backup) { File errorDir = new File(ctx.getBaseDir(), "docs"); File file = new File(errorDir, base + "-header.ht"); try { @@ -515,7 +525,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem /** * @since 0.9.4 moved from I2PTunnelHTTPClient */ - private static byte[] readFile(I2PAppContext ctx, File file) throws IOException { + private static String readFile(I2PAppContext ctx, File file) throws IOException { Reader reader = null; char[] buf = new char[512]; StringBuilder out = new StringBuilder(2048); @@ -525,7 +535,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem while((len = reader.read(buf)) > 0) { out.append(buf, 0, len); } - return out.toString().getBytes("UTF-8"); + return out.toString(); } finally { try { if(reader != null) @@ -578,7 +588,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem boolean usingWWWProxy, String wwwProxy, long requestId) { if (out == null) return; - byte[] header; + String header; if (usingWWWProxy) header = getErrorPage(I2PAppContext.getGlobalContext(), "dnfp", ERR_DESTINATION_UNKNOWN); else @@ -601,13 +611,18 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem return; int status = ise != null ? ise.getStatus() : -1; String error; - //TODO MessageStatusMessage.STATUS_SEND_FAILURE_UNSUPPORTED_ENCRYPTION if (status == MessageStatusMessage.STATUS_SEND_FAILURE_NO_LEASESET) { + // We won't get this one unless it is treated as a hard failure + // in streaming. See PacketQueue.java error = usingWWWProxy ? "nolsp" : "nols"; + } else if (status == MessageStatusMessage.STATUS_SEND_FAILURE_UNSUPPORTED_ENCRYPTION) { + error = usingWWWProxy ? "encp" : "enc"; + } else if (status == I2PSocketException.STATUS_CONNECTION_RESET) { + error = usingWWWProxy ? "resetp" : "reset"; } else { error = usingWWWProxy ? "dnfp" : "dnf"; } - byte[] header = getErrorPage(error, ERR_DESTINATION_UNKNOWN); + String header = getErrorPage(error, ERR_DESTINATION_UNKNOWN); String message = ise != null ? ise.getLocalizedMessage() : "unknown error"; try { writeErrorMessage(header, message, out, targetRequest, usingWWWProxy, wwwProxy); @@ -618,7 +633,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem * No jump servers or extra message * @since 0.9.14 */ - protected void writeErrorMessage(byte[] errMessage, OutputStream out, String targetRequest, + protected void writeErrorMessage(String errMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy) throws IOException { writeErrorMessage(errMessage, null, out, targetRequest, usingWWWProxy, wwwProxy, null); } @@ -628,17 +643,17 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem * @param jumpServers comma- or space-separated list, or null * @since 0.9.14 moved from subclasses */ - protected void writeErrorMessage(byte[] errMessage, OutputStream out, String targetRequest, + protected void writeErrorMessage(String errMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy, String jumpServers) throws IOException { writeErrorMessage(errMessage, null, out, targetRequest, usingWWWProxy, wwwProxy, jumpServers); } /** * No jump servers - * @param extraMessage extra message + * @param extraMessage extra message or null, will be HTML-escaped * @since 0.9.14 */ - protected void writeErrorMessage(byte[] errMessage, String extraMessage, + protected void writeErrorMessage(String errMessage, String extraMessage, OutputStream out, String targetRequest, boolean usingWWWProxy, String wwwProxy) throws IOException { writeErrorMessage(errMessage, extraMessage, out, targetRequest, usingWWWProxy, wwwProxy, null); @@ -646,30 +661,34 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem /** * @param jumpServers comma- or space-separated list, or null - * @param extraMessage extra message + * @param extraMessage extra message or null, will be HTML-escaped * @since 0.9.14 */ - protected void writeErrorMessage(byte[] errMessage, String extraMessage, - OutputStream out, String targetRequest, + protected void writeErrorMessage(String errMessage, String extraMessage, + OutputStream outs, String targetRequest, boolean usingWWWProxy, String wwwProxy, String jumpServers) throws IOException { - if (out == null) + if (outs == null) return; + Writer out = new BufferedWriter(new OutputStreamWriter(outs, "UTF-8")); out.write(errMessage); if (targetRequest != null) { - String uri = targetRequest.replace("&", "&"); - out.write("".getBytes()); - out.write(uri.getBytes()); - out.write("".getBytes()); + String uri = DataHelper.escapeHTML(targetRequest); + out.write(""); + if (targetRequest.length() > 80) + out.write(DataHelper.escapeHTML(targetRequest.substring(0, 75)) + "…"); + else + out.write(uri); + out.write(""); if (usingWWWProxy) { - out.write(("

").getBytes()); - out.write(_("HTTP Outproxy").getBytes("UTF-8")); - out.write((": " + wwwProxy).getBytes()); + out.write("

"); + out.write(_t("HTTP Outproxy")); + out.write(": " + wwwProxy); } if (extraMessage != null) { - out.write(("

" + extraMessage + "").getBytes()); + out.write("

" + DataHelper.escapeHTML(extraMessage) + ""); } if (jumpServers != null && jumpServers.length() > 0) { boolean first = true; @@ -703,21 +722,23 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem if (first) { first = false; - out.write("

".getBytes()); - out.write(_("Click a link below to look for an address helper by using a \"jump\" service:").getBytes("UTF-8")); - out.write("
\n".getBytes()); + out.write("

"); + out.write(_t("Click a link below for an address helper from a jump service")); + out.write("

\n"); + } else { + out.write("
"); } - out.write("
".getBytes()); + out.write(""); // Translators: parameter is a host name - out.write(_("{0} jump service", jumphost).getBytes()); - out.write("\n".getBytes()); + out.write(_t("{0} jump service", jumphost)); + out.write("\n"); } } } - out.write("
".getBytes()); + out.write("
"); writeFooter(out); } @@ -728,19 +749,36 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem * @since 0.9.14 moved from I2PTunnelHTTPClient */ public static void writeFooter(OutputStream out) throws IOException { + out.write(getFooter().getBytes("UTF-8")); + out.flush(); + } + + /** + * Flushes. + * + * Public only for LocalHTTPServer, not for general use + * @since 0.9.19 + */ + public static void writeFooter(Writer out) throws IOException { + out.write(getFooter()); + out.flush(); + } + + private static String getFooter() { // The css is hiding this div for now, but we'll keep it here anyway // Tag the strings below for translation if we unhide it. - out.write("

I2P HTTP Proxy Server
Generated on: ".getBytes()); - out.write(new Date().toString().getBytes()); - out.write("

\n".getBytes()); - out.flush(); + StringBuilder buf = new StringBuilder(128); + buf.append("

I2P HTTP Proxy Server
Generated on: ") + .append(new Date().toString()) + .append("

\n"); + return buf.toString(); } /** * Translate * @since 0.9.14 moved from I2PTunnelHTTPClient */ - protected String _(String key) { + protected String _t(String key) { return Translate.getString(key, _context, BUNDLE_NAME); } @@ -749,7 +787,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem * {0} * @since 0.9.14 moved from I2PTunnelHTTPClient */ - protected String _(String key, Object o) { + protected String _t(String key, Object o) { return Translate.getString(key, o, _context, BUNDLE_NAME); } @@ -758,7 +796,7 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem * {0} and {1} * @since 0.9.14 moved from I2PTunnelHTTPClient */ - protected String _(String key, Object o, Object o2) { + protected String _t(String key, Object o, Object o2) { return Translate.getString(key, o, o2, _context, BUNDLE_NAME); } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientRunner.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientRunner.java index e12b839d3..656b2c0f9 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientRunner.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClientRunner.java @@ -33,6 +33,9 @@ public class I2PTunnelHTTPClientRunner extends I2PTunnelRunner { super(s, i2ps, slock, initialI2PData, null, sockList, onFail); } + /** + * Only call once! + */ @Override protected OutputStream getSocketOut() throws IOException { OutputStream raw = super.getSocketOut(); @@ -86,7 +89,8 @@ public class I2PTunnelHTTPClientRunner extends I2PTunnelRunner { // ignore } t1.join(30*1000); - t2.join(30*1000); + // t2 = fromI2P now run inline + //t2.join(30*1000); } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java index 128b1565d..157a94011 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPServer.java @@ -4,6 +4,7 @@ package net.i2p.i2ptunnel; import java.io.BufferedInputStream; +import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -11,6 +12,7 @@ import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -63,14 +65,22 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { private static final String SERVER_HEADER = "Server"; private static final String X_POWERED_BY_HEADER = "X-Powered-By"; private static final String[] SERVER_SKIPHEADERS = {SERVER_HEADER, X_POWERED_BY_HEADER}; + /** timeout for first request line */ private static final long HEADER_TIMEOUT = 15*1000; + /** total timeout for the request and all the headers */ private static final long TOTAL_HEADER_TIMEOUT = 2 * HEADER_TIMEOUT; private static final long START_INTERVAL = (60 * 1000) * 3; + private static final int MAX_LINE_LENGTH = 8*1024; + /** ridiculously long, just to prevent OOM DOS @since 0.7.13 */ + private static final int MAX_HEADERS = 60; + /** Includes request, just to prevent OOM DOS @since 0.9.20 */ + private static final int MAX_TOTAL_HEADER_SIZE = 32*1024; + private long _startedOn = 0L; private ConnThrottler _postThrottler; - private final static byte[] ERR_UNAVAILABLE = - ("HTTP/1.1 503 Service Unavailable\r\n"+ + private final static String ERR_UNAVAILABLE = + "HTTP/1.1 503 Service Unavailable\r\n"+ "Content-Type: text/html; charset=iso-8859-1\r\n"+ "Cache-control: no-cache\r\n"+ "Connection: close\r\n"+ @@ -78,12 +88,11 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { "\r\n"+ "503 Service Unavailable\n"+ "

503 Service Unavailable

\n" + - "

This I2P eepsite is unavailable. It may be down or undergoing maintenance.

\n" + - "") - .getBytes(); + "

This I2P website is unavailable. It may be down or undergoing maintenance.

\n" + + ""; - private final static byte[] ERR_DENIED = - ("HTTP/1.1 403 Denied\r\n"+ + private final static String ERR_DENIED = + "HTTP/1.1 403 Denied\r\n"+ "Content-Type: text/html; charset=iso-8859-1\r\n"+ "Cache-control: no-cache\r\n"+ "Connection: close\r\n"+ @@ -92,11 +101,10 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { "403 Denied\n"+ "

403 Denied

\n" + "

Denied due to excessive requests. Please try again later.

\n" + - "") - .getBytes(); + ""; - private final static byte[] ERR_INPROXY = - ("HTTP/1.1 403 Denied\r\n"+ + private final static String ERR_INPROXY = + "HTTP/1.1 403 Denied\r\n"+ "Content-Type: text/html; charset=iso-8859-1\r\n"+ "Cache-control: no-cache\r\n"+ "Connection: close\r\n"+ @@ -105,8 +113,64 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { "403 Denied\n"+ "

403 Denied

\n" + "

Inproxy access denied. You must run I2P to access this site.

\n" + - "") - .getBytes(); + ""; + + private final static String ERR_SSL = + "HTTP/1.1 503 Service Unavailable\r\n"+ + "Content-Type: text/html; charset=iso-8859-1\r\n"+ + "Cache-control: no-cache\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ + "\r\n"+ + "503 Service Unavailable\n"+ + "

503 Service Unavailable

\n" + + "

This I2P website is not configured for SSL.

\n" + + ""; + + private final static String ERR_REQUEST_URI_TOO_LONG = + "HTTP/1.1 414 Request URI too long\r\n"+ + "Content-Type: text/html; charset=iso-8859-1\r\n"+ + "Cache-control: no-cache\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ + "\r\n"+ + "414 Request URI Too Long\n"+ + "

414 Request URI too long

\n" + + ""; + + private final static String ERR_HEADERS_TOO_LARGE = + "HTTP/1.1 431 Request header fields too large\r\n"+ + "Content-Type: text/html; charset=iso-8859-1\r\n"+ + "Cache-control: no-cache\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ + "\r\n"+ + "431 Request Header Fields Too Large\n"+ + "

431 Request header fields too large

\n" + + ""; + + private final static String ERR_REQUEST_TIMEOUT = + "HTTP/1.1 408 Request timeout\r\n"+ + "Content-Type: text/html; charset=iso-8859-1\r\n"+ + "Cache-control: no-cache\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ + "\r\n"+ + "408 Request Timeout\n"+ + "

408 Request timeout

\n" + + ""; + + private final static String ERR_BAD_REQUEST = + "HTTP/1.1 400 Bad Request\r\n"+ + "Content-Type: text/html; charset=iso-8859-1\r\n"+ + "Cache-control: no-cache\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ + "\r\n"+ + "400 Bad Request\n"+ + "

400 Bad request

\n" + + ""; + public I2PTunnelHTTPServer(InetAddress host, int port, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) { super(host, port, privData, l, notifyThis, tunnel); @@ -126,7 +190,6 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { private void setupI2PTunnelHTTPServer(String spoofHost) { _spoofHost = (spoofHost != null && spoofHost.trim().length() > 0) ? spoofHost.trim() : null; getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 }); - getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000 }); } @Override @@ -182,6 +245,10 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { if (getTunnel() != tunnel) return; setupPostThrottle(); + Properties props = tunnel.getClientOptions(); + // see TunnelController.setSessionOptions() + String spoofHost = props.getProperty(TunnelController.PROP_SPOOFED_HOST); + _spoofHost = (spoofHost != null && spoofHost.trim().length() > 0) ? spoofHost.trim() : null; super.optionsUpdated(tunnel); } @@ -199,16 +266,88 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { //local is fast, so synchronously. Does not need that many //threads. try { + if (socket.getLocalPort() == 443) { + if (getTunnel().getClientOptions().getProperty("targetForPort.443") == null) { + try { + socket.getOutputStream().write(ERR_SSL.getBytes("UTF-8")); + } catch (IOException ioe) { + } finally { + try { + socket.close(); + } catch (IOException ioe) {} + } + return; + } + Socket s = getSocket(socket.getPeerDestination().calculateHash(), 443); + Runnable t = new I2PTunnelRunner(s, socket, slock, null, null, + null, (I2PTunnelRunner.FailCallback) null); + _clientExecutor.execute(t); + return; + } + long afterAccept = getTunnel().getContext().clock().now(); + // The headers _should_ be in the first packet, but // may not be, depending on the client-side options - socket.setReadTimeout(HEADER_TIMEOUT); - - InputStream in = socket.getInputStream(); StringBuilder command = new StringBuilder(128); - Map> headers = readHeaders(in, command, - CLIENT_SKIPHEADERS, getTunnel().getContext()); + Map> headers; + try { + // catch specific exceptions thrown, to return a good + // error to the client + headers = readHeaders(socket, null, command, + CLIENT_SKIPHEADERS, getTunnel().getContext()); + } catch (SocketTimeoutException ste) { + try { + socket.getOutputStream().write(ERR_REQUEST_TIMEOUT.getBytes("UTF-8")); + } catch (IOException ioe) { + } finally { + try { socket.close(); } catch (IOException ioe) {} + } + if (_log.shouldLog(Log.WARN)) + _log.warn("Error while receiving the new HTTP request", ste); + return; + } catch (EOFException eofe) { + try { + socket.getOutputStream().write(ERR_BAD_REQUEST.getBytes("UTF-8")); + } catch (IOException ioe) { + } finally { + try { socket.close(); } catch (IOException ioe) {} + } + if (_log.shouldLog(Log.WARN)) + _log.warn("Error while receiving the new HTTP request", eofe); + return; + } catch (LineTooLongException ltle) { + try { + socket.getOutputStream().write(ERR_HEADERS_TOO_LARGE.getBytes("UTF-8")); + } catch (IOException ioe) { + } finally { + try { socket.close(); } catch (IOException ioe) {} + } + if (_log.shouldLog(Log.WARN)) + _log.warn("Error while receiving the new HTTP request", ltle); + return; + } catch (RequestTooLongException rtle) { + try { + socket.getOutputStream().write(ERR_REQUEST_URI_TOO_LONG.getBytes("UTF-8")); + } catch (IOException ioe) { + } finally { + try { socket.close(); } catch (IOException ioe) {} + } + if (_log.shouldLog(Log.WARN)) + _log.warn("Error while receiving the new HTTP request", rtle); + return; + } catch (BadRequestException bre) { + try { + socket.getOutputStream().write(ERR_BAD_REQUEST.getBytes("UTF-8")); + } catch (IOException ioe) { + } finally { + try { socket.close(); } catch (IOException ioe) {} + } + if (_log.shouldLog(Log.WARN)) + _log.warn("Error while receiving the new HTTP request", bre); + return; + } long afterHeaders = getTunnel().getContext().clock().now(); Properties opts = getTunnel().getClientOptions(); @@ -216,12 +355,24 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { (headers.containsKey("X-Forwarded-For") || headers.containsKey("X-Forwarded-Server") || headers.containsKey("X-Forwarded-Host"))) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Refusing inproxy access: " + peerHash.toBase64()); + if (_log.shouldLog(Log.WARN)) { + StringBuilder buf = new StringBuilder(); + buf.append("Refusing inproxy access: ").append(peerHash.toBase64()); + List h = headers.get("X-Forwarded-For"); + if (h != null) + buf.append(" from: ").append(h.get(0)); + h = headers.get("X-Forwarded-Server"); + if (h != null) + buf.append(" via: ").append(h.get(0)); + h = headers.get("X-Forwarded-Host"); + if (h != null) + buf.append(" for: ").append(h.get(0)); + _log.warn(buf.toString()); + } try { // Send a 403, so the user doesn't get an HTTP Proxy error message // and blame his router or the network. - socket.getOutputStream().write(ERR_INPROXY); + socket.getOutputStream().write(ERR_INPROXY.getBytes("UTF-8")); } catch (IOException ioe) {} try { socket.close(); @@ -238,7 +389,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { try { // Send a 403, so the user doesn't get an HTTP Proxy error message // and blame his router or the network. - socket.getOutputStream().write(ERR_DENIED); + socket.getOutputStream().write(ERR_DENIED.getBytes("UTF-8")); } catch (IOException ioe) {} try { socket.close(); @@ -268,12 +419,14 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { setEntry(headers, "Connection", "close"); // we keep the enc sent by the browser before clobbering it, since it may have // been x-i2p-gzip - String enc = getEntryOrNull(headers, "Accept-encoding"); - String altEnc = getEntryOrNull(headers, "X-Accept-encoding"); + String enc = getEntryOrNull(headers, "Accept-Encoding"); + String altEnc = getEntryOrNull(headers, "X-Accept-Encoding"); // according to rfc2616 s14.3, this *should* force identity, even if // "identity;q=1, *;q=0" didn't. - setEntry(headers, "Accept-encoding", ""); + // as of 0.9.23, the client passes this header through, and we do the same, + // so if the server and browser can do the compression/decompression, we don't have to + //setEntry(headers, "Accept-Encoding", ""); socket.setReadTimeout(readTimeout); Socket s = getSocket(socket.getPeerDestination().calculateHash(), socket.getLocalPort()); @@ -281,7 +434,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { // instead of i2ptunnelrunner, use something that reads the HTTP // request from the socket, modifies the headers, sends the request to the // server, reads the response headers, rewriting to include Content-encoding: x-i2p-gzip - // if it was one of the Accept-encoding: values, and gzip the payload + // if it was one of the Accept-Encoding: values, and gzip the payload boolean allowGZIP = true; String val = opts.getProperty("i2ptunnel.gzip"); if ( (val != null) && (!Boolean.parseBoolean(val)) ) @@ -292,26 +445,26 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { boolean useGZIP = alt || ( (enc != null) && (enc.indexOf("x-i2p-gzip") >= 0) ); // Don't pass this on, outproxies should strip so I2P traffic isn't so obvious but they probably don't if (alt) - headers.remove("X-Accept-encoding"); + headers.remove("X-Accept-Encoding"); String modifiedHeader = formatHeaders(headers, command); if (_log.shouldLog(Log.DEBUG)) _log.debug("Modified header: [" + modifiedHeader + "]"); + Runnable t; if (allowGZIP && useGZIP) { - I2PAppThread req = new I2PAppThread( - new CompressedRequestor(s, socket, modifiedHeader, getTunnel().getContext(), _log), - Thread.currentThread().getName()+".hc"); - req.start(); + t = new CompressedRequestor(s, socket, modifiedHeader, getTunnel().getContext(), _log); } else { - Thread t = new I2PTunnelRunner(s, socket, slock, null, modifiedHeader.getBytes(), + t = new I2PTunnelRunner(s, socket, slock, null, DataHelper.getUTF8(modifiedHeader), null, (I2PTunnelRunner.FailCallback) null); - t.start(); } + // run in the unlimited client pool + //t.start(); + _clientExecutor.execute(t); long afterHandle = getTunnel().getContext().clock().now(); long timeToHandle = afterHandle - afterAccept; - getTunnel().getContext().statManager().addRateData("i2ptunnel.httpserver.blockingHandleTime", timeToHandle, 0); + getTunnel().getContext().statManager().addRateData("i2ptunnel.httpserver.blockingHandleTime", timeToHandle); if ( (timeToHandle > 1000) && (_log.shouldLog(Log.WARN)) ) _log.warn("Took a while to handle the request for " + remoteHost + ':' + remotePort + " [" + timeToHandle + @@ -323,7 +476,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { try { // Send a 503, so the user doesn't get an HTTP Proxy error message // and blame his router or the network. - socket.getOutputStream().write(ERR_UNAVAILABLE); + socket.getOutputStream().write(ERR_UNAVAILABLE.getBytes("UTF-8")); } catch (IOException ioe) {} try { socket.close(); @@ -344,7 +497,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { try { // Send a 503, so the user doesn't get an HTTP Proxy error message // and blame his router or the network. - socket.getOutputStream().write(ERR_UNAVAILABLE); + socket.getOutputStream().write(ERR_UNAVAILABLE.getBytes("UTF-8")); } catch (IOException ioe) {} try { socket.close(); @@ -384,7 +537,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { if (_log.shouldLog(Log.INFO)) _log.info("request headers: " + _headers); - serverout.write(_headers.getBytes()); + serverout.write(DataHelper.getUTF8(_headers)); browserin = _browser.getInputStream(); // Don't spin off a thread for this except for POSTs // beware interference with Shoutcast, etc.? @@ -419,10 +572,10 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { //Change headers to protect server identity StringBuilder command = new StringBuilder(128); - Map> headers = readHeaders(serverin, command, + Map> headers = readHeaders(null, serverin, command, SERVER_SKIPHEADERS, _ctx); String modifiedHeaders = formatHeaders(headers, command); - compressedOut.write(modifiedHeaders.getBytes()); + compressedOut.write(DataHelper.getUTF8(modifiedHeaders)); Sender s = new Sender(compressedOut, serverin, "server: server to browser", _log); if (_log.shouldLog(Log.INFO)) @@ -435,7 +588,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { try { if (browserout == null) browserout = _browser.getOutputStream(); - browserout.write(ERR_UNAVAILABLE); + browserout.write(ERR_UNAVAILABLE.getBytes("UTF-8")); } catch (IOException ioe) {} } catch (IOException ioe) { if (_log.shouldLog(Log.WARN)) @@ -511,7 +664,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { */ @Override protected String filterResponseLine(String line) { - String[] s = line.split(" ", 3); + String[] s = DataHelper.split(line, " ", 3); if (s.length > 1 && (s[1].startsWith("3") || s[1].startsWith("5"))) _dataExpected = 0; @@ -520,6 +673,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { /** * Don't compress small responses or images. + * Don't compress things that are already compressed. * Compression is inline but decompression on the client side * creates a new thread. */ @@ -536,7 +690,11 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { (!_contentType.equals("application/x-bzip")) && (!_contentType.equals("application/x-bzip2")) && (!_contentType.equals("application/x-gzip")) && - (!_contentType.equals("application/zip")))); + (!_contentType.equals("application/zip")))) && + (_contentEncoding == null || + ((!_contentEncoding.equals("gzip")) && + (!_contentEncoding.equals("compress")) && + (!_contentEncoding.equals("deflate")))); } @Override @@ -544,7 +702,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { //if (_log.shouldLog(Log.INFO)) // _log.info("Including x-i2p-gzip as the content encoding in the response"); if (shouldCompress()) - out.write("Content-encoding: x-i2p-gzip\r\n".getBytes()); + out.write(DataHelper.getASCII("Content-encoding: x-i2p-gzip\r\n")); super.finishHeaders(); } @@ -584,7 +742,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { public long getTotalRead() { try { return def.getTotalIn(); - } catch (Exception e) { + } catch (RuntimeException e) { // j2se 1.4.2_08 on linux is sometimes throwing an NPE in the getTotalIn() implementation return 0; } @@ -592,7 +750,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { public long getTotalCompressed() { try { return def.getTotalOut(); - } catch (Exception e) { + } catch (RuntimeException e) { // j2se 1.4.2_08 on linux is sometimes throwing an NPE in the getTotalOut() implementation return 0; } @@ -615,9 +773,6 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { return buf.toString(); } - /** ridiculously long, just to prevent OOM DOS @since 0.7.13 */ - private static final int MAX_HEADERS = 60; - /** * Add an entry to the multimap. */ @@ -655,49 +810,71 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { } } - protected static Map> readHeaders(InputStream in, StringBuilder command, + /** + * From I2P to server: socket non-null, in null. + * From server to I2P: socket null, in non-null. + * + * @param socket if null, use in as InputStream + * @param in if null, use socket.getInputStream() as InputStream + * @param command out parameter, first line + * @throws SocketTimeoutException if timeout is reached before newline + * @throws EOFException if EOF is reached before newline + * @throws LineTooLongException if one header too long, or too many headers, or total size too big + * @throws RequestTooLongException if too long + * @throws BadRequestException on bad headers + * @throws IOException on other errors in the underlying stream + */ + static Map> readHeaders(I2PSocket socket, InputStream in, StringBuilder command, String[] skipHeaders, I2PAppContext ctx) throws IOException { HashMap> headers = new HashMap>(); StringBuilder buf = new StringBuilder(128); // slowloris / darkloris long expire = ctx.clock().now() + TOTAL_HEADER_TIMEOUT; - boolean ok = DataHelper.readLine(in, command); - if (!ok) throw new IOException("EOF reached while reading the HTTP command [" + command.toString() + "]"); + if (socket != null) { + try { + readLine(socket, command, HEADER_TIMEOUT); + } catch (LineTooLongException ltle) { + // convert for first line + throw new RequestTooLongException("Request too long - max " + MAX_LINE_LENGTH); + } + } else { + boolean ok = DataHelper.readLine(in, command); + if (!ok) + throw new EOFException("EOF reached before the end of the headers"); + } //if (_log.shouldLog(Log.DEBUG)) // _log.debug("Read the http command [" + command.toString() + "]"); - // FIXME we probably don't need or want this in the outgoing direction - int trimmed = 0; - if (command.length() > 0) { - for (int i = 0; i < command.length(); i++) { - if (command.charAt(i) == 0) { - command = command.deleteCharAt(i); - i--; - trimmed++; - } - } - } - if (trimmed > 0) - ctx.statManager().addRateData("i2ptunnel.httpNullWorkaround", trimmed, 0); - + int totalSize = command.length(); int i = 0; while (true) { - if (++i > MAX_HEADERS) - throw new IOException("Too many header lines - max " + MAX_HEADERS); + if (++i > MAX_HEADERS) { + throw new LineTooLongException("Too many header lines - max " + MAX_HEADERS); + } buf.setLength(0); - ok = DataHelper.readLine(in, buf); - if (!ok) throw new IOException("EOF reached before the end of the headers [" + buf.toString() + "]"); + if (socket != null) { + readLine(socket, buf, expire - ctx.clock().now()); + } else { + boolean ok = DataHelper.readLine(in, buf); + if (!ok) + throw new BadRequestException("EOF reached before the end of the headers"); + } if ( (buf.length() == 0) || ((buf.charAt(0) == '\n') || (buf.charAt(0) == '\r')) ) { // end of headers reached return headers; } else { - if (ctx.clock().now() > expire) - throw new IOException("Headers took too long [" + buf.toString() + "]"); + if (ctx.clock().now() > expire) { + throw new SocketTimeoutException("Headers took too long"); + } int split = buf.indexOf(":"); - if (split <= 0) throw new IOException("Invalid HTTP header, missing colon [" + buf.toString() + "]"); + if (split <= 0) + throw new BadRequestException("Invalid HTTP header, missing colon"); + totalSize += buf.length(); + if (totalSize > MAX_TOTAL_HEADER_SIZE) + throw new LineTooLongException("Req+headers too big"); String name = buf.substring(0, split).trim(); String value = null; if (buf.length() > split + 1) @@ -707,9 +884,9 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { String lcName = name.toLowerCase(Locale.US); if ("accept-encoding".equals(lcName)) - name = "Accept-encoding"; + name = "Accept-Encoding"; else if ("x-accept-encoding".equals(lcName)) - name = "X-Accept-encoding"; + name = "X-Accept-Encoding"; else if ("x-forwarded-for".equals(lcName)) name = "X-Forwarded-For"; else if ("x-forwarded-server".equals(lcName)) @@ -736,5 +913,77 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer { } } } + + /** + * Read a line teriminated by newline, with a total read timeout. + * + * Warning - strips \n but not \r + * Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded + * Warning - not UTF-8 + * + * @param buf output + * @param timeout throws SocketTimeoutException immediately if zero or negative + * @throws SocketTimeoutException if timeout is reached before newline + * @throws EOFException if EOF is reached before newline + * @throws LineTooLongException if too long + * @throws IOException on other errors in the underlying stream + * @since 0.9.19 modified from DataHelper + */ + private static void readLine(I2PSocket socket, StringBuilder buf, long timeout) throws IOException { + if (timeout <= 0) + throw new SocketTimeoutException(); + long expires = System.currentTimeMillis() + timeout; + InputStream in = socket.getInputStream(); + int c; + int i = 0; + socket.setReadTimeout(timeout); + while ( (c = in.read()) != -1) { + if (++i > MAX_LINE_LENGTH) + throw new LineTooLongException("Line too long - max " + MAX_LINE_LENGTH); + if (c == '\n') + break; + long newTimeout = expires - System.currentTimeMillis(); + if (newTimeout <= 0) + throw new SocketTimeoutException(); + buf.append((char)c); + if (newTimeout != timeout) { + timeout = newTimeout; + socket.setReadTimeout(timeout); + } + } + if (c == -1) { + if (System.currentTimeMillis() >= expires) + throw new SocketTimeoutException(); + else + throw new EOFException(); + } + } + + /** + * @since 0.9.19 + */ + private static class LineTooLongException extends IOException { + public LineTooLongException(String s) { + super(s); + } + } + + /** + * @since 0.9.20 + */ + private static class RequestTooLongException extends IOException { + public RequestTooLongException(String s) { + super(s); + } + } + + /** + * @since 0.9.20 + */ + private static class BadRequestException extends IOException { + public BadRequestException(String s) { + super(s); + } + } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java index 3915ae688..f53a72cd1 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Properties; import java.util.StringTokenizer; +import net.i2p.I2PException; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketAddress; import net.i2p.data.DataHelper; @@ -41,6 +42,9 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { public static final String PROP_DCC = "i2ptunnel.ircclient.enableDCC"; /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @param destinations peers we target, comma- or space-separated. Since 0.9.9, each dest may be appended with :port * @throws IllegalArgumentException if the I2PTunnel does not contain * valid config to contact the router @@ -81,8 +85,6 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { _dccEnabled = Boolean.parseBoolean(tunnel.getClientOptions().getProperty(PROP_DCC)); // TODO add some prudent tunnel options (or is it too late?) - startRunning(); - notifyEvent("openIRCClientResult", "ok"); } @@ -136,9 +138,12 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { DCCHelper dcc = _dccEnabled ? new DCC(s.getLocalAddress().getAddress()) : null; Thread in = new I2PAppThread(new IrcInboundFilter(s,i2ps, expectedPong, _log, dcc), "IRC Client " + _clientId + " in", true); in.start(); - Thread out = new I2PAppThread(new IrcOutboundFilter(s,i2ps, expectedPong, _log, dcc), "IRC Client " + _clientId + " out", true); - out.start(); - } catch (Exception ex) { + //Thread out = new I2PAppThread(new IrcOutboundFilter(s,i2ps, expectedPong, _log, dcc), "IRC Client " + _clientId + " out", true); + Runnable out = new IrcOutboundFilter(s,i2ps, expectedPong, _log, dcc); + // we are called from an unlimited thread pool, so run inline + //out.start(); + out.run(); + } catch (IOException ex) { // generally NoRouteToHostException if (_log.shouldLog(Log.WARN)) _log.warn("Error connecting", ex); @@ -156,6 +161,23 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { mySockets.remove(sockLock); } } + } catch (I2PException ex) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Error connecting", ex); + //l.log("Error connecting: " + ex.getMessage()); + try { + // Send a response so the user doesn't just see a disconnect + // and blame his router or the network. + String name = addr != null ? addr.getHostName() : "undefined"; + String msg = ":" + name + " 499 you :" + ex + "\r\n"; + s.getOutputStream().write(DataHelper.getUTF8(msg)); + } catch (IOException ioe) {} + closeSocket(s); + if (i2ps != null) { + synchronized (sockLock) { + mySockets.remove(sockLock); + } + } } } @@ -194,7 +216,8 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase { @Override public void startRunning() { super.startRunning(); - _context.portMapper().register(PortMapper.SVC_IRC, getLocalPort()); + if (open) + _context.portMapper().register(PortMapper.SVC_IRC, getLocalPort()); } @Override diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java index f39df586f..87dd7e937 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java @@ -1,11 +1,13 @@ package net.i2p.i2ptunnel; +import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; +import java.net.SocketTimeoutException; import java.util.Locale; import java.util.Properties; @@ -54,23 +56,44 @@ import net.i2p.util.Log; * @author zzz */ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { + private final byte[] cloakKey; // 32 bytes of stuff to scramble the dest with + private final String hostname; + private final String method; + private final String webircPassword; + private final String webircSpoofIP; + public static final String PROP_METHOD="ircserver.method"; public static final String PROP_METHOD_DEFAULT="user"; public static final String PROP_CLOAK="ircserver.cloakKey"; public static final String PROP_WEBIRC_PASSWORD="ircserver.webircPassword"; - public static final String PROP_WEBIRC_SPOOF_IP="ircserver.webircSpoofIP"; - public static final String PROP_WEBIRC_SPOOF_IP_DEFAULT="127.0.0.1"; + public static final String PROP_WEBIRC_SPOOF_IP="ircserver.webircSpoofIP"; + public static final String PROP_WEBIRC_SPOOF_IP_DEFAULT="127.0.0.1"; public static final String PROP_HOSTNAME="ircserver.fakeHostname"; public static final String PROP_HOSTNAME_DEFAULT="%f.b32.i2p"; private static final long HEADER_TIMEOUT = 15*1000; private static final long TOTAL_HEADER_TIMEOUT = 2 * HEADER_TIMEOUT; + private static final int MAX_LINE_LENGTH = 1024; - private final static byte[] ERR_UNAVAILABLE = - (":ircserver.i2p 499 you :" + - "This I2P IRC server is unvailable. It may be down or undergoing maintenance. " + + private final static String ERR_UNAVAILABLE = + ":ircserver.i2p 499 you :" + + "This I2P IRC server is unavailable. It may be down or undergoing maintenance. " + "Please try again later." + - "\r\n") - .getBytes(); + "\r\n"; + + private final static String ERR_REGISTRATION = + ":ircserver.i2p 499 you :" + + "Bad registration." + + "\r\n"; + + private final static String ERR_TIMEOUT = + ":ircserver.i2p 499 you :" + + "Timeout registering." + + "\r\n"; + + private final static String ERR_EOF = + ":ircserver.i2p 499 you :" + + "EOF while registering." + + "\r\n"; private static final String[] BAD_PROTOCOLS = { "GET ", "HEAD ", "POST ", "GNUTELLA CONNECT", "\023BitTorrent protocol" @@ -97,8 +120,8 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { // get the password for the webirc method this.webircPassword = opts.getProperty(PROP_WEBIRC_PASSWORD); - // get the spoof IP for the webirc method - this.webircSpoofIP = opts.getProperty(PROP_WEBIRC_SPOOF_IP, PROP_WEBIRC_SPOOF_IP_DEFAULT); + // get the spoof IP for the webirc method + this.webircSpoofIP = opts.getProperty(PROP_WEBIRC_SPOOF_IP, PROP_WEBIRC_SPOOF_IP_DEFAULT); // get the cloaking passphrase String passphrase = opts.getProperty(PROP_CLOAK); @@ -106,7 +129,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { this.cloakKey = new byte[Hash.HASH_LENGTH]; tunnel.getContext().random().nextBytes(this.cloakKey); } else { - this.cloakKey = SHA256Generator.getInstance().calculateHash(passphrase.trim().getBytes()).getData(); + this.cloakKey = SHA256Generator.getInstance().calculateHash(DataHelper.getUTF8(passphrase.trim())).getData(); } // get the fake hostmask to use @@ -119,33 +142,66 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { _log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() + " from: " + socket.getPeerDestination().calculateHash() + " port " + socket.getPort()); try { - String modifiedRegistration; - if(!this.method.equals("webirc")) { - // The headers _should_ be in the first packet, but - // may not be, depending on the client-side options - socket.setReadTimeout(HEADER_TIMEOUT); - InputStream in = socket.getInputStream(); - modifiedRegistration = filterRegistration(in, cloakDest(socket.getPeerDestination())); - socket.setReadTimeout(readTimeout); - } else { - StringBuffer buf = new StringBuffer("WEBIRC "); - buf.append(this.webircPassword); - buf.append(" cgiirc "); - buf.append(cloakDest(socket.getPeerDestination())); - buf.append(' '); - buf.append(this.webircSpoofIP); - buf.append("\r\n"); - modifiedRegistration = buf.toString(); - } + String modifiedRegistration; + if(!this.method.equals("webirc")) { + // The headers _should_ be in the first packet, but + // may not be, depending on the client-side options + modifiedRegistration = filterRegistration(socket, cloakDest(socket.getPeerDestination())); + socket.setReadTimeout(readTimeout); + } else { + StringBuffer buf = new StringBuffer("WEBIRC "); + buf.append(this.webircPassword); + buf.append(" cgiirc "); + buf.append(cloakDest(socket.getPeerDestination())); + buf.append(' '); + buf.append(this.webircSpoofIP); + buf.append("\r\n"); + modifiedRegistration = buf.toString(); + } Socket s = getSocket(socket.getPeerDestination().calculateHash(), socket.getLocalPort()); - Thread t = new I2PTunnelRunner(s, socket, slock, null, modifiedRegistration.getBytes(), + Thread t = new I2PTunnelRunner(s, socket, slock, null, DataHelper.getUTF8(modifiedRegistration), null, (I2PTunnelRunner.FailCallback) null); - t.start(); + // run in the unlimited client pool + //t.start(); + _clientExecutor.execute(t); + } catch (RegistrationException ex) { + try { + // Send a response so the user doesn't just see a disconnect + // and blame his router or the network. + socket.getOutputStream().write(ERR_REGISTRATION.getBytes("ISO-8859-1")); + } catch (IOException ioe) { + } finally { + try { socket.close(); } catch (IOException ioe) {} + } + if (_log.shouldLog(Log.WARN)) + _log.warn("Error while receiving the new IRC Connection", ex); + } catch (EOFException ex) { + try { + // Send a response so the user doesn't just see a disconnect + // and blame his router or the network. + socket.getOutputStream().write(ERR_EOF.getBytes("ISO-8859-1")); + } catch (IOException ioe) { + } finally { + try { socket.close(); } catch (IOException ioe) {} + } + if (_log.shouldLog(Log.WARN)) + _log.warn("Error while receiving the new IRC Connection", ex); + } catch (SocketTimeoutException ex) { + try { + // Send a response so the user doesn't just see a disconnect + // and blame his router or the network. + socket.getOutputStream().write(ERR_TIMEOUT.getBytes("ISO-8859-1")); + } catch (IOException ioe) { + } finally { + try { socket.close(); } catch (IOException ioe) {} + } + if (_log.shouldLog(Log.WARN)) + _log.warn("Error while receiving the new IRC Connection", ex); } catch (SocketException ex) { try { // Send a response so the user doesn't just see a disconnect // and blame his router or the network. - socket.getOutputStream().write(ERR_UNAVAILABLE); + socket.getOutputStream().write(ERR_UNAVAILABLE.getBytes("ISO-8859-1")); } catch (IOException ioe) {} try { socket.close(); @@ -189,32 +245,40 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { return this.hostname.replace("%f", hf).replace("%c", hc); } - /** keep reading until we see USER or SERVER */ - private static String filterRegistration(InputStream in, String newHostname) throws IOException { + /** + * Keep reading until we see USER or SERVER. + * This modifies the socket readTimeout, caller must save and restore. + * + * @throws SocketTimeoutException if timeout is reached before newline + * @throws EOFException if EOF is reached before newline + * @throws RegistrationException if line too long + * @throws IOException on other errors in the underlying stream + */ + private static String filterRegistration(I2PSocket socket, String newHostname) throws IOException { StringBuilder buf = new StringBuilder(128); int lineCount = 0; // slowloris / darkloris long expire = System.currentTimeMillis() + TOTAL_HEADER_TIMEOUT; while (true) { - String s = DataHelper.readLine(in); + String s = readLine(socket, expire - System.currentTimeMillis()); if (s == null) - throw new IOException("EOF reached before the end of the headers [" + buf.toString() + "]"); + throw new EOFException("EOF reached before the end of the headers"); if (lineCount == 0) { for (int i = 0; i < BAD_PROTOCOLS.length; i++) { if (s.startsWith(BAD_PROTOCOLS[i])) - throw new IOException("Bad protocol " + BAD_PROTOCOLS[i]); + throw new RegistrationException("Bad protocol " + BAD_PROTOCOLS[i]); } } if (++lineCount > 10) - throw new IOException("Too many lines before USER or SERVER, giving up"); + throw new RegistrationException("Too many lines before USER or SERVER, giving up"); if (System.currentTimeMillis() > expire) - throw new IOException("Headers took too long [" + buf.toString() + "]"); + throw new SocketTimeoutException("Headers took too long"); s = s.trim(); //if (_log.shouldLog(Log.DEBUG)) // _log.debug("Got line: " + s); - String field[]=s.split(" ",5); + String field[] = DataHelper.split(s, " ", 5); String command; int idx=0; @@ -223,12 +287,12 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { idx++; command = field[idx++].toUpperCase(Locale.US); } catch (IndexOutOfBoundsException ioobe) { - throw new IOException("Dropping defective message: [" + s + ']'); + throw new RegistrationException("Dropping defective message: [" + s + ']'); } if ("USER".equals(command)) { if (field.length < idx + 4) - throw new IOException("Too few parameters in USER message: " + s); + throw new RegistrationException("Too few parameters in USER message: " + s); // USER zzz1 hostname localhost :zzz // => // USER zzz1 abcd1234.i2p localhost :zzz @@ -247,9 +311,58 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { return buf.toString(); } - private final byte[] cloakKey; // 32 bytes of stuff to scramble the dest with - private final String hostname; - private final String method; - private final String webircPassword; - private final String webircSpoofIP; + /** + * Read a line teriminated by newline, with a total read timeout. + * + * Warning - strips \n but not \r + * Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded + * Warning - not UTF-8 + * + * @param timeout throws SocketTimeoutException immediately if zero or negative + * @throws SocketTimeoutException if timeout is reached before newline + * @throws EOFException if EOF is reached before newline + * @throws RegistrationException if line too long + * @throws IOException on other errors in the underlying stream + * @since 0.9.19 modified from DataHelper and I2PTunnelHTTPServer + */ + private static String readLine(I2PSocket socket, long timeout) throws IOException { + StringBuilder buf = new StringBuilder(128); + if (timeout <= 0) + throw new SocketTimeoutException(); + long expires = System.currentTimeMillis() + timeout; + InputStream in = socket.getInputStream(); + int c; + int i = 0; + socket.setReadTimeout(timeout); + while ( (c = in.read()) != -1) { + if (++i > MAX_LINE_LENGTH) + throw new RegistrationException("Line too long - max " + MAX_LINE_LENGTH); + if (c == '\n') + break; + long newTimeout = expires - System.currentTimeMillis(); + if (newTimeout <= 0) + throw new SocketTimeoutException(); + buf.append((char)c); + if (newTimeout != timeout) { + timeout = newTimeout; + socket.setReadTimeout(timeout); + } + } + if (c == -1) { + if (System.currentTimeMillis() >= expires) + throw new SocketTimeoutException(); + else + throw new EOFException(); + } + return buf.toString(); + } + + /** + * @since 0.9.19 + */ + private static class RegistrationException extends IOException { + public RegistrationException(String s) { + super(s); + } + } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelOutproxyRunner.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelOutproxyRunner.java index 1e0752b17..d8d9369a0 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelOutproxyRunner.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelOutproxyRunner.java @@ -99,6 +99,7 @@ public class I2PTunnelOutproxyRunner extends I2PAppThread { /** * When was the last data for this runner sent or received? + * As of 0.9.20, returns -1 always! * * @return date (ms since the epoch), or -1 if no data has been transferred yet * @deprecated unused @@ -107,9 +108,11 @@ public class I2PTunnelOutproxyRunner extends I2PAppThread { return lastActivityOn; } +/**** private void updateActivity() { lastActivityOn = Clock.getInstance().now(); } +****/ /** * When this runner started up transferring data @@ -179,7 +182,7 @@ public class I2PTunnelOutproxyRunner extends I2PAppThread { } catch (IllegalStateException ise) { if (_log.shouldLog(Log.WARN)) _log.warn("gnu?", ise); - } catch (Exception e) { + } catch (RuntimeException e) { if (_log.shouldLog(Log.ERROR)) _log.error("Internal error", e); } finally { @@ -284,26 +287,31 @@ public class I2PTunnelOutproxyRunner extends I2PAppThread { try { int len; while ((len = in.read(buffer)) != -1) { - out.write(buffer, 0, len); - if (_toI2P) - totalSent += len; - else - totalReceived += len; - - if (len > 0) updateActivity(); + if (len > 0) { + out.write(buffer, 0, len); + if (_toI2P) + totalSent += len; + else + totalReceived += len; + //updateActivity(); + } if (in.available() == 0) { if (_log.shouldLog(Log.DEBUG)) _log.debug(direction + ": " + len + " bytes flushed through " + (_toI2P ? "to " : "from ") + "outproxy"); - try { - Thread.sleep(I2PTunnel.PACKET_DELAY); - } catch (InterruptedException e) { - e.printStackTrace(); + if (_toI2P) { + try { + Thread.sleep(5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (in.available() <= 0) + out.flush(); + } else { + out.flush(); } - - if (in.available() <= 0) - out.flush(); // make sure the data get though } } //out.flush(); // close() flushes diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelRunner.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelRunner.java index d4bd1d455..b8bfdaebf 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelRunner.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelRunner.java @@ -62,8 +62,6 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr private long totalSent; private long totalReceived; - private static final AtomicLong __forwarderId = new AtomicLong(); - /** * For use in new constructor * @since 0.9.14 @@ -200,6 +198,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr /** * When was the last data for this runner sent or received? + * As of 0.9.20, returns -1 always! * * @return date (ms since the epoch), or -1 if no data has been transferred yet * @deprecated unused @@ -208,9 +207,11 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr return lastActivityOn; } +/**** private void updateActivity() { lastActivityOn = Clock.getInstance().now(); } +****/ /** * When this runner started up transferring data @@ -268,9 +269,10 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr in = new BufferedInputStream(in, 2*NETWORK_BUFFER_SIZE); StreamForwarder toI2P = new StreamForwarder(in, i2pout, true); StreamForwarder fromI2P = new StreamForwarder(i2pin, out, false); - // TODO can we run one of these inline and save a thread? toI2P.start(); - fromI2P.start(); + // We are already a thread, so run the second one inline + //fromI2P.start(); + fromI2P.run(); synchronized (finishLock) { while (!finished) { finishLock.wait(); @@ -324,7 +326,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr // at net.i2p.i2ptunnel.I2PTunnelRunner.run(I2PTunnelRunner.java:167) if (_log.shouldLog(Log.WARN)) _log.warn("gnu?", ise); - } catch (Exception e) { + } catch (RuntimeException e) { if (_log.shouldLog(Log.ERROR)) _log.error("Internal error", e); } finally { @@ -384,7 +386,8 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr // ignore } t1.join(30*1000); - t2.join(30*1000); + // t2 = fromI2P now run inline + //t2.join(30*1000); } /** @@ -426,7 +429,7 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr _toI2P = toI2P; direction = (toI2P ? "toI2P" : "fromI2P"); _cache = ByteCache.getInstance(32, NETWORK_BUFFER_SIZE); - setName("StreamForwarder " + _runnerId + '.' + __forwarderId.incrementAndGet()); + setName("StreamForwarder " + _runnerId + '.' + direction); } @Override @@ -448,28 +451,33 @@ public class I2PTunnelRunner extends I2PAppThread implements I2PSocket.SocketErr try { int len; while ((len = in.read(buffer)) != -1) { - out.write(buffer, 0, len); - if (_toI2P) - totalSent += len; - else - totalReceived += len; - - if (len > 0) updateActivity(); + if (len > 0) { + out.write(buffer, 0, len); + if (_toI2P) + totalSent += len; + else + totalReceived += len; + //updateActivity(); + } if (in.available() == 0) { //if (_log.shouldLog(Log.DEBUG)) // _log.debug("Flushing after sending " + len + " bytes through"); if (_log.shouldLog(Log.DEBUG)) _log.debug(direction + ": " + len + " bytes flushed through " + (_toI2P ? "to " : "from ") - + i2ps.getPeerDestination().calculateHash().toBase64().substring(0,6)); - try { - Thread.sleep(I2PTunnel.PACKET_DELAY); - } catch (InterruptedException e) { - e.printStackTrace(); + + to); + if (_toI2P) { + try { + Thread.sleep(5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (in.available() <= 0) + out.flush(); + } else { + out.flush(); } - - if (in.available() <= 0) - out.flush(); // make sure the data get though } } //out.flush(); // close() flushes diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java index 0d2667d60..3b9217238 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java @@ -16,6 +16,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; import java.net.SocketTimeoutException; +import java.net.UnknownHostException; import java.security.GeneralSecurityException; import java.util.Map; import java.util.Properties; @@ -28,6 +29,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.ThreadFactory; import net.i2p.I2PException; +import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PSocket; @@ -44,14 +46,14 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { protected final Log _log; protected final I2PSocketManager sockMgr; - protected I2PServerSocket i2pss; + protected volatile I2PServerSocket i2pss; private final Object lock = new Object(); protected final Object slock = new Object(); protected final Object sslLock = new Object(); - protected final InetAddress remoteHost; - protected final int remotePort; + protected InetAddress remoteHost; + protected int remotePort; private final boolean _usePool; protected final Logging l; private I2PSSLSocketFactory _sslFactory; @@ -78,6 +80,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { protected I2PTunnelTask task; protected boolean bidir; private ThreadPoolExecutor _executor; + protected volatile ThreadPoolExecutor _clientExecutor; private final Map _socketMap = new ConcurrentHashMap(4); /** unused? port should always be specified */ @@ -212,7 +215,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { try { I2PSocketManager rv = I2PSocketManagerFactory.createDisconnectedManager(privData, getTunnel().host, portNum, props); - rv.setName("Server"); + rv.setName("I2PTunnel Server"); getTunnel().addSession(rv.getSession()); return rv; } catch (I2PSessionException ise) { @@ -265,6 +268,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { * Copy input stream to a byte array, so we can retry * @since 0.7.10 */ +/**** private static ByteArrayInputStream copyOfInputStream(InputStream is) throws IOException { byte[] buf = new byte[128]; ByteArrayOutputStream os = new ByteArrayOutputStream(768); @@ -279,6 +283,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { } return new ByteArrayInputStream(os.toByteArray()); } +****/ /** * Start running the I2PTunnelServer. @@ -314,6 +319,13 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { return readTimeout; } + /** + * Note that the tunnel can be reopened after this by calling startRunning(). + * This does not release all resources. In particular, the I2PSocketManager remains + * and it may have timer threads that continue running. + * + * To release all resources permanently, call destroy(). + */ public synchronized boolean close(boolean forced) { if (!open) return true; if (task != null) { @@ -328,16 +340,20 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { return false; } l.log("Stopping tunnels for server at " + this.remoteHost + ':' + this.remotePort); + open = false; try { - if (i2pss != null) i2pss.close(); - getTunnel().removeSession(sockMgr.getSession()); - sockMgr.getSession().destroySession(); + if (i2pss != null) { + i2pss.close(); + i2pss = null; + } + I2PSession session = sockMgr.getSession(); + getTunnel().removeSession(session); + session.destroySession(); } catch (I2PException ex) { _log.error("Error destroying the session", ex); //System.exit(1); } //l.log("Server shut down."); - open = false; if (_usePool && _executor != null) { _executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); _executor.shutdownNow(); @@ -346,8 +362,23 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { } } + /** + * Note that the tunnel cannot be reopened after this by calling startRunning(), + * as it will destroy the underlying socket manager. + * This releases all resources. + * + * @since 0.9.17 + */ + @Override + public synchronized boolean destroy() { + close(true); + sockMgr.destroySocketManager(); + return true; + } + /** * Update the I2PSocketManager. + * And since 0.9.15, the target host and port. * * @since 0.9.1 */ @@ -357,6 +388,27 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { return; Properties props = tunnel.getClientOptions(); sockMgr.setDefaultOptions(sockMgr.buildOptions(props)); + // see TunnelController.setSessionOptions() + String h = props.getProperty(TunnelController.PROP_TARGET_HOST); + if (h != null) { + try { + remoteHost = InetAddress.getByName(h); + } catch (UnknownHostException uhe) { + l.log("Unknown host: " + h); + } + } + String p = props.getProperty(TunnelController.PROP_TARGET_PORT); + if (p != null) { + try { + int port = Integer.parseInt(p); + if (port > 0 && port <= 65535) + remotePort = port; + else + l.log("Bad port: " + port); + } catch (NumberFormatException nfe) { + l.log("Bad port: " + p); + } + } buildSocketMap(props); } @@ -409,7 +461,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { * hands each I2P socket to the executor or runs it in-line. */ public void run() { - I2PServerSocket i2pS_S = sockMgr.getServerSocket(); + i2pss = sockMgr.getServerSocket(); if (_log.shouldLog(Log.WARN)) { if (_usePool) _log.warn("Starting executor with " + getHandlerCount() + " threads max"); @@ -419,9 +471,22 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { if (_usePool) { _executor = new CustomThreadPoolExecutor(getHandlerCount(), "ServerHandler pool " + remoteHost + ':' + remotePort); } + TunnelControllerGroup tcg = TunnelControllerGroup.getInstance(); + if (tcg != null) { + _clientExecutor = tcg.getClientExecutor(); + } else { + // Fallback in case TCG.getInstance() is null, never instantiated + // and we were not started by TCG. + // Maybe a plugin loaded before TCG? Should be rare. + // Never shut down. + _clientExecutor = new TunnelControllerGroup.CustomThreadPoolExecutor(); + } while (open) { try { - final I2PSocket i2ps = i2pS_S.accept(); + I2PServerSocket ci2pss = i2pss; + if (ci2pss == null) + throw new I2PException("I2PServerSocket closed"); + final I2PSocket i2ps = ci2pss.accept(); if (i2ps == null) throw new I2PException("I2PServerSocket closed"); if (_usePool) { try { @@ -448,13 +513,11 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { } catch (ConnectException ce) { if (_log.shouldLog(Log.ERROR)) _log.error("Error accepting", ce); - // not killing the server.. - try { - Thread.sleep(500); - } catch (InterruptedException ie) {} + open = false; + break; } catch(SocketTimeoutException ste) { // ignored, we never set the timeout - } catch (Exception e) { + } catch (RuntimeException e) { // streaming borkage if (_log.shouldLog(Log.ERROR)) _log.error("Uncaught exception accepting", e); @@ -464,7 +527,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { } catch (InterruptedException ie) {} } } - if (_executor != null) + if (_executor != null && !_executor.isTerminating() && !_executor.isShutdown()) _executor.shutdownNow(); } @@ -507,10 +570,25 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { } public void run() { - blockingHandle(_i2ps); + try { + blockingHandle(_i2ps); + } catch (Throwable t) { + _log.error("Uncaught error in i2ptunnel server", t); + } } } + /** + * This is run in a thread from a limited-size thread pool via Handler.run(), + * except for a standard server (this class, no extension, as determined in getUsePool()), + * it is run directly in the acceptor thread (see run()). + * + * In either case, this method and any overrides must spawn a thread and return quickly. + * If blocking while reading the headers (as in HTTP and IRC), the thread pool + * may be exhausted. + * + * See PROP_USE_POOL, DEFAULT_USE_POOL, PROP_HANDLER_COUNT, DEFAULT_HANDLER_COUNT + */ protected void blockingHandle(I2PSocket socket) { if (_log.shouldLog(Log.INFO)) _log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() + @@ -525,7 +603,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable { afterSocket = getTunnel().getContext().clock().now(); Thread t = new I2PTunnelRunner(s, socket, slock, null, null, null, (I2PTunnelRunner.FailCallback) null); - t.start(); + // run in the unlimited client pool + //t.start(); + _clientExecutor.execute(t); long afterHandle = getTunnel().getContext().clock().now(); long timeToHandle = afterHandle - afterAccept; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelTask.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelTask.java index 2954b0a2f..b59567ff8 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelTask.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelTask.java @@ -8,9 +8,15 @@ import net.i2p.util.EventDispatcher; import net.i2p.util.EventDispatcherImpl; /** - * Either a Server or a Client. + * Either a Server or a Client. + * + * Use caution if extending externally. + * This class should be maintained as a stable API, + * but ask to be sure. + * + * Note that there is no startRunning() method, + * however all extending classes implement one. */ - public abstract class I2PTunnelTask extends EventDispatcherImpl { private int id; @@ -56,12 +62,37 @@ public abstract class I2PTunnelTask extends EventDispatcherImpl { tunnel.routerDisconnected(); } + /** + * Note that the tunnel can be reopened after this by calling startRunning(). + * This may not release all resources. In particular, the I2PSocketManager remains + * and it may have timer threads that continue running. + * + * To release all resources permanently, call destroy(). + * + * @return success + */ public abstract boolean close(boolean forced); + /** + * Note that the tunnel cannot be reopened after this by calling startRunning(), + * as it may destroy the underlying socket manager, depending on implementation. + * This should release all resources. + * + * The implementation here simply calls close(true). + * Extending classes should override to release all resources. + * + * @return success + * @since 0.9.17 + */ + public boolean destroy() { + return close(true); + } + /** * Notify the task that I2PTunnel's options have been updated. * Extending classes should override and call I2PTunnel.getClientOptions(), * then update the I2PSocketManager. + * Does nothing here. * * @since 0.9.1 */ @@ -80,9 +111,15 @@ public abstract class I2PTunnelTask extends EventDispatcherImpl { getTunnel().removeSession(session); } + /** + * Does nothing here. Extending classes may override. + */ public void errorOccurred(I2PSession session, String message, Throwable error) { } + /** + * Does nothing here. Extending classes may override. + */ public void reportAbuse(I2PSession session, int severity) { } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2Ping.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2Ping.java index e8321e41a..da615301e 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2Ping.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2Ping.java @@ -4,8 +4,9 @@ package net.i2p.i2ptunnel; import java.io.BufferedReader; -import java.io.FileReader; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.net.Socket; import java.util.ArrayList; import java.util.List; @@ -18,6 +19,7 @@ import net.i2p.I2PException; import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.client.streaming.I2PSocketManager; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.util.EventDispatcher; import net.i2p.util.I2PAppThread; @@ -67,7 +69,7 @@ public class I2Ping extends I2PTunnelClientBase { // Notify constructor that port is ready synchronized (this) { listenerReady = true; - notify(); + notifyAll(); } l.log("*** I2Ping results:"); try { @@ -92,7 +94,7 @@ public class I2Ping extends I2PTunnelClientBase { int localPort = 0; int remotePort = 0; boolean error = false; - String[] argv = cmd.split(" "); + String[] argv = DataHelper.split(cmd, " "); Getopt g = new Getopt("ping", argv, "t:m:n:chl:f:p:"); int c; while ((c = g.getopt()) != -1) { @@ -157,7 +159,7 @@ public class I2Ping extends I2PTunnelClientBase { } if (hostListFile != null) { - BufferedReader br = new BufferedReader(new FileReader(hostListFile)); + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(hostListFile), "UTF-8")); String line; List pingHandlers = new ArrayList(); int i = 0; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/SSLClientUtil.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/SSLClientUtil.java new file mode 100644 index 000000000..01e7c4791 --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/SSLClientUtil.java @@ -0,0 +1,203 @@ +package net.i2p.i2ptunnel; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.GeneralSecurityException; +import java.util.Properties; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLContext; + +import net.i2p.I2PAppContext; +import net.i2p.crypto.KeyStoreUtil; +import net.i2p.util.Log; +import net.i2p.util.SecureDirectory; + +/** + * Utilities for I2PTunnel client SSL server sockets. + * + * @since 0.9.15 adopted from net.i2p.router.client.SSLClientListenerRunner + */ +public class SSLClientUtil { + + private static final String PROP_KEYSTORE_PASSWORD = "keystorePassword"; + private static final String DEFAULT_KEYSTORE_PASSWORD = "changeit"; + private static final String PROP_KEY_PASSWORD = "keyPassword"; + private static final String PROP_KEY_ALIAS = "keyAlias"; + private static final String ASCII_KEYFILE_SUFFIX = ".local.crt"; + private static final String PROP_KS_NAME = "keystoreFile"; + private static final String KS_DIR = "keystore"; + private static final String PREFIX = "i2ptunnel-"; + private static final String KS_SUFFIX = ".ks"; + private static final String CERT_DIR = "certificates/i2ptunnel"; + + /** + * Create a new selfsigned cert and keystore and pubkey cert if they don't exist. + * May take a while. + * + * @param opts in/out, updated if rv is true + * @return false if it already exists; if true, caller must save opts + * @throws IOException on creation fail + */ + public static boolean verifyKeyStore(Properties opts) throws IOException { + return verifyKeyStore(opts, ""); + } + + /** + * Create a new selfsigned cert and keystore and pubkey cert if they don't exist. + * May take a while. + * + * @param opts in/out, updated if rv is true + * @param optPfx add this prefix when getting/setting options + * @return false if it already exists; if true, caller must save opts + * @throws IOException on creation fail + */ + public static boolean verifyKeyStore(Properties opts, String optPfx) throws IOException { + String name = opts.getProperty(optPfx + PROP_KEY_ALIAS); + if (name == null) { + name = KeyStoreUtil.randomString(); + opts.setProperty(optPfx + PROP_KEY_ALIAS, name); + } + String ksname = opts.getProperty(optPfx + PROP_KS_NAME); + if (ksname == null) { + ksname = PREFIX + name + KS_SUFFIX; + opts.setProperty(optPfx + PROP_KS_NAME, ksname); + } + File ks = new File(ksname); + if (!ks.isAbsolute()) { + ks = new File(I2PAppContext.getGlobalContext().getConfigDir(), KS_DIR); + ks = new File(ks, ksname); + } + if (ks.exists()) + return false; + File dir = ks.getParentFile(); + if (!dir.exists()) { + File sdir = new SecureDirectory(dir.getAbsolutePath()); + if (!sdir.mkdirs()) + throw new IOException("Unable to create keystore " + ks); + } + boolean rv = createKeyStore(ks, name, opts, optPfx); + if (!rv) + throw new IOException("Unable to create keystore " + ks); + + // Now read it back out of the new keystore and save it in ascii form + // where the clients can get to it. + // Failure of this part is not fatal. + exportCert(ks, name, opts, optPfx); + return true; + } + + + /** + * Call out to keytool to create a new keystore with a keypair in it. + * + * @param name used in CNAME + * @param opts in/out, updated if rv is true, must contain PROP_KEY_ALIAS + * @param optPfx add this prefix when getting/setting options + * @return success, if true, opts will have password properties added to be saved + */ + private static boolean createKeyStore(File ks, String name, Properties opts, String optPfx) { + // make a random 48 character password (30 * 8 / 5) + String keyPassword = KeyStoreUtil.randomString(); + // and one for the cname + String cname = name + ".i2ptunnel.i2p.net"; + + String keyName = opts.getProperty(optPfx + PROP_KEY_ALIAS); + boolean success = KeyStoreUtil.createKeys(ks, keyName, cname, "I2PTUNNEL", keyPassword); + if (success) { + success = ks.exists(); + if (success) { + opts.setProperty(optPfx + PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD); + opts.setProperty(optPfx + PROP_KEY_PASSWORD, keyPassword); + } + } + if (success) { + logAlways("Created self-signed certificate for " + cname + " in keystore: " + ks.getAbsolutePath() + "\n" + + "The certificate name was generated randomly, and is not associated with your " + + "IP address, host name, router identity, or destination keys."); + } else { + error("Failed to create I2PTunnel SSL keystore.\n" + + "If you create the keystore manually, you must add " + optPfx + PROP_KEYSTORE_PASSWORD + " and " + optPfx + PROP_KEY_PASSWORD + + " to " + (new File(I2PAppContext.getGlobalContext().getConfigDir(), "i2ptunnel.config")).getAbsolutePath()); + } + return success; + } + + /** + * Pull the cert back OUT of the keystore and save it as ascii + * so the clients can get to it. + * + * @param name used to generate output file name + * @param opts must contain optPfx + PROP_KEY_ALIAS + * @param optPfx add this prefix when getting options + */ + private static void exportCert(File ks, String name, Properties opts, String optPfx) { + File sdir = new SecureDirectory(I2PAppContext.getGlobalContext().getConfigDir(), CERT_DIR); + if (sdir.exists() || sdir.mkdirs()) { + String keyAlias = opts.getProperty(optPfx + PROP_KEY_ALIAS); + String ksPass = opts.getProperty(optPfx + PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD); + File out = new File(sdir, PREFIX + name + ASCII_KEYFILE_SUFFIX); + boolean success = KeyStoreUtil.exportCert(ks, ksPass, keyAlias, out); + if (!success) + error("Error getting SSL cert to save as ASCII"); + } else { + error("Error saving ASCII SSL keys"); + } + } + + /** + * Sets up the SSLContext and sets the socket factory. + * No option prefix allowed. + * + * @throws IOException; GeneralSecurityExceptions are wrapped in IOE for convenience + * @return factory, throws on all errors + */ + public static SSLServerSocketFactory initializeFactory(Properties opts) throws IOException { + String ksPass = opts.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD); + String keyPass = opts.getProperty(PROP_KEY_PASSWORD); + if (keyPass == null) { + throw new IOException("No key password, set " + PROP_KEY_PASSWORD + " in " + + (new File(I2PAppContext.getGlobalContext().getConfigDir(), "i2ptunnel.config")).getAbsolutePath()); + } + String ksname = opts.getProperty(PROP_KS_NAME); + if (ksname == null) { + throw new IOException("No keystore, set " + PROP_KS_NAME + " in " + + (new File(I2PAppContext.getGlobalContext().getConfigDir(), "i2ptunnel.config")).getAbsolutePath()); + } + File ks = new File(ksname); + if (!ks.isAbsolute()) { + ks = new File(I2PAppContext.getGlobalContext().getConfigDir(), KS_DIR); + ks = new File(ks, ksname); + } + + InputStream fis = null; + try { + SSLContext sslc = SSLContext.getInstance("TLS"); + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + fis = new FileInputStream(ks); + keyStore.load(fis, ksPass.toCharArray()); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, keyPass.toCharArray()); + sslc.init(kmf.getKeyManagers(), null, I2PAppContext.getGlobalContext().random()); + return sslc.getServerSocketFactory(); + } catch (GeneralSecurityException gse) { + IOException ioe = new IOException("keystore error"); + ioe.initCause(gse); + throw ioe; + } finally { + if (fis != null) try { fis.close(); } catch (IOException ioe) {} + } + } + + private static void error(String s) { + I2PAppContext.getGlobalContext().logManager().getLog(SSLClientUtil.class).error(s); + } + + private static void logAlways(String s) { + I2PAppContext.getGlobalContext().logManager().getLog(SSLClientUtil.class).logAlways(Log.INFO, s); + } +} diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java index 96fab6213..229a4b7d1 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java @@ -4,9 +4,12 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import net.i2p.I2PAppContext; import net.i2p.I2PException; @@ -21,6 +24,7 @@ import net.i2p.util.I2PAppThread; import net.i2p.util.Log; import net.i2p.util.SecureFile; import net.i2p.util.SecureFileOutputStream; +import net.i2p.util.SystemVersion; /** * Coordinate the runtime operation and configuration of a single I2PTunnel. @@ -39,8 +43,18 @@ public class TunnelController implements Logging { private final I2PTunnel _tunnel; private final List _messages; private List _sessions; - private boolean _running; - private boolean _starting; + private volatile TunnelState _state; + + /** @since 0.9.19 */ + private enum TunnelState { + START_ON_LOAD, + STARTING, + RUNNING, + STOPPING, + STOPPED, + DESTROYING, + DESTROYED, + } public static final String KEY_BACKUP_DIR = "i2ptunnel-keyBackup"; @@ -68,6 +82,7 @@ public class TunnelController implements Logging { private static final String OPT_BUNDLE_REPLY = PFX_OPTION + "shouldBundleReplyInfo"; private static final String OPT_TAGS_SEND = PFX_OPTION + "crypto.tagsToSend"; private static final String OPT_LOW_TAGS = PFX_OPTION + "crypto.lowTagThreshold"; + private static final String OPT_SIG_TYPE = PFX_OPTION + I2PClient.PROP_SIGTYPE; /** all of these @since 0.9.14 */ public static final String TYPE_CONNECT = "connectclient"; @@ -80,15 +95,35 @@ public class TunnelController implements Logging { public static final String TYPE_SOCKS_IRC = "socksirctunnel"; public static final String TYPE_STD_CLIENT = "client"; public static final String TYPE_STD_SERVER = "server"; + /** Client in the UI and I2P side but a server on the localhost side */ public static final String TYPE_STREAMR_CLIENT = "streamrclient"; + /** Server in the UI and I2P side but a client on the localhost side */ public static final String TYPE_STREAMR_SERVER = "streamrserver"; + /** + * This is guaranteed to be available. + * @since 0.9.17 + */ + public static final SigType PREFERRED_SIGTYPE; + static { + if (SystemVersion.isARM() || SystemVersion.isGNU() || SystemVersion.isAndroid()) { + if (SigType.ECDSA_SHA256_P256.isAvailable()) + PREFERRED_SIGTYPE = SigType.ECDSA_SHA256_P256; + else + PREFERRED_SIGTYPE = SigType.DSA_SHA1; + } else { + PREFERRED_SIGTYPE = SigType.EdDSA_SHA512_Ed25519; + } + } + /** * Create a new controller for a tunnel out of the specific config options. * The config may contain a large number of options - only ones that begin in * the prefix should be used (and, in turn, that prefix should be stripped off * before being interpreted by this controller) * + * Defaults in config properties are not recommended, they may or may not be honored. + * * @param config original key=value mapping non-null * @param prefix beginning of key values that are relevant to this tunnel */ @@ -97,6 +132,7 @@ public class TunnelController implements Logging { } /** + * Defaults in config properties are not recommended, they may or may not be honored. * * @param config original key=value mapping non-null * @param prefix beginning of key values that are relevant to this tunnel @@ -109,11 +145,10 @@ public class TunnelController implements Logging { _log = I2PAppContext.getGlobalContext().logManager().getLog(TunnelController.class); setConfig(config, prefix); _messages = new ArrayList(4); - _running = false; boolean keyOK = true; if (createKey && (getType().endsWith("server") || getPersistentClientKey())) keyOK = createPrivateKey(); - _starting = keyOK && getStartOnLoad(); + _state = keyOK && getStartOnLoad() ? TunnelState.START_ON_LOAD : TunnelState.STOPPED; } /** @@ -121,15 +156,12 @@ public class TunnelController implements Logging { */ private boolean createPrivateKey() { I2PClient client = I2PClientFactory.createClient(); - String filename = getPrivKeyFile(); - if ( (filename == null) || (filename.trim().length() <= 0) ) { + File keyFile = getPrivateKeyFile(); + if (keyFile == null) { log("No filename specified for the private key"); return false; } - File keyFile = new File(getPrivKeyFile()); - if (!keyFile.isAbsolute()) - keyFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), getPrivKeyFile()); if (keyFile.exists()) { //log("Not overwriting existing private keys in " + keyFile.getAbsolutePath()); return true; @@ -141,14 +173,14 @@ public class TunnelController implements Logging { FileOutputStream fos = null; try { fos = new SecureFileOutputStream(keyFile); - SigType stype = I2PClient.DEFAULT_SIGTYPE; - String st = _config.getProperty(PFX_OPTION + I2PClient.PROP_SIGTYPE); + SigType stype = PREFERRED_SIGTYPE; + String st = _config.getProperty(OPT_SIG_TYPE); if (st != null) { SigType type = SigType.parseSigType(st); - if (type != null) + if (type != null && type.isAvailable()) stype = type; else - log("Unsupported sig type " + st); + log("Unsupported sig type " + st + ", reverting to " + stype); } Destination dest = client.createDestination(fos, stype); String destStr = dest.toBase64(); @@ -161,8 +193,10 @@ public class TunnelController implements Logging { if (backupDir.isDirectory() || backupDir.mkdir()) { String name = b32 + '-' + I2PAppContext.getGlobalContext().clock().now() + ".dat"; File backup = new File(backupDir, name); - if (FileUtil.copy(keyFile, backup, false, true)) + if (FileUtil.copy(keyFile, backup, false, true)) { + SecureFileOutputStream.setPerms(backup); log("Private key backup saved to " + backup.getAbsolutePath()); + } } } catch (I2PException ie) { if (_log.shouldLog(Log.ERROR)) @@ -181,9 +215,11 @@ public class TunnelController implements Logging { } public void startTunnelBackground() { - if (_running) return; - _starting = true; - new I2PAppThread(new Runnable() { public void run() { startTunnel(); } }).start(); + synchronized (this) { + if (_state != TunnelState.STOPPED && _state != TunnelState.START_ON_LOAD) + return; + } + new I2PAppThread(new Runnable() { public void run() { startTunnel(); } }, "Tunnel Starter " + getName()).start(); } /** @@ -191,31 +227,40 @@ public class TunnelController implements Logging { * */ public void startTunnel() { - _starting = true; + synchronized (this) { + if (_state != TunnelState.STOPPED && _state != TunnelState.START_ON_LOAD) { + if (_state == TunnelState.RUNNING) { + if (_log.shouldLog(Log.INFO)) + _log.info("Already running"); + log("Tunnel " + getName() + " is already running"); + } + return; + } + changeState(TunnelState.STARTING); + } try { doStartTunnel(); - } catch (Exception e) { + } catch (RuntimeException e) { _log.error("Error starting the tunnel " + getName(), e); log("Error starting the tunnel " + getName() + ": " + e.getMessage()); // if we don't acquire() then the release() in stopTunnel() won't work acquire(); stopTunnel(); } - _starting = false; } /** * @throws IllegalArgumentException via methods in I2PTunnel */ private void doStartTunnel() { - if (_running) { - if (_log.shouldLog(Log.INFO)) - _log.info("Already running"); - log("Tunnel " + getName() + " is already running"); - return; + synchronized (this) { + if (_state != TunnelState.STARTING) + return; } + String type = getType(); if ( (type == null) || (type.length() <= 0) ) { + changeState(TunnelState.STOPPED); if (_log.shouldLog(Log.ERROR)) _log.error("Cannot start the tunnel - no type specified"); return; @@ -225,6 +270,7 @@ public class TunnelController implements Logging { if (type.endsWith("server") || getPersistentClientKey()) { boolean ok = createPrivateKey(); if (!ok) { + changeState(TunnelState.STOPPED); log("Failed to start tunnel " + getName() + " as the private key file could not be created"); return; } @@ -256,12 +302,13 @@ public class TunnelController implements Logging { } else if (TYPE_STREAMR_SERVER.equals(type)) { startStreamrServer(); } else { + changeState(TunnelState.STOPPED); if (_log.shouldLog(Log.ERROR)) _log.error("Cannot start tunnel - unknown type [" + type + "]"); return; } acquire(); - _running = true; + changeState(TunnelState.RUNNING); } private void startHttpClient() { @@ -387,10 +434,9 @@ public class TunnelController implements Logging { * Note the fact that we are no longer using some sessions, and if * no other tunnels are using them, close them. */ - private void release() { - if (_sessions != null && !_sessions.isEmpty()) { - for (int i = 0; i < _sessions.size(); i++) { - I2PSession s = _sessions.get(i); + private void release(Collection sessions) { + if (!sessions.isEmpty()) { + for (I2PSession s : sessions) { if (_log.shouldLog(Log.INFO)) _log.info("Releasing session " + s); TunnelControllerGroup group = TunnelControllerGroup.getInstance(); @@ -403,6 +449,22 @@ public class TunnelController implements Logging { _log.warn("No sessions to release? for " + getName()); } } + + /** + * Get all the sessions we may be using. + * + * @return a copy, non-null + * @since 0.9.15 + */ + private Collection getAllSessions() { + // We use _sessions AND the tunnel sessions as + // _sessions will be null for delay-open tunnels - see acquire(). + // We want the current sessions. + Set sessions = new HashSet(_tunnel.getSessions()); + if (_sessions != null) + sessions.addAll(_sessions); + return sessions; + } private void startClient() { setListenOn(); @@ -458,6 +520,7 @@ public class TunnelController implements Logging { /** * These are the ones stored with a prefix of "option." + * Defaults in config properties are not honored. * * @return keys with the "option." prefix stripped, non-null * @since 0.9.1 Much better than getClientOptions() @@ -487,6 +550,17 @@ public class TunnelController implements Logging { String proxies = getProxyList(); if (proxies != null) opts.setProperty(PROP_PROXIES, proxies); + // Ditto spoof host. Since 0.9.15. + String spoofhost = getSpoofedHost(); + if (spoofhost != null) + opts.setProperty(PROP_SPOOFED_HOST, spoofhost); + // Ditto target host/port. Since 0.9.15. + String targethost = getTargetHost(); + if (targethost != null) + opts.setProperty(PROP_TARGET_HOST, targethost); + String targetport = getTargetPort(); + if (targetport != null) + opts.setProperty(PROP_TARGET_PORT, targetport); _tunnel.setClientOptions(opts); } @@ -510,10 +584,43 @@ public class TunnelController implements Logging { } } + /** + * May be restarted with restartTunnel() or startTunnel() later. + * This may not release all resources. In particular, the I2PSocketManager remains + * and it may have timer threads that continue running. + */ public void stopTunnel() { + synchronized (this) { + if (_state != TunnelState.STARTING && _state != TunnelState.RUNNING) + return; + changeState(TunnelState.STOPPING); + } + // I2PTunnel removes the session in close(), + // so save the sessions to pass to release() and TCG + Collection sessions = getAllSessions(); _tunnel.runClose(new String[] { "forced", "all" }, this); - release(); - _running = false; + release(sessions); + changeState(TunnelState.STOPPED); + } + + /** + * May NOT be restarted with restartTunnel() or startTunnel() later. + * This should release all resources. + * + * @since 0.9.17 + */ + public void destroyTunnel() { + synchronized (this) { + if (_state != TunnelState.RUNNING) + return; + changeState(TunnelState.DESTROYING); + } + // I2PTunnel removes the session in close(), + // so save the sessions to pass to release() and TCG + Collection sessions = getAllSessions(); + _tunnel.runClose(new String[] { "destroy", "all" }, this); + release(sessions); + changeState(TunnelState.DESTROYED); } public void restartTunnel() { @@ -552,16 +659,42 @@ public class TunnelController implements Logging { if (!_config.containsKey(OPT_LOW_TAGS)) _config.setProperty(OPT_LOW_TAGS, "14"); } + // same default logic as in EditBean.getSigType() + if (!isClient(type) || + type.equals(TYPE_IRC_CLIENT) || type.equals(TYPE_STD_CLIENT) || + type.equals(TYPE_SOCKS_IRC) || type.equals(TYPE_STREAMR_CLIENT) || + (type.equals(TYPE_HTTP_CLIENT) && Boolean.valueOf(getSharedClient()))) { + if (!_config.containsKey(OPT_SIG_TYPE)) + _config.setProperty(OPT_SIG_TYPE, PREFERRED_SIGTYPE.name()); + } } // tell i2ptunnel, who will tell the TunnelTask, who will tell the SocketManager setSessionOptions(); - if (_running && _sessions != null) { - for (I2PSession s : _sessions) { - // tell the router via the session - if (!s.isClosed()) { - s.updateOptions(_tunnel.getClientOptions()); + + synchronized (this) { + if (_state != TunnelState.RUNNING) { + if (_log.shouldLog(Log.DEBUG)) { + _log.debug("Not running, not updating sessions"); } + return; + } + } + // Running, so check sessions + Collection sessions = getAllSessions(); + if (sessions.isEmpty()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Running but no sessions to update"); + } + for (I2PSession s : sessions) { + // tell the router via the session + if (!s.isClosed()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Session is open, updating: " + s); + s.updateOptions(_tunnel.getClientOptions()); + } else { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Session is closed, not updating: " + s); } } } @@ -585,6 +718,34 @@ public class TunnelController implements Logging { public String getI2CPHost() { return _config.getProperty(PROP_I2CP_HOST); } public String getI2CPPort() { return _config.getProperty(PROP_I2CP_PORT); } + /** + * Is it a client or server in the UI and I2P side? + * Note that a streamr client is a UI and I2P client but a server on the localhost side. + * Note that a streamr server is a UI and I2P server but a client on the localhost side. + * + * @since 0.9.17 + */ + public boolean isClient() { + return isClient(getType()); + } + + /** + * Is it a client or server in the UI and I2P side? + * Note that a streamr client is a UI and I2P client but a server on the localhost side. + * Note that a streamr server is a UI and I2P server but a client on the localhost side. + * + * @since 0.9.17 moved from IndexBean + */ + public static boolean isClient(String type) { + return TYPE_STD_CLIENT.equals(type) || + TYPE_HTTP_CLIENT.equals(type) || + TYPE_SOCKS.equals(type) || + TYPE_SOCKS_IRC.equals(type) || + TYPE_CONNECT.equals(type) || + TYPE_STREAMR_CLIENT.equals(type) || + TYPE_IRC_CLIENT.equals(type); + } + /** * These are the ones with a prefix of "option." * @@ -609,7 +770,12 @@ public class TunnelController implements Logging { public String getTargetHost() { return _config.getProperty(PROP_TARGET_HOST); } public String getTargetPort() { return _config.getProperty(PROP_TARGET_PORT); } public String getSpoofedHost() { return _config.getProperty(PROP_SPOOFED_HOST); } + + /** + * Probably not absolute. May be null. getPrivateKeyFile() recommended. + */ public String getPrivKeyFile() { return _config.getProperty(PROP_FILE); } + public String getListenPort() { return _config.getProperty(PROP_LISTEN_PORT); } public String getTargetDestination() { return _config.getProperty(PROP_DEST); } public String getProxyList() { return _config.getProperty(PROP_PROXIES); } @@ -619,47 +785,85 @@ public class TunnelController implements Logging { public boolean getStartOnLoad() { return Boolean.parseBoolean(_config.getProperty(PROP_START, "true")); } public boolean getPersistentClientKey() { return Boolean.parseBoolean(_config.getProperty(OPT_PERSISTENT)); } + /** + * Does not necessarily exist. + * @return absolute path or null if unset + * @since 0.9.17 + */ + public File getPrivateKeyFile() { + String f = getPrivKeyFile(); + if (f == null) + return null; + f = f.trim(); + if (f.length() == 0) + return null; + File rv = new File(f); + if (!rv.isAbsolute()) + rv = new File(I2PAppContext.getGlobalContext().getConfigDir(), f); + return rv; + } + + /** + * Returns null if not running. + * @return Base64 or null + */ public String getMyDestination() { - if (_tunnel != null) { - List sessions = _tunnel.getSessions(); - for (int i = 0; i < sessions.size(); i++) { - I2PSession session = sessions.get(i); - Destination dest = session.getMyDestination(); - if (dest != null) - return dest.toBase64(); - } - } + Destination dest = getDestination(); + if (dest != null) + return dest.toBase64(); return null; } /** + * Returns null if not running. * @return "{52 chars}.b32.i2p" or null */ public String getMyDestHashBase32() { + Destination dest = getDestination(); + if (dest != null) + return dest.toBase32(); + return null; + } + + /** + * Returns null if not running. + * @return Destination or null + * @since 0.9.17 + */ + public Destination getDestination() { if (_tunnel != null) { List sessions = _tunnel.getSessions(); for (int i = 0; i < sessions.size(); i++) { I2PSession session = sessions.get(i); Destination dest = session.getMyDestination(); if (dest != null) - return dest.toBase32(); + return dest; } } return null; } - public boolean getIsRunning() { return _running; } - public boolean getIsStarting() { return _starting; } + public boolean getIsRunning() { return _state == TunnelState.RUNNING; } + public boolean getIsStarting() { return _state == TunnelState.START_ON_LOAD || _state == TunnelState.STARTING; } + /** if running but no open sessions, we are in standby */ public boolean getIsStandby() { - if (!_running) - return false; + synchronized (this) { + if (_state != TunnelState.RUNNING) + return false; + } + for (I2PSession sess : _tunnel.getSessions()) { if (!sess.isClosed()) return false; } return true; } + + /** @since 0.9.19 */ + private synchronized void changeState(TunnelState state) { + _state = state; + } /** * A text description of the tunnel. @@ -780,7 +984,7 @@ public class TunnelController implements Logging { * */ public void log(String s) { - synchronized (this) { + synchronized (_messages) { _messages.add(s); while (_messages.size() > 10) _messages.remove(0); @@ -795,11 +999,19 @@ public class TunnelController implements Logging { * @return list of messages pulled off (each is a String, earliest first) */ public List clearMessages() { - List rv = null; - synchronized (this) { + List rv; + synchronized (_messages) { rv = new ArrayList(_messages); _messages.clear(); } return rv; } + + /** + * @since 0.9.15 + */ + @Override + public String toString() { + return "TC " + getType() + ' ' + getName() + " for " + _tunnel + ' ' + _state; + } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java index a0614dceb..e35f4342a 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelControllerGroup.java @@ -9,6 +9,14 @@ import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import net.i2p.I2PAppContext; import net.i2p.app.*; @@ -36,6 +44,9 @@ public class TunnelControllerGroup implements ClientApp { static final String DEFAULT_CONFIG_FILE = "i2ptunnel.config"; private final List _controllers; + private final ReadWriteLock _controllersLock; + private boolean _controllersLoaded; + private final Object _controllersLoadedLock = new Object(); private final String _configFile; private static final String REGISTERED_NAME = "i2ptunnel"; @@ -48,6 +59,21 @@ public class TunnelControllerGroup implements ClientApp { */ private final Map> _sessions; + /** + * We keep a pool of socket handlers for all clients, + * as there is no need for isolation on the client side. + * Extending classes may use it for other purposes. + * + * May also be used by servers, carefully, + * as there is no limit on threads. + */ + private ThreadPoolExecutor _executor; + private static final AtomicLong _executorThreadCount = new AtomicLong(); + private final Object _executorLock = new Object(); + /** how long to wait before dropping an idle thread */ + private static final long HANDLER_KEEPALIVE_MS = 2*60*1000; + + /** * In I2PAppContext will instantiate if necessary and always return non-null. * As of 0.9.4, when in RouterContext, will return null (except in Android) @@ -61,7 +87,8 @@ public class TunnelControllerGroup implements ClientApp { I2PAppContext ctx = I2PAppContext.getGlobalContext(); if (SystemVersion.isAndroid() || !ctx.isRouterContext()) { _instance = new TunnelControllerGroup(ctx, null, null); - _instance.startup(); + if (!SystemVersion.isAndroid()) + _instance.startup(); } // else wait for the router to start it } return _instance; @@ -75,6 +102,7 @@ public class TunnelControllerGroup implements ClientApp { * @param mgr may be null * @param args one arg, the config file, if not absolute will be relative to the context's config dir, * if empty or null, the default is i2ptunnel.config + * @throws IllegalArgumentException if too many args * @since 0.9.4 */ public TunnelControllerGroup(I2PAppContext context, ClientAppManager mgr, String[] args) { @@ -83,6 +111,7 @@ public class TunnelControllerGroup implements ClientApp { _mgr = mgr; _log = _context.logManager().getLog(TunnelControllerGroup.class); _controllers = new ArrayList(); + _controllersLock = new ReentrantReadWriteLock(true); if (args == null || args.length <= 0) _configFile = DEFAULT_CONFIG_FILE; else if (args.length == 1) @@ -121,7 +150,20 @@ public class TunnelControllerGroup implements ClientApp { * @since 0.9.4 */ public void startup() { - loadControllers(_configFile); + try { + loadControllers(_configFile); + } catch (IllegalArgumentException iae) { + if (DEFAULT_CONFIG_FILE.equals(_configFile) && !_context.isRouterContext()) { + // for i2ptunnel command line + synchronized (_controllersLoadedLock) { + _controllersLoaded = true; + } + _log.logAlways(Log.WARN, "Not in router context and no preconfigured tunnels"); + } else { + throw iae; + } + } + startControllers(); if (_mgr != null) _mgr.register(this); // RouterAppManager registers its own shutdown hook @@ -206,46 +248,80 @@ public class TunnelControllerGroup implements ClientApp { if (_instance == this) _instance = null; } -/// fixme static - I2PTunnelClientBase.killClientExecutor(); + killClientExecutor(); changeState(STOPPED); } /** - * Load up all of the tunnels configured in the given file (but do not start - * them) + * Load up all of the tunnels configured in the given file. + * Prior to 0.9.20, also started the tunnels. + * As of 0.9.20, does not start the tunnels, you must call startup() + * or getInstance() instead of loadControllers(). * * DEPRECATED for use outside this class. Use startup() or getInstance(). * * @throws IllegalArgumentException if unable to load from file */ public synchronized void loadControllers(String configFile) { - changeState(STARTING); - Properties cfg = loadConfig(configFile); - int i = 0; - while (true) { - String type = cfg.getProperty("tunnel." + i + ".type"); - if (type == null) - break; - TunnelController controller = new TunnelController(cfg, "tunnel." + i + "."); - _controllers.add(controller); - i++; + synchronized (_controllersLoadedLock) { + if (_controllersLoaded) + return; } + + Properties cfg = loadConfig(configFile); + int i = 0; + _controllersLock.writeLock().lock(); + try { + while (true) { + String type = cfg.getProperty("tunnel." + i + ".type"); + if (type == null) + break; + TunnelController controller = new TunnelController(cfg, "tunnel." + i + "."); + _controllers.add(controller); + i++; + } + } finally { + _controllersLock.writeLock().unlock(); + } + + synchronized (_controllersLoadedLock) { + _controllersLoaded = true; + } + if (i > 0) { + if (_log.shouldLog(Log.INFO)) + _log.info(i + " controllers loaded from " + configFile); + } else { + _log.logAlways(Log.WARN, "No i2ptunnel configurations found in " + configFile); + } + } + + /** + * Start all of the tunnels. Must call loadControllers() first. + * @since 0.9.20 + */ + private synchronized void startControllers() { + changeState(STARTING); I2PAppThread startupThread = new I2PAppThread(new StartControllers(), "Startup tunnels"); startupThread.start(); - - if (_log.shouldLog(Log.INFO)) - _log.info(i + " controllers loaded from " + configFile); changeState(RUNNING); } private class StartControllers implements Runnable { public void run() { synchronized(TunnelControllerGroup.this) { - for (int i = 0; i < _controllers.size(); i++) { - TunnelController controller = _controllers.get(i); - if (controller.getStartOnLoad()) - controller.startTunnel(); + _controllersLock.readLock().lock(); + try { + if (_controllers.size() <= 0) { + _log.logAlways(Log.WARN, "No configured tunnels to start"); + return; + } + for (int i = 0; i < _controllers.size(); i++) { + TunnelController controller = _controllers.get(i); + if (controller.getStartOnLoad()) + controller.startTunnelBackground(); + } + } finally { + _controllersLock.readLock().unlock(); } } } @@ -260,6 +336,7 @@ public class TunnelControllerGroup implements ClientApp { public synchronized void reloadControllers() { unloadControllers(); loadControllers(_configFile); + startControllers(); } /** @@ -268,19 +345,40 @@ public class TunnelControllerGroup implements ClientApp { * */ public synchronized void unloadControllers() { - stopAllControllers(); - _controllers.clear(); + synchronized (_controllersLoadedLock) { + if (!_controllersLoaded) + return; + } + + _controllersLock.writeLock().lock(); + try { + destroyAllControllers(); + _controllers.clear(); + } finally { + _controllersLock.writeLock().unlock(); + } + + synchronized (_controllersLoadedLock) { + _controllersLoaded = false; + } if (_log.shouldLog(Log.INFO)) _log.info("All controllers stopped and unloaded"); } - + /** * Add the given tunnel to the set of known controllers (but dont add it to * a config file or start it or anything) * */ - public synchronized void addController(TunnelController controller) { _controllers.add(controller); } - + public synchronized void addController(TunnelController controller) { + _controllersLock.writeLock().lock(); + try { + _controllers.add(controller); + } finally { + _controllersLock.writeLock().unlock(); + } + } + /** * Stop and remove the given tunnel * @@ -290,26 +388,51 @@ public class TunnelControllerGroup implements ClientApp { if (controller == null) return new ArrayList(); controller.stopTunnel(); List msgs = controller.clearMessages(); - _controllers.remove(controller); + _controllersLock.writeLock().lock(); + try { + _controllers.remove(controller); + } finally { + _controllersLock.writeLock().unlock(); + } msgs.add("Tunnel " + controller.getName() + " removed"); return msgs; } /** - * Stop all tunnels + * Stop all tunnels. May be restarted. * * @return list of messages the tunnels generate when stopped */ public synchronized List stopAllControllers() { List msgs = new ArrayList(); + _controllersLock.readLock().lock(); + try { + for (int i = 0; i < _controllers.size(); i++) { + TunnelController controller = _controllers.get(i); + controller.stopTunnel(); + msgs.addAll(controller.clearMessages()); + } + if (_log.shouldLog(Log.INFO)) + _log.info(_controllers.size() + " controllers stopped"); + } finally { + _controllersLock.readLock().unlock(); + } + return msgs; + } + + /** + * Stop all tunnels. They may not be restarted, you must reload. + * Caller must synch. Caller must clear controller list. + * + * @since 0.9.17 + */ + private void destroyAllControllers() { for (int i = 0; i < _controllers.size(); i++) { TunnelController controller = _controllers.get(i); - controller.stopTunnel(); - msgs.addAll(controller.clearMessages()); + controller.destroyTunnel(); } if (_log.shouldLog(Log.INFO)) _log.info(_controllers.size() + " controllers stopped"); - return msgs; } /** @@ -319,14 +442,19 @@ public class TunnelControllerGroup implements ClientApp { */ public synchronized List startAllControllers() { List msgs = new ArrayList(); - for (int i = 0; i < _controllers.size(); i++) { - TunnelController controller = _controllers.get(i); - controller.startTunnelBackground(); - msgs.addAll(controller.clearMessages()); - } + _controllersLock.readLock().lock(); + try { + for (int i = 0; i < _controllers.size(); i++) { + TunnelController controller = _controllers.get(i); + controller.startTunnelBackground(); + msgs.addAll(controller.clearMessages()); + } - if (_log.shouldLog(Log.INFO)) - _log.info(_controllers.size() + " controllers started"); + if (_log.shouldLog(Log.INFO)) + _log.info(_controllers.size() + " controllers started"); + } finally { + _controllersLock.readLock().unlock(); + } return msgs; } @@ -337,13 +465,18 @@ public class TunnelControllerGroup implements ClientApp { */ public synchronized List restartAllControllers() { List msgs = new ArrayList(); - for (int i = 0; i < _controllers.size(); i++) { - TunnelController controller = _controllers.get(i); - controller.restartTunnel(); - msgs.addAll(controller.clearMessages()); + _controllersLock.readLock().lock(); + try { + for (int i = 0; i < _controllers.size(); i++) { + TunnelController controller = _controllers.get(i); + controller.restartTunnel(); + msgs.addAll(controller.clearMessages()); + } + if (_log.shouldLog(Log.INFO)) + _log.info(_controllers.size() + " controllers restarted"); + } finally { + _controllersLock.readLock().unlock(); } - if (_log.shouldLog(Log.INFO)) - _log.info(_controllers.size() + " controllers restarted"); return msgs; } @@ -352,11 +485,16 @@ public class TunnelControllerGroup implements ClientApp { * * @return list of messages the tunnels have generated */ - public synchronized List clearAllMessages() { + public List clearAllMessages() { List msgs = new ArrayList(); - for (int i = 0; i < _controllers.size(); i++) { - TunnelController controller = _controllers.get(i); - msgs.addAll(controller.clearMessages()); + _controllersLock.readLock().lock(); + try { + for (int i = 0; i < _controllers.size(); i++) { + TunnelController controller = _controllers.get(i); + msgs.addAll(controller.clearMessages()); + } + } finally { + _controllersLock.readLock().unlock(); } return msgs; } @@ -383,10 +521,15 @@ public class TunnelControllerGroup implements ClientApp { parent.mkdirs(); Properties map = new OrderedProperties(); - for (int i = 0; i < _controllers.size(); i++) { - TunnelController controller = _controllers.get(i); - Properties cur = controller.getConfig("tunnel." + i + "."); - map.putAll(cur); + _controllersLock.readLock().lock(); + try { + for (int i = 0; i < _controllers.size(); i++) { + TunnelController controller = _controllers.get(i); + Properties cur = controller.getConfig("tunnel." + i + "."); + map.putAll(cur); + } + } finally { + _controllersLock.readLock().unlock(); } DataHelper.storeProps(map, cfgFile); @@ -420,12 +563,26 @@ public class TunnelControllerGroup implements ClientApp { } /** - * Retrieve a list of tunnels known + * Retrieve a list of tunnels known. + * + * Side effect: if the tunnels have not been loaded from config yet, they + * will be. * * @return list of TunnelController objects + * @throws IllegalArgumentException if unable to load config from file */ - public synchronized List getControllers() { - return new ArrayList(_controllers); + public List getControllers() { + synchronized (_controllersLoadedLock) { + if (!_controllersLoaded) + loadControllers(_configFile); + } + + _controllersLock.readLock().lock(); + try { + return new ArrayList(_controllers); + } finally { + _controllersLock.readLock().unlock(); + } } @@ -485,4 +642,59 @@ public class TunnelControllerGroup implements ClientApp { } } } + + /** + * @return non-null + * @since 0.8.8 Moved from I2PTunnelClientBase in 0.9.18 + */ + ThreadPoolExecutor getClientExecutor() { + synchronized (_executorLock) { + if (_executor == null) + _executor = new CustomThreadPoolExecutor(); + } + return _executor; + } + + /** + * @since 0.8.8 Moved from I2PTunnelClientBase in 0.9.18 + */ + private void killClientExecutor() { + synchronized (_executorLock) { + if (_executor != null) { + _executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); + _executor.shutdownNow(); + _executor = null; + } + } + // kill the shared client, so that on restart in android + // we won't latch onto the old one + I2PTunnelClientBase.killSharedClient(); + } + + /** + * Not really needed for now but in case we want to add some hooks like afterExecute(). + * Package private for fallback in case TCG.getInstance() is null, never instantiated + * but a plugin still needs it... should be rare. + * + * @since 0.9.18 Moved from I2PTunnelClientBase + */ + static class CustomThreadPoolExecutor extends ThreadPoolExecutor { + public CustomThreadPoolExecutor() { + super(0, Integer.MAX_VALUE, HANDLER_KEEPALIVE_MS, TimeUnit.MILLISECONDS, + new SynchronousQueue(), new CustomThreadFactory()); + } + } + + /** + * Just to set the name and set Daemon + * @since 0.9.18 Moved from I2PTunnelClientBase + */ + private static class CustomThreadFactory implements ThreadFactory { + public Thread newThread(Runnable r) { + Thread rv = Executors.defaultThreadFactory().newThread(r); + rv.setName("I2PTunnel Client Runner " + _executorThreadCount.incrementAndGet()); + rv.setDaemon(true); + return rv; + } + } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/DCCClientManager.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/DCCClientManager.java index 42af9abf2..753da65ec 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/DCCClientManager.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/DCCClientManager.java @@ -109,6 +109,7 @@ public class DCCClientManager extends EventReceiver { I2PTunnelDCCClient cTunnel = new I2PTunnelDCCClient(b32, localPort, port, l, sockMgr, _dispatch, _tunnel, ++_id); cTunnel.attachEventDispatcher(this); + cTunnel.startRunning(); int lport = cTunnel.getLocalPort(); if (_log.shouldLog(Log.WARN)) _log.warn("Opened client tunnel at port " + lport + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCClient.java index e22662103..24ac12e61 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCClient.java @@ -6,6 +6,7 @@ package net.i2p.i2ptunnel.irc; import java.net.Socket; import java.io.IOException; +import net.i2p.I2PException; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketOptions; @@ -37,6 +38,9 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase { public static final String CONNECT_STOP_EVENT = "connectionStopped"; /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * * @param dest the target, presumably b32 * @param localPort if 0, use any port, get actual port selected with getLocalPort() * @throws IllegalArgumentException if the I2PTunnel does not contain @@ -51,8 +55,6 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase { _expires = tunnel.getContext().clock().now() + INBOUND_EXPIRE; setName("DCC send -> " + dest + ':' + remotePort); - - startRunning(); } /** @@ -76,8 +78,17 @@ public class I2PTunnelDCCClient extends I2PTunnelClientBase { try { i2ps = createI2PSocket(dest, opts); Thread t = new Runner(s, i2ps); - t.start(); - } catch (Exception ex) { + // we are called from an unlimited thread pool, so run inline + //t.start(); + t.run(); + } catch (IOException ex) { + _log.error("Could not make DCC connection to " + _dest + ':' + _remotePort, ex); + closeSocket(s); + if (i2ps != null) { + try { i2ps.close(); } catch (IOException ioe) {} + } + notifyEvent(CONNECT_STOP_EVENT, Integer.valueOf(getLocalPort())); + } catch (I2PException ex) { _log.error("Could not make DCC connection to " + _dest + ':' + _remotePort, ex); closeSocket(s); if (i2ps != null) { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCServer.java index 4b1b6b8f5..cab6513ad 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/I2PTunnelDCCServer.java @@ -111,7 +111,9 @@ public class I2PTunnelDCCServer extends I2PTunnelServer { _sockList.add(socket); Thread t = new I2PTunnelRunner(s, socket, slock, null, null, _sockList, (I2PTunnelRunner.FailCallback) null); - t.start(); + // run in the unlimited client pool + //t.start(); + _clientExecutor.execute(t); local.socket = socket; local.expire = getTunnel().getContext().clock().now() + OUTBOUND_EXPIRE; _active.put(Integer.valueOf(myPort), local); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IRCFilter.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IRCFilter.java index 3112c9dda..eef558837 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IRCFilter.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IRCFilter.java @@ -33,7 +33,7 @@ abstract class IRCFilter { */ public static String inboundFilter(String s, StringBuffer expectedPong, DCCHelper helper) { - String field[]=s.split(" ",4); + String field[] = DataHelper.split(s, " ", 4); String command; int idx=0; final String[] allowedCommands = @@ -274,7 +274,7 @@ abstract class IRCFilter { */ public static String outboundFilter(String s, StringBuffer expectedPong, DCCHelper helper) { - String field[]=s.split(" ",3); + String field[] = DataHelper.split(s, " ",3); if(field[0].length()==0) return null; // W T F? @@ -420,7 +420,7 @@ abstract class IRCFilter { int ctcp = msg.indexOf(0x01); if (ctcp > 0) msg = msg.substring(0, ctcp); - String[] args = msg.split(" ", 5); + String[] args = DataHelper.split(msg, " ", 5); if (args.length <= 0) return null; String type = args[0]; @@ -512,7 +512,7 @@ abstract class IRCFilter { int ctcp = msg.indexOf(0x01); if (ctcp > 0) msg = msg.substring(0, ctcp); - String[] args = msg.split(" ", 5); + String[] args = DataHelper.split(msg, " ", 5); if (args.length <= 0) return null; String type = args[0]; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IrcInboundFilter.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IrcInboundFilter.java index 5f0dd8333..2a2edf0db 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IrcInboundFilter.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IrcInboundFilter.java @@ -47,8 +47,8 @@ public class IrcInboundFilter implements Runnable { in = new BufferedReader(new InputStreamReader(remote.getInputStream(), "ISO-8859-1")); output=local.getOutputStream(); } catch (IOException e) { - if (_log.shouldLog(Log.ERROR)) - _log.error("IrcInboundFilter: no streams",e); + if (_log.shouldLog(Log.WARN)) + _log.warn("IrcInboundFilter: no streams",e); return; } if (_log.shouldLog(Log.DEBUG)) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IrcOutboundFilter.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IrcOutboundFilter.java index 5e142081a..75ce191e7 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IrcOutboundFilter.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/IrcOutboundFilter.java @@ -47,8 +47,8 @@ public class IrcOutboundFilter implements Runnable { in = new BufferedReader(new InputStreamReader(local.getInputStream(), "ISO-8859-1")); output=remote.getOutputStream(); } catch (IOException e) { - if (_log.shouldLog(Log.ERROR)) - _log.error("IrcOutboundFilter: no streams",e); + if (_log.shouldLog(Log.WARN)) + _log.warn("IrcOutboundFilter: no streams",e); return; } if (_log.shouldLog(Log.DEBUG)) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/package.html b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/package.html new file mode 100644 index 000000000..3e40205e4 --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/irc/package.html @@ -0,0 +1,7 @@ + + +

+Filters for the IRC client tunnel, and DCC handlers. +

+ + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java index 1368580c7..bd84ac9ee 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java @@ -14,6 +14,7 @@ import java.util.StringTokenizer; import net.i2p.I2PAppContext; import net.i2p.client.naming.NamingService; import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.i2ptunnel.I2PTunnelHTTPClient; import net.i2p.util.FileUtil; @@ -33,19 +34,30 @@ import net.i2p.util.Translate; */ public abstract class LocalHTTPServer { - private final static byte[] ERR_404 = - ("HTTP/1.1 404 Not Found\r\n"+ + private final static String ERR_404 = + "HTTP/1.1 404 Not Found\r\n"+ "Content-Type: text/plain\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n"+ - "HTTP Proxy local file not found") - .getBytes(); + "HTTP Proxy local file not found"; - private final static byte[] ERR_ADD = - ("HTTP/1.1 409 Bad\r\n"+ + private final static String ERR_ADD = + "HTTP/1.1 409 Bad\r\n"+ "Content-Type: text/plain\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n"+ - "Add to addressbook failed - bad parameters") - .getBytes(); + "Add to addressbook failed - bad parameters"; + + private final static String OK = + "HTTP/1.1 200 OK\r\n" + + "Content-Type: text/plain\r\n" + + "Cache-Control: max-age=86400\r\n" + + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ + "\r\n"+ + "I2P HTTP proxy OK"; /** * Very simple web server. @@ -69,14 +81,13 @@ public abstract class LocalHTTPServer { * @param targetRequest decoded path only, non-null * @param query raw (encoded), may be null */ - public static void serveLocalFile(OutputStream out, String method, String targetRequest, String query, String proxyNonce) { + public static void serveLocalFile(OutputStream out, String method, String targetRequest, + String query, String proxyNonce) throws IOException { //System.err.println("targetRequest: \"" + targetRequest + "\""); // a home page message for the curious... if (targetRequest.equals("/")) { - try { - out.write(("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: max-age=86400\r\n\r\nI2P HTTP proxy OK").getBytes()); - out.flush(); - } catch (IOException ioe) {} + out.write(OK.getBytes("UTF-8")); + out.flush(); return; } if ((method.equals("GET") || method.equals("HEAD")) && @@ -104,12 +115,10 @@ public abstract class LocalHTTPServer { else if (filename.endsWith(".jpg")) type = "image/jpeg"; else type = "text/html"; - try { - out.write("HTTP/1.1 200 OK\r\nContent-Type: ".getBytes()); - out.write(type.getBytes()); - out.write("\r\nCache-Control: max-age=86400\r\n\r\n".getBytes()); - FileUtil.readFile(filename, themesDir.getAbsolutePath(), out); - } catch (IOException ioe) {} + out.write("HTTP/1.1 200 OK\r\nContent-Type: ".getBytes("UTF-8")); + out.write(type.getBytes("UTF-8")); + out.write("\r\nCache-Control: max-age=86400\r\nConnection: close\r\nProxy-Connection: close\r\n\r\n".getBytes("UTF-8")); + FileUtil.readFile(filename, themesDir.getAbsolutePath(), out); return; } } @@ -153,64 +162,60 @@ public abstract class LocalHTTPServer { //System.err.println("book : \"" + book + "\""); //System.err.println("nonce : \"" + nonce + "\""); if (proxyNonce.equals(nonce) && url != null && host != null && dest != null) { - try { - NamingService ns = I2PAppContext.getGlobalContext().namingService(); - Properties nsOptions = new Properties(); - nsOptions.setProperty("list", book); - if (referer != null && referer.startsWith("http")) { - String from = "" + referer + ""; - nsOptions.setProperty("s", _("Added via address helper from {0}", from)); - } else { - nsOptions.setProperty("s", _("Added via address helper")); - } - boolean success = ns.put(host, dest, nsOptions); - writeRedirectPage(out, success, host, book, url); - return; - } catch (IOException ioe) {} + NamingService ns = I2PAppContext.getGlobalContext().namingService(); + Properties nsOptions = new Properties(); + nsOptions.setProperty("list", book); + if (referer != null && referer.startsWith("http")) { + String ref = DataHelper.escapeHTML(referer); + String from = "" + ref + ""; + nsOptions.setProperty("s", _t("Added via address helper from {0}", from)); + } else { + nsOptions.setProperty("s", _t("Added via address helper")); + } + boolean success = ns.put(host, dest, nsOptions); + writeRedirectPage(out, success, host, book, url); + return; } - try { - out.write(ERR_ADD); - out.flush(); - } catch (IOException ioe) {} - return; + out.write(ERR_ADD.getBytes("UTF-8")); + } else { + out.write(ERR_404.getBytes("UTF-8")); } - try { - out.write(ERR_404); - out.flush(); - } catch (IOException ioe) {} + out.flush(); } /** @since 0.8.7 */ private static void writeRedirectPage(OutputStream out, boolean success, String host, String book, String url) throws IOException { String tbook; if ("hosts.txt".equals(book)) - tbook = _("router"); + tbook = _t("router"); else if ("userhosts.txt".equals(book)) - tbook = _("master"); + tbook = _t("master"); else if ("privatehosts.txt".equals(book)) - tbook = _("private"); + tbook = _t("private"); else tbook = book; out.write(("HTTP/1.1 200 OK\r\n"+ "Content-Type: text/html; charset=UTF-8\r\n"+ + "Connection: close\r\n"+ + "Proxy-Connection: close\r\n"+ "\r\n"+ ""+ - "" + _("Redirecting to {0}", host) + "\n" + + "" + _t("Redirecting to {0}", host) + "\n" + "\n" + "\n" + "\n" + "\n" + "" + "
\n" + "

" + (success ? - _("Saved {0} to the {1} addressbook, redirecting now.", host, tbook) : - _("Failed to save {0} to the {1} addressbook, redirecting now.", host, tbook)) + + _t("Saved {0} to the {1} addressbook, redirecting now.", host, tbook) : + _t("Failed to save {0} to the {1} addressbook, redirecting now.", host, tbook)) + "

\n

" + - _("Click here if you are not redirected automatically.") + + _t("Click here if you are not redirected automatically.") + "

").getBytes("UTF-8")); I2PTunnelHTTPClient.writeFooter(out); out.flush(); @@ -245,17 +250,17 @@ public abstract class LocalHTTPServer { private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.proxy.messages"; /** lang in routerconsole.lang property, else current locale */ - protected static String _(String key) { + protected static String _t(String key) { return Translate.getString(key, I2PAppContext.getGlobalContext(), BUNDLE_NAME); } /** {0} */ - protected static String _(String key, Object o) { + protected static String _t(String key, Object o) { return Translate.getString(key, o, I2PAppContext.getGlobalContext(), BUNDLE_NAME); } /** {0} and {1} */ - protected static String _(String key, Object o, Object o2) { + protected static String _t(String key, Object o, Object o2) { return Translate.getString(key, o, o2, I2PAppContext.getGlobalContext(), BUNDLE_NAME); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/localServer/package.html b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/localServer/package.html new file mode 100644 index 000000000..dc8a69bae --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/localServer/package.html @@ -0,0 +1,7 @@ + + +

+A very simple HTTP server, used only for css and images on HTTP client proxy error pages. +

+ + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/package.html b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/package.html new file mode 100644 index 000000000..de517ffb4 --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/package.html @@ -0,0 +1,14 @@ + + +

+Implementation of preconfigured tunnels, both for clients and servers, +and a UI for adding more and editing the configuration. +Includes special-purpose tunnels for IRC, SOCKS, HTTP, and more. +

+The entry point is TunnelControllerGroup, which is started from clients.config. +Individual tunnel configuration is in i2ptunnel.config. +The primary API is TunnelControllerGroup and TunnelController. +Other classes may not be maintained as a stable API. +

+ + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java index b4363afe0..8484ef0c2 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSIRCTunnel.java @@ -55,9 +55,12 @@ public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel { Thread in = new I2PAppThread(new IrcInboundFilter(clientSock, destSock, expectedPong, _log), "SOCKS IRC Client " + id + " in", true); in.start(); - Thread out = new I2PAppThread(new IrcOutboundFilter(clientSock, destSock, expectedPong, _log), - "SOCKS IRC Client " + id + " out", true); - out.start(); + //Thread out = new I2PAppThread(new IrcOutboundFilter(clientSock, destSock, expectedPong, _log), + // "SOCKS IRC Client " + id + " out", true); + Runnable out = new IrcOutboundFilter(clientSock, destSock, expectedPong, _log); + // we are called from an unlimited thread pool, so run inline + //out.start(); + out.run(); } catch (SOCKSException e) { if (_log.shouldLog(Log.WARN)) _log.warn("Error from SOCKS connection", e); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java index 89674c592..916793941 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/I2PSOCKSTunnel.java @@ -27,25 +27,22 @@ import net.i2p.util.Log; public class I2PSOCKSTunnel extends I2PTunnelClientBase { private HashMap> proxies = null; // port# + "" or "default" -> hostname list - protected Destination outProxyDest = null; //public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest) { // I2PSOCKSTunnel(localPort, l, ownDest, (EventDispatcher)null); //} - /** @param pkf private key file name or null for transient key */ + /** + * As of 0.9.20 this is fast, and does NOT connect the manager to the router, + * or open the local socket. You MUST call startRunning() for that. + * + * @param pkf private key file name or null for transient key + */ public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel, String pkf) { super(localPort, ownDest, l, notifyThis, "SOCKS Proxy on " + tunnel.listenHost + ':' + localPort, tunnel, pkf); - if (waitEventValue("openBaseClientResult").equals("error")) { - notifyEvent("openSOCKSTunnelResult", "error"); - return; - } - setName("SOCKS Proxy on " + tunnel.listenHost + ':' + localPort); parseOptions(); - startRunning(); - notifyEvent("openSOCKSTunnelResult", "ok"); } @@ -56,7 +53,9 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase { I2PSocket destSock = serv.getDestinationI2PSocket(this); Thread t = new I2PTunnelRunner(clientSock, destSock, sockLock, null, null, mySockets, (I2PTunnelRunner.FailCallback) null); - t.start(); + // we are called from an unlimited thread pool, so run inline + //t.start(); + t.run(); } catch (SOCKSException e) { if (_log.shouldLog(Log.WARN)) _log.warn("Error from SOCKS connection", e); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/MultiSink.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/MultiSink.java index c34616a03..bc2af1514 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/MultiSink.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/MultiSink.java @@ -22,6 +22,10 @@ public class MultiSink implements Source, Sink { public void start() {} + /** + * May throw RuntimeException from underlying sinks + * @throws RuntimeException + */ public void send(Destination from, byte[] data) { Sink s = this.cache.get(from); if (s == null) { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/ReplyTracker.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/ReplyTracker.java index 7f7e0a030..7e99efa42 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/ReplyTracker.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/ReplyTracker.java @@ -23,6 +23,10 @@ public class ReplyTracker implements Source, Sink { public void start() {} + /** + * May throw RuntimeException from underlying sink + * @throws RuntimeException + */ public void send(Destination to, byte[] data) { this.cache.put(to, this.reply); this.sink.send(to, data); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java index 02c5c3b0e..5fff2c1eb 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java @@ -24,6 +24,7 @@ import net.i2p.I2PException; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketOptions; import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase; import net.i2p.i2ptunnel.I2PTunnel; @@ -226,7 +227,7 @@ public class SOCKS5Server extends SOCKSServer { } byte addr[] = new byte[addrLen]; in.readFully(addr); - connHostName = new String(addr); + connHostName = DataHelper.getUTF8(addr); } _log.debug("DOMAINNAME address type in request: " + connHostName); break; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java index e2e7edc72..6c61e0959 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java @@ -1,6 +1,7 @@ package net.i2p.i2ptunnel.socks; import net.i2p.I2PAppContext; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; /** @@ -54,7 +55,7 @@ public class SOCKSHeader { this.header = new byte[beg.length + 60 + end.length]; System.arraycopy(this.header, 0, beg, 0, beg.length); String b32 = dest.toBase32(); - System.arraycopy(this.header, beg.length, b32.getBytes(), 0, 60); + System.arraycopy(this.header, beg.length, DataHelper.getASCII(b32), 0, 60); System.arraycopy(this.header, beg.length + 60, end, 0, end.length); } @@ -65,7 +66,7 @@ public class SOCKSHeader { int namelen = (this.header[4] & 0xff); byte[] nameBytes = new byte[namelen]; System.arraycopy(nameBytes, 0, this.header, 5, namelen); - return new String(nameBytes); + return DataHelper.getUTF8(nameBytes); } public Destination getDestination() { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java index 1c348e1f4..049d190b6 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSServerFactory.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.net.Socket; import java.util.Properties; +import net.i2p.data.DataHelper; import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase; /** @@ -63,7 +64,7 @@ public class SOCKSServerFactory { case 'H': case 'P': DataOutputStream out = new DataOutputStream(s.getOutputStream()); - out.write(ERR_REQUEST_DENIED.getBytes()); + out.write(DataHelper.getASCII(ERR_REQUEST_DENIED)); throw new SOCKSException("HTTP request to socks"); default: throw new SOCKSException("SOCKS protocol version not supported (" + Integer.toHexString(socksVer) + ")"); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPPort.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPPort.java index 1f414f134..2064d698b 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPPort.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPPort.java @@ -64,6 +64,10 @@ public class SOCKSUDPPort implements Source, Sink { this.udpsource.stop(); } + /** + * May throw RuntimeException from underlying sink + * @throws RuntimeException + */ public void send(Destination from, byte[] data) { this.wrapper.send(from, data); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPUnwrapper.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPUnwrapper.java index e446398e7..89a27cde1 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPUnwrapper.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPUnwrapper.java @@ -30,6 +30,8 @@ public class SOCKSUDPUnwrapper implements Source, Sink { /** * + * May throw RuntimeException from underlying sink + * @throws RuntimeException */ public void send(Destination ignored_from, byte[] data) { SOCKSHeader h; diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPWrapper.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPWrapper.java index eab156841..daad929f4 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPWrapper.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSUDPWrapper.java @@ -25,6 +25,8 @@ public class SOCKSUDPWrapper implements Source, Sink { /** * Use the cached header, which should have the host string and port * + * May throw RuntimeException from underlying sink + * @throws RuntimeException */ public void send(Destination from, byte[] data) { if (this.sink == null) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/package.html b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/package.html new file mode 100644 index 000000000..a16de8b25 --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/package.html @@ -0,0 +1,7 @@ + + +

+SOCKS 4, 4a, and 5 client tunnels. +

+ + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/MultiSource.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/MultiSource.java index 0bb6400ec..7de086e78 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/MultiSource.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/MultiSource.java @@ -27,6 +27,10 @@ public class MultiSource implements Source, Sink { this.sinks.clear(); } + /** + * May throw RuntimeException from underlying sinks + * @throws RuntimeException + */ public void send(Destination ignored_from, byte[] data) { for(Destination dest : this.sinks) { this.sink.send(dest, data); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/Pinger.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/Pinger.java index dd7f5642d..dc4a621ea 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/Pinger.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/Pinger.java @@ -1,6 +1,9 @@ package net.i2p.i2ptunnel.streamr; import net.i2p.i2ptunnel.udp.*; +import net.i2p.I2PAppContext; +import net.i2p.util.I2PAppThread; +import net.i2p.util.Log; /** * @@ -9,7 +12,7 @@ import net.i2p.i2ptunnel.udp.*; public class Pinger implements Source, Runnable { public Pinger() { - this.thread = new Thread(this); + this.thread = new I2PAppThread(this); } public void setSink(Sink sink) { @@ -30,7 +33,9 @@ public class Pinger implements Source, Runnable { // send unsubscribe-message byte[] data = new byte[1]; data[0] = 1; - this.sink.send(null, data); + try { + this.sink.send(null, data); + } catch (RuntimeException re) {} } public void run() { @@ -40,7 +45,14 @@ public class Pinger implements Source, Runnable { int i = 0; while(this.running) { //System.out.print("p"); - this.sink.send(null, data); + try { + this.sink.send(null, data); + } catch (RuntimeException re) { + Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); + if (log.shouldWarn()) + log.warn("error sending", re); + break; + } synchronized(this.waitlock) { int delay = 10000; if (i < 5) { @@ -49,7 +61,9 @@ public class Pinger implements Source, Runnable { } try { this.waitlock.wait(delay); - } catch(InterruptedException ie) {} + } catch(InterruptedException ie) { + break; + } } } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/Subscriber.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/Subscriber.java index 300832a2f..5bf89c945 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/Subscriber.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/Subscriber.java @@ -2,9 +2,11 @@ package net.i2p.i2ptunnel.streamr; import java.util.Set; +import net.i2p.I2PAppContext; import net.i2p.data.Destination; import net.i2p.i2ptunnel.udp.*; import net.i2p.util.ConcurrentHashSet; +import net.i2p.util.Log; /** * server-mode @@ -19,10 +21,18 @@ public class Subscriber implements Sink { this.subscriptions = new ConcurrentHashSet(); } + /** + * Doesn't really "send" anywhere, just subscribes or unsubscribes the destination + * + * @param dest to subscribe or unsubscribe + * @param data must be a single byte, 0 to subscribe, 1 to unsubscribe + */ public void send(Destination dest, byte[] data) { if(dest == null || data.length < 1) { // invalid packet - // TODO: write to log + Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); + if (log.shouldWarn()) + log.warn("bad subscription from " + dest); } else { byte ctrl = data[0]; if(ctrl == 0) { @@ -40,7 +50,9 @@ public class Subscriber implements Sink { multi.remove(dest); } else { // invalid packet - // TODO: write to log + Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); + if (log.shouldWarn()) + log.warn("bad subscription from " + dest); } } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/package.html b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/package.html new file mode 100644 index 000000000..3f3f8173e --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/streamr/package.html @@ -0,0 +1,9 @@ + + +

+Special-purpose client and server tunnels for streaming UDP clients and servers, +generally for audio and video streaming. +Extends the base classes in net.i2p.i2ptunnel.udpTunnel. +

+ + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSink.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSink.java index e4f47cdaf..705200926 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSink.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSink.java @@ -32,7 +32,10 @@ public class I2PSink implements Sink { } } - /** @param src ignored */ + /** + * @param src ignored + * @throws RuntimeException if session is closed + */ public synchronized void send(Destination src, byte[] data) { //System.out.print("w"); // create payload @@ -49,9 +52,8 @@ public class I2PSink implements Sink { this.sess.sendMessage(this.dest, payload, (this.raw ? I2PSession.PROTO_DATAGRAM_RAW : I2PSession.PROTO_DATAGRAM), I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); - } catch(I2PSessionException exc) { - // TODO: handle better - exc.printStackTrace(); + } catch (I2PSessionException ise) { + throw new RuntimeException("failed to send data", ise); } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSinkAnywhere.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSinkAnywhere.java index e33d93d10..9308bd379 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSinkAnywhere.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSinkAnywhere.java @@ -31,7 +31,10 @@ public class I2PSinkAnywhere implements Sink { } } - /** @param to - where it's going */ + /** + * @param to - where it's going + * @throws RuntimeException if session is closed + */ public synchronized void send(Destination to, byte[] data) { // create payload byte[] payload; @@ -47,9 +50,8 @@ public class I2PSinkAnywhere implements Sink { this.sess.sendMessage(to, payload, (this.raw ? I2PSession.PROTO_DATAGRAM_RAW : I2PSession.PROTO_DATAGRAM), I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); - } catch(I2PSessionException exc) { - // TODO: handle better - exc.printStackTrace(); + } catch (I2PSessionException ise) { + throw new RuntimeException("failed to send data", ise); } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSource.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSource.java index 68a9d90a2..e50e1a051 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSource.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/I2PSource.java @@ -3,9 +3,12 @@ package net.i2p.i2ptunnel.udp; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import net.i2p.I2PAppContext; import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionListener; import net.i2p.client.datagram.I2PDatagramDissector; +import net.i2p.util.I2PAppThread; +import net.i2p.util.Log; /** * @@ -33,7 +36,7 @@ public class I2PSource implements Source, Runnable { this.sess.setSessionListener(new Listener()); // create thread - this.thread = new Thread(this); + this.thread = new I2PAppThread(this); } public void setSink(Sink sink) { @@ -47,7 +50,8 @@ public class I2PSource implements Source, Runnable { public void run() { // create dissector I2PDatagramDissector diss = new I2PDatagramDissector(); - while(true) { + _running = true; + while (_running) { try { // get id int id = this.queue.take(); @@ -70,7 +74,10 @@ public class I2PSource implements Source, Runnable { } //System.out.print("r"); } catch(Exception e) { - e.printStackTrace(); + Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); + if (log.shouldWarn()) + log.warn("error sending", e); + break; } } } @@ -90,11 +97,15 @@ public class I2PSource implements Source, Runnable { } public void disconnected(I2PSession arg0) { - // ignore + _running = false; + thread.interrupt(); } public void errorOccurred(I2PSession arg0, String arg1, Throwable arg2) { - // ignore + Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); + log.error(arg1, arg2); + _running = false; + thread.interrupt(); } } @@ -105,4 +116,5 @@ public class I2PSource implements Source, Runnable { protected final Thread thread; protected final boolean verify; protected final boolean raw; + private volatile boolean _running; } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/Sink.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/Sink.java index a3ddc6b84..b12539160 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/Sink.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/Sink.java @@ -7,5 +7,9 @@ import net.i2p.data.Destination; * @author welterde */ public interface Sink { + /** + * @param src some implementations may ignore + * @throws RuntimeException in some implementations + */ public void send(Destination src, byte[] data); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/UDPSink.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/UDPSink.java index 0b5905ad7..2766b1e07 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/UDPSink.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/UDPSink.java @@ -1,5 +1,6 @@ package net.i2p.i2ptunnel.udp; +import java.io.IOException; import java.net.DatagramSocket; import java.net.DatagramPacket; import java.net.InetAddress; @@ -12,13 +13,15 @@ import net.i2p.data.Destination; */ public class UDPSink implements Sink { + /** + * @throws IllegalArgumentException on DatagramSocket IOException + */ public UDPSink(InetAddress host, int port) { // create socket try { this.sock = new DatagramSocket(); - } catch(Exception e) { - // TODO: fail better - throw new RuntimeException("failed to open udp-socket", e); + } catch (IOException e) { + throw new IllegalArgumentException("failed to open udp-socket", e); } this.remoteHost = host; @@ -27,6 +30,10 @@ public class UDPSink implements Sink { this.remotePort = port; } + /** + * @param src ignored + * @throws RuntimeException on DatagramSocket IOException + */ public void send(Destination src, byte[] data) { // if data.length > this.sock.getSendBufferSize() ... @@ -36,9 +43,8 @@ public class UDPSink implements Sink { // send packet try { this.sock.send(packet); - } catch(Exception e) { - // TODO: fail a bit better - e.printStackTrace(); + } catch (IOException ioe) { + throw new RuntimeException("failed to send data", ioe); } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/UDPSource.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/UDPSource.java index 6f1a20e5f..e54394107 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/UDPSource.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/UDPSource.java @@ -1,8 +1,13 @@ package net.i2p.i2ptunnel.udp; +import java.io.IOException; import java.net.DatagramSocket; import java.net.DatagramPacket; +import net.i2p.I2PAppContext; +import net.i2p.util.I2PAppThread; +import net.i2p.util.Log; + /** * * @author welterde @@ -10,22 +15,25 @@ import java.net.DatagramPacket; public class UDPSource implements Source, Runnable { public static final int MAX_SIZE = 15360; + /** + * @throws RuntimeException on DatagramSocket IOException + */ public UDPSource(int port) { // create udp-socket try { this.sock = new DatagramSocket(port); - } catch(Exception e) { + } catch (IOException e) { throw new RuntimeException("failed to listen...", e); } // create thread - this.thread = new Thread(this); + this.thread = new I2PAppThread(this); } /** use socket from UDPSink */ public UDPSource(DatagramSocket sock) { this.sock = sock; - this.thread = new Thread(this); + this.thread = new I2PAppThread(this); } public void setSink(Sink sink) { @@ -55,7 +63,9 @@ public class UDPSource implements Source, Runnable { this.sink.send(null, nbuf); //System.out.print("i"); } catch(Exception e) { - e.printStackTrace(); + Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); + if (log.shouldWarn()) + log.warn("error sending", e); break; } } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/package.html b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/package.html new file mode 100644 index 000000000..0eb89724e --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udp/package.html @@ -0,0 +1,7 @@ + + +

+A small API used by UDP tunnels. +

+ + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java index f1e8abaab..75b0d683d 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java @@ -52,8 +52,6 @@ import net.i2p.util.EventDispatcher; private static final AtomicLong __clientId = new AtomicLong(); protected long _clientId; - protected Destination dest; - private final Object startLock = new Object(); private final I2PSession _session; @@ -98,6 +96,7 @@ import net.i2p.util.EventDispatcher; // create a session try { ByteArrayInputStream in = new ByteArrayInputStream(key); + // FIXME this may not pick up non-default I2CP host/port settings from tunnel _session = client.createSession(in, tunnel.getClientOptions()); connected(_session); } catch(Exception exc) { @@ -180,6 +179,7 @@ import net.i2p.util.EventDispatcher; * * @param to - ignored if configured for a single destination * (we use the dest specified in the constructor) + * @throws RuntimeException if session is closed */ public void send(Destination to, byte[] data) { _i2pSink.send(to, data); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPServerBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPServerBase.java index dc17522b8..ade6e3058 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPServerBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPServerBase.java @@ -87,19 +87,12 @@ public class I2PTunnelUDPServerBase extends I2PTunnelTask implements Source, Sin private void init(boolean verify, InputStream privData, String privkeyname, Logging l) { this.l = l; - int portNum = 7654; - if (getTunnel().port != null) { - try { - portNum = Integer.parseInt(getTunnel().port); - } catch (NumberFormatException nfe) { - _log.log(Log.CRIT, "Invalid port specified [" + getTunnel().port + "], reverting to " + portNum); - } - } // create i2pclient I2PClient client = I2PClientFactory.createClient(); try { + // FIXME this may not pick up non-default I2CP host/port settings from tunnel _session = client.createSession(privData, getTunnel().getClientOptions()); connected(_session); } catch(I2PSessionException exc) { @@ -195,6 +188,7 @@ public class I2PTunnelUDPServerBase extends I2PTunnelTask implements Source, Sin * Sink Methods * * @param to + * @throws RuntimeException if session is closed * */ public void send(Destination to, byte[] data) { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/GeneralHelper.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/GeneralHelper.java new file mode 100644 index 000000000..eb481f6ea --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/GeneralHelper.java @@ -0,0 +1,722 @@ +package net.i2p.i2ptunnel.ui; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; + +import net.i2p.I2PAppContext; +import net.i2p.I2PException; +import net.i2p.client.I2PClient; +import net.i2p.crypto.SigType; +import net.i2p.data.DataHelper; +import net.i2p.data.Destination; +import net.i2p.data.PrivateKeyFile; +import net.i2p.i2ptunnel.I2PTunnelClientBase; +import net.i2p.i2ptunnel.I2PTunnelHTTPClient; +import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase; +import net.i2p.i2ptunnel.I2PTunnelHTTPServer; +import net.i2p.i2ptunnel.I2PTunnelIRCClient; +import net.i2p.i2ptunnel.I2PTunnelServer; +import net.i2p.i2ptunnel.SSLClientUtil; +import net.i2p.i2ptunnel.TunnelController; +import net.i2p.i2ptunnel.TunnelControllerGroup; +import net.i2p.i2ptunnel.web.Messages; +import net.i2p.util.FileUtil; +import net.i2p.util.Log; +import net.i2p.util.SecureFile; + +/** + * General helper functions used by all UIs. + * + * @since 0.9.19 + */ +public class GeneralHelper { + public static final int RUNNING = 1; + public static final int STARTING = 2; + public static final int NOT_RUNNING = 3; + public static final int STANDBY = 4; + + protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList"; + protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList"; + + private static final String OPT = TunnelController.PFX_OPTION; + + private final I2PAppContext _context; + protected final TunnelControllerGroup _group; + + public GeneralHelper(TunnelControllerGroup tcg) { + this(I2PAppContext.getGlobalContext(), tcg); + } + + public GeneralHelper(I2PAppContext context, TunnelControllerGroup tcg) { + _context = context; + _group = tcg; + } + + public TunnelController getController(int tunnel) { + return getController(_group, tunnel); + } + public static TunnelController getController(TunnelControllerGroup tcg, int tunnel) { + if (tunnel < 0) return null; + if (tcg == null) return null; + List controllers = tcg.getControllers(); + if (controllers.size() > tunnel) + return controllers.get(tunnel); + else + return null; + } + + public List saveTunnel(int tunnel, TunnelConfig config) { + return saveTunnel(_context, _group, tunnel, config); + } + public static List saveTunnel( + I2PAppContext context, TunnelControllerGroup tcg, int tunnel, TunnelConfig config) { + List msgs = updateTunnelConfig(tcg, tunnel, config); + msgs.addAll(saveConfig(context, tcg)); + return msgs; + } + + protected static List updateTunnelConfig(TunnelControllerGroup tcg, int tunnel, TunnelConfig config) { + // Get current tunnel controller + TunnelController cur = getController(tcg, tunnel); + + Properties props = config.getConfig(); + + List msgs = new ArrayList(); + String type = props.getProperty(TunnelController.PROP_TYPE); + if (TunnelController.TYPE_STD_CLIENT.equals(type) || TunnelController.TYPE_IRC_CLIENT.equals(type)) { + // + // If we switch to SSL, create the keystore here, so we can store the new properties. + // Down in I2PTunnelClientBase it's very hard to save the config. + // + if (Boolean.parseBoolean(props.getProperty(OPT + I2PTunnelClientBase.PROP_USE_SSL))) { + try { + boolean created = SSLClientUtil.verifyKeyStore(props, OPT); + if (created) { + // config now contains new keystore props + msgs.add("Created new self-signed certificate for tunnel " + getTunnelName(tcg, tunnel)); + } + } catch (IOException ioe) { + msgs.add("Failed to create new self-signed certificate for tunnel " + + getTunnelName(tcg, tunnel) + ", check logs: " + ioe); + } + } + } + if (cur == null) { + // creating new + cur = new TunnelController(props, "", true); + tcg.addController(cur); + if (cur.getStartOnLoad()) + cur.startTunnelBackground(); + } else { + cur.setConfig(props, ""); + } + // Only modify other shared tunnels + // if the current tunnel is shared, and of supported type + if (Boolean.parseBoolean(cur.getSharedClient()) && TunnelController.isClient(cur.getType())) { + // all clients use the same I2CP session, and as such, use the same I2CP options + List controllers = tcg.getControllers(); + + for (int i = 0; i < controllers.size(); i++) { + TunnelController c = controllers.get(i); + + // Current tunnel modified by user, skip + if (c == cur) continue; + + // Only modify this non-current tunnel + // if it belongs to a shared destination, and is of supported type + if (Boolean.parseBoolean(c.getSharedClient()) && TunnelController.isClient(c.getType())) { + Properties cOpt = c.getConfig(""); + config.updateTunnelQuantities(cOpt); + cOpt.setProperty("option.inbound.nickname", TunnelConfig.SHARED_CLIENT_NICKNAME); + cOpt.setProperty("option.outbound.nickname", TunnelConfig.SHARED_CLIENT_NICKNAME); + + c.setConfig(cOpt, ""); + } + } + } + + return msgs; + } + + protected static List saveConfig(I2PAppContext context, TunnelControllerGroup tcg) { + List rv = tcg.clearAllMessages(); + try { + tcg.saveConfig(); + rv.add(0, _t("Configuration changes saved", context)); + } catch (IOException ioe) { + Log log = context.logManager().getLog(GeneralHelper.class); + log.error("Failed to save config file", ioe); + rv.add(0, _t("Failed to save configuration", context) + ": " + ioe.toString()); + } + return rv; + } + + public List deleteTunnel(int tunnel, String privKeyFile) { + return deleteTunnel(_context, _group, tunnel, privKeyFile); + } + /** + * Stop the tunnel, delete from config, + * rename the private key file if in the default directory + * + * @param privKeyFile The priv key file name from the tunnel edit form. Can + * be null if not known. + */ + public static List deleteTunnel( + I2PAppContext context, TunnelControllerGroup tcg, int tunnel, String privKeyFile) { + List msgs; + TunnelController cur = getController(tcg, tunnel); + if (cur == null) { + msgs = new ArrayList(); + msgs.add("Invalid tunnel number"); + return msgs; + } + + msgs = tcg.removeController(cur); + msgs.addAll(saveConfig(context, tcg)); + + // Rename private key file if it was a default name in + // the default directory, so it doesn't get reused when a new + // tunnel is created. + // Use configured file name if available, not the one from the form. + String pk = cur.getPrivKeyFile(); + if (pk == null) + pk = privKeyFile; + if (pk != null && pk.startsWith("i2ptunnel") && pk.endsWith("-privKeys.dat") && + ((!TunnelController.isClient(cur.getType())) || cur.getPersistentClientKey())) { + File pkf = new File(context.getConfigDir(), pk); + if (pkf.exists()) { + String name = cur.getName(); + if (name == null) { + name = cur.getDescription(); + if (name == null) { + name = cur.getType(); + if (name == null) + name = Long.toString(context.clock().now()); + } + } + name = name.replace(' ', '_').replace(':', '_').replace("..", "_").replace('/', '_').replace('\\', '_'); + name = "i2ptunnel-deleted-" + name + '-' + context.clock().now() + "-privkeys.dat"; + File backupDir = new SecureFile(context.getConfigDir(), TunnelController.KEY_BACKUP_DIR); + File to; + if (backupDir.isDirectory() || backupDir.mkdir()) + to = new File(backupDir, name); + else + to = new File(context.getConfigDir(), name); + boolean success = FileUtil.rename(pkf, to); + if (success) + msgs.add("Private key file " + pkf.getAbsolutePath() + + " renamed to " + to.getAbsolutePath()); + } + } + return msgs; + } + + // + // Accessors + // + + public String getTunnelType(int tunnel) { + TunnelController tun = getController(tunnel); + return (tun != null && tun.getType() != null) ? tun.getType() : ""; + } + + public String getTunnelName(int tunnel) { + return getTunnelName(_group, tunnel); + } + public static String getTunnelName(TunnelControllerGroup tcg, int tunnel) { + TunnelController tun = getController(tcg, tunnel); + return tun != null ? tun.getName() : null; + } + + public String getTunnelDescription(int tunnel) { + TunnelController tun = getController(tunnel); + return (tun != null && tun.getDescription() != null) ? tun.getDescription() : ""; + } + + public String getTargetHost(int tunnel) { + TunnelController tun = getController(tunnel); + return (tun != null && tun.getTargetHost() != null) ? tun.getTargetHost() : "127.0.0.1"; + } + + /** + * @param tunnel + * @return -1 if unset or invalid + */ + public int getTargetPort(int tunnel) { + TunnelController tun = getController(tunnel); + if (tun != null && tun.getTargetPort() != null) { + try { + return Integer.parseInt(tun.getTargetPort()); + } catch (NumberFormatException e) { + return -1; + } + } else + return -1; + } + + public String getSpoofedHost(int tunnel) { + TunnelController tun = getController(tunnel); + return (tun != null && tun.getSpoofedHost() != null) ? tun.getSpoofedHost() : ""; + } + + public String getPrivateKeyFile(int tunnel) { + return getPrivateKeyFile(_group, tunnel); + } + public static String getPrivateKeyFile(TunnelControllerGroup tcg, int tunnel) { + TunnelController tun = getController(tcg, tunnel); + if (tun != null && tun.getPrivKeyFile() != null) + return tun.getPrivKeyFile(); + if (tunnel < 0) + tunnel = tcg == null ? 999 : tcg.getControllers().size(); + return "i2ptunnel" + tunnel + "-privKeys.dat"; + } + + public String getClientInterface(int tunnel) { + TunnelController tun = getController(tunnel); + if (tun != null) { + if ("streamrclient".equals(tun.getType())) + return tun.getTargetHost(); + else + return tun.getListenOnInterface(); + } else + return "127.0.0.1"; + } + + public int getClientPort(int tunnel) { + TunnelController tun = getController(tunnel); + if (tun != null && tun.getListenPort() != null) { + try { + return Integer.parseInt(tun.getListenPort()); + } catch (NumberFormatException e) { + return -1; + } + } else + return -1; + } + + public int getTunnelStatus(int tunnel) { + TunnelController tun = getController(tunnel); + if (tun == null) return NOT_RUNNING; + if (tun.getIsRunning()) { + if (tun.isClient() && tun.getIsStandby()) + return STANDBY; + else + return RUNNING; + } else if (tun.getIsStarting()) return STARTING; + else return NOT_RUNNING; + } + + public String getClientDestination(int tunnel) { + TunnelController tun = getController(tunnel); + if (tun == null) return ""; + String rv; + if (TunnelController.TYPE_STD_CLIENT.equals(tun.getType()) || + TunnelController.TYPE_IRC_CLIENT.equals(tun.getType()) || + TunnelController.TYPE_STREAMR_CLIENT.equals(tun.getType())) + rv = tun.getTargetDestination(); + else + rv = tun.getProxyList(); + return rv != null ? rv : ""; + } + + /** + * Works even if tunnel is not running. + * @return Destination or null + */ + public Destination getDestination(int tunnel) { + TunnelController tun = getController(tunnel); + if (tun != null) { + Destination rv = tun.getDestination(); + if (rv != null) + return rv; + // if not running, do this the hard way + File keyFile = tun.getPrivateKeyFile(); + if (keyFile != null) { + PrivateKeyFile pkf = new PrivateKeyFile(keyFile); + try { + rv = pkf.getDestination(); + if (rv != null) + return rv; + } catch (I2PException e) { + } catch (IOException e) {} + } + } + return null; + } + + public boolean shouldStartAutomatically(int tunnel) { + TunnelController tun = getController(tunnel); + return tun != null ? tun.getStartOnLoad() : false; + } + + public boolean isSharedClient(int tunnel) { + TunnelController tun = getController(tunnel); + return tun != null ? Boolean.parseBoolean(tun.getSharedClient()) : false; + } + + public boolean shouldDelayConnect(int tunnel) { + return getProperty(tunnel, "i2p.streaming.connectDelay", 0) > 0; + } + + public boolean isInteractive(int tunnel) { + return getProperty(tunnel, "i2p.streaming.maxWindowSize", 128) == 16; + } + + public int getTunnelDepth(int tunnel, int defaultLength) { + return getProperty(tunnel, "inbound.length", defaultLength); + } + + public int getTunnelQuantity(int tunnel, int defaultQuantity) { + return getProperty(tunnel, "inbound.quantity", defaultQuantity); + } + + public int getTunnelBackupQuantity(int tunnel, int defaultBackupQuantity) { + return getProperty(tunnel, "inbound.backupQuantity", defaultBackupQuantity); + } + + public int getTunnelVariance(int tunnel, int defaultVariance) { + return getProperty(tunnel, "inbound.lengthVariance", defaultVariance); + } + + public boolean getReduceOnIdle(int tunnel, boolean def) { + return getBooleanProperty(tunnel, "i2cp.reduceOnIdle", def); + } + + public int getReduceCount(int tunnel, int def) { + return getProperty(tunnel, "i2cp.reduceQuantity", def); + } + + /** + * @param tunnel + * @param def in minutes + * @return time in minutes + */ + public int getReduceTime(int tunnel, int def) { + return getProperty(tunnel, "i2cp.reduceIdleTime", def*60*1000) / (60*1000); + } + + public int getCert(int tunnel) { + return 0; + } + + public int getEffort(int tunnel) { + return 23; + } + + public String getSigner(int tunnel) { + return ""; + } + + public boolean getEncrypt(int tunnel) { + return getBooleanProperty(tunnel, "i2cp.encryptLeaseSet"); + } + + /** + * @param newTunnelType used if tunnel < 0 + */ + public int getSigType(int tunnel, String newTunnelType) { + SigType type; + String ttype; + boolean isShared; + if (tunnel >= 0) { + Destination d = getDestination(tunnel); + if (d != null) { + type = d.getSigType(); + if (type != null) + return type.getCode(); + } + String stype = getProperty(tunnel, I2PClient.PROP_SIGTYPE, null); + type = stype != null ? SigType.parseSigType(stype) : null; + ttype = getTunnelType(tunnel); + isShared = isSharedClient(tunnel); + } else { + type = null; + ttype = newTunnelType; + isShared = false; + } + if (type == null) { + // same default logic as in TunnelController.setConfig() + if (!TunnelController.isClient(ttype) || + TunnelController.TYPE_IRC_CLIENT.equals(ttype) || + TunnelController.TYPE_SOCKS_IRC.equals(ttype) || + TunnelController.TYPE_STREAMR_CLIENT.equals(ttype) || + TunnelController.TYPE_STD_CLIENT.equals(ttype) || + (TunnelController.TYPE_HTTP_CLIENT.equals(ttype) && isShared)) + type = TunnelController.PREFERRED_SIGTYPE; + else + type = SigType.DSA_SHA1; + } + return type.getCode(); + } + + /** + * Random keys + */ + public String getInboundRandomKey(int tunnel) { + return getProperty(tunnel, "inbound.randomKey", ""); + } + + public String getOutboundRandomKey(int tunnel) { + return getProperty(tunnel, "outbound.randomKey", ""); + } + + public String getLeaseSetSigningPrivateKey(int tunnel) { + return getProperty(tunnel, "i2cp.leaseSetSigningPrivateKey", ""); + } + + public String getLeaseSetPrivateKey(int tunnel) { + return getProperty(tunnel, "i2cp.leaseSetPrivateKey", ""); + } + + public boolean getDCC(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelIRCClient.PROP_DCC); + } + + public boolean isSSLEnabled(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelServer.PROP_USE_SSL); + } + + public String getEncryptKey(int tunnel) { + return getProperty(tunnel, "i2cp.leaseSetKey", ""); + } + + public int getAccessMode(int tunnel) { + if (getBooleanProperty(tunnel, PROP_ENABLE_ACCESS_LIST)) + return 1; + if (getBooleanProperty(tunnel, PROP_ENABLE_BLACKLIST)) + return 2; + return 0; + } + + public String getAccessList(int tunnel) { + return getProperty(tunnel, "i2cp.accessList", "").replace(",", "\n"); + } + + public String getJumpList(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPClient.PROP_JUMP_SERVERS, + I2PTunnelHTTPClient.DEFAULT_JUMP_SERVERS).replace(",", "\n"); + } + + public boolean getCloseOnIdle(int tunnel, boolean def) { + return getBooleanProperty(tunnel, "i2cp.closeOnIdle", def); + } + + public int getCloseTime(int tunnel, int def) { + return getProperty(tunnel, "i2cp.closeIdleTime", def*60*1000) / (60*1000); + } + + public boolean getNewDest(int tunnel) { + return getBooleanProperty(tunnel, "i2cp.newDestOnResume") && + getBooleanProperty(tunnel, "i2cp.closeOnIdle") && + !getBooleanProperty(tunnel, "persistentClientKey"); + } + + public boolean getPersistentClientKey(int tunnel) { + return getBooleanProperty(tunnel, "persistentClientKey"); + } + + public boolean getDelayOpen(int tunnel) { + return getBooleanProperty(tunnel, "i2cp.delayOpen"); + } + + public boolean getAllowUserAgent(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_USER_AGENT); + } + + public boolean getAllowReferer(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_REFERER); + } + + public boolean getAllowAccept(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_ACCEPT); + } + + public boolean getAllowInternalSSL(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_INTERNAL_SSL); + } + + public boolean getMultihome(int tunnel) { + return getBooleanProperty(tunnel, "shouldBundleReplyInfo"); + } + + public String getProxyAuth(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_AUTH, "false"); + } + + public boolean getOutproxyAuth(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH); + } + + public String getOutproxyUsername(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER, ""); + } + + public String getOutproxyPassword(int tunnel) { + if (getOutproxyUsername(tunnel).length() <= 0) + return ""; + return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW, ""); + } + + public String getSslProxies(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPClient.PROP_SSL_OUTPROXIES, ""); + } + + /** + * Default true + */ + public boolean getUseOutproxyPlugin(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN, true); + } + + /** all of these are @since 0.8.3 */ + public int getLimitMinute(int tunnel) { + return getProperty(tunnel, TunnelConfig.PROP_MAX_CONNS_MIN, 0); + } + + public int getLimitHour(int tunnel) { + return getProperty(tunnel, TunnelConfig.PROP_MAX_CONNS_HOUR, 0); + } + + public int getLimitDay(int tunnel) { + return getProperty(tunnel, TunnelConfig.PROP_MAX_CONNS_DAY, 0); + } + + public int getTotalMinute(int tunnel) { + return getProperty(tunnel, TunnelConfig.PROP_MAX_TOTAL_CONNS_MIN, 0); + } + + public int getTotalHour(int tunnel) { + return getProperty(tunnel, TunnelConfig.PROP_MAX_TOTAL_CONNS_HOUR, 0); + } + + public int getTotalDay(int tunnel) { + return getProperty(tunnel, TunnelConfig.PROP_MAX_TOTAL_CONNS_DAY, 0); + } + + public int getMaxStreams(int tunnel) { + return getProperty(tunnel, TunnelConfig.PROP_MAX_STREAMS, 0); + } + + /** + * POST limits + * @since 0.9.9 + */ + public int getPostMax(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_MAX, 0); + } + + public int getPostTotalMax(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_TOTAL_MAX, 0); + } + + public int getPostCheckTime(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_WINDOW, I2PTunnelHTTPServer.DEFAULT_POST_WINDOW) / 60; + } + + public int getPostBanTime(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_BAN_TIME) / 60; + } + + public int getPostTotalBanTime(int tunnel) { + return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_TOTAL_BAN_TIME) / 60; + } + + public boolean getRejectInproxy(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelHTTPServer.OPT_REJECT_INPROXY); + } + + public boolean getUniqueLocal(int tunnel) { + return getBooleanProperty(tunnel, I2PTunnelServer.PROP_UNIQUE_LOCAL); + } + + public String getCustomOptionsString(int tunnel) { + TunnelController tun = getController(tunnel); + if (tun != null) { + Properties opts = tun.getClientOptionProps(); + if (opts == null) return ""; + boolean isMD5Proxy = TunnelController.TYPE_HTTP_CLIENT.equals(tun.getType()) || + TunnelController.TYPE_CONNECT.equals(tun.getType()); + Map sorted = new TreeMap(); + for (Map.Entry e : opts.entrySet()) { + String key = (String)e.getKey(); + if (TunnelConfig._noShowSet.contains(key)) + continue; + // leave in for HTTP and Connect so it can get migrated to MD5 + // hide for SOCKS until migrated to MD5 + if ((!isMD5Proxy) && + TunnelConfig._nonProxyNoShowSet.contains(key)) + continue; + sorted.put(key, (String)e.getValue()); + } + if (sorted.isEmpty()) + return ""; + StringBuilder buf = new StringBuilder(64); + boolean space = false; + for (Map.Entry e : sorted.entrySet()) { + if (space) + buf.append(' '); + else + space = true; + buf.append(e.getKey()).append('=').append(e.getValue()); + } + return DataHelper.escapeHTML(buf.toString()); + } else { + return ""; + } + } + + // + // Internal helpers + // + + private int getProperty(int tunnel, String prop, int def) { + TunnelController tun = getController(tunnel); + if (tun != null) { + Properties opts = tun.getClientOptionProps(); + if (opts != null) { + String s = opts.getProperty(prop); + if (s == null) return def; + try { + return Integer.parseInt(s); + } catch (NumberFormatException nfe) {} + } + } + return def; + } + + private String getProperty(int tunnel, String prop, String def) { + TunnelController tun = getController(tunnel); + if (tun != null) { + Properties opts = tun.getClientOptionProps(); + if (opts != null) { + String rv = opts.getProperty(prop); + if (rv != null) + return DataHelper.escapeHTML(rv); + } + } + return def; + } + + /** default is false */ + private boolean getBooleanProperty(int tunnel, String prop) { + return getBooleanProperty(tunnel, prop, false); + } + private boolean getBooleanProperty(int tunnel, String prop, boolean def) { + TunnelController tun = getController(tunnel); + if (tun != null) { + Properties opts = tun.getClientOptionProps(); + if (opts != null) + return Boolean.parseBoolean(opts.getProperty(prop)); + } + return def; + } + + protected static String _t(String key, I2PAppContext context) { + return Messages._t(key, context); + } +} diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/TunnelConfig.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/TunnelConfig.java new file mode 100644 index 000000000..c0839e503 --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/TunnelConfig.java @@ -0,0 +1,814 @@ +package net.i2p.i2ptunnel.ui; + +import java.security.GeneralSecurityException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentHashMap; + +import net.i2p.I2PAppContext; +import net.i2p.client.I2PClient; +import net.i2p.crypto.KeyGenerator; +import net.i2p.crypto.SigType; +import net.i2p.data.Base64; +import net.i2p.data.Destination; +import net.i2p.data.SimpleDataStructure; +import net.i2p.i2ptunnel.I2PTunnelClientBase; +import net.i2p.i2ptunnel.I2PTunnelConnectClient; +import net.i2p.i2ptunnel.I2PTunnelHTTPClient; +import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase; +import net.i2p.i2ptunnel.I2PTunnelHTTPServer; +import net.i2p.i2ptunnel.I2PTunnelIRCClient; +import net.i2p.i2ptunnel.I2PTunnelServer; +import net.i2p.i2ptunnel.TunnelController; +import net.i2p.util.ConcurrentHashSet; +import net.i2p.util.PasswordManager; + +/** + * Helper class to generate a valid TunnelController configuration from provided + * settings. + * + * @since 0.9.19 logic moved from IndexBean + */ +public class TunnelConfig { + public static final String SHARED_CLIENT_NICKNAME = "shared clients"; + + private static final String OPT = TunnelController.PFX_OPTION; + + protected final I2PAppContext _context; + + private String _type; + private String _name; + private String _description; + private String _i2cpHost; + private String _i2cpPort; + private int _tunnelDepth = -1; + private int _tunnelQuantity = -1; + // -2 or higher is valid + private int _tunnelVariance = -3; + private int _tunnelBackupQuantity = -1; + private boolean _connectDelay; + private String _customOptions; + private String _proxyList; + private int _port = -1; + private String _reachableBy; + private String _targetDestination; + private String _targetHost; + private int _targetPort = -1; + private String _spoofedHost; + private String _privKeyFile; + private String _profile; + private boolean _startOnLoad; + private boolean _sharedClient; + private final Set _booleanOptions; + private final Map _otherOptions; + private String _newProxyUser; + private String _newProxyPW; + private Destination _dest; + + public TunnelConfig() { + _context = I2PAppContext.getGlobalContext(); + _booleanOptions = new ConcurrentHashSet(4); + _otherOptions = new ConcurrentHashMap(4); + } + + /** + * What type of tunnel (httpclient, ircclient, client, or server). This is + * required when adding a new tunnel. + * + */ + public void setType(String type) { + _type = (type != null ? type.trim() : null); + } + public String getType() { + return _type; + } + + /** Short name of the tunnel */ + public void setName(String name) { + _name = (name != null ? name.trim() : null); + } + /** one line description */ + public void setDescription(String description) { + // '#' will blow up DataHelper.storeProps() + _description = (description != null ? description.replace('#', ' ').trim() : null); + } + /** I2CP host the router is on, ignored when in router context */ + public void setClientHost(String host) { + _i2cpHost = (host != null ? host.trim() : null); + } + /** I2CP port the router is on, ignored when in router context */ + public void setClientPort(String port) { + _i2cpPort = (port != null ? port.trim() : null); + } + /** how many hops to use for inbound tunnels */ + public void setTunnelDepth(int tunnelDepth) { + _tunnelDepth = tunnelDepth; + } + /** how many parallel inbound tunnels to use */ + public void setTunnelQuantity(int tunnelQuantity) { + _tunnelQuantity = tunnelQuantity; + } + /** how much randomisation to apply to the depth of tunnels */ + public void setTunnelVariance(int tunnelVariance) { + _tunnelVariance = tunnelVariance; + } + /** how many tunnels to hold in reserve to guard against failures */ + public void setTunnelBackupQuantity(int tunnelBackupQuantity) { + _tunnelBackupQuantity = tunnelBackupQuantity; + } + /** what I2P session overrides should be used */ + public void setCustomOptions(String customOptions) { + _customOptions = (customOptions != null ? customOptions.trim() : null); + } + /** what HTTP outproxies should be used (httpclient specific) */ + public void setProxyList(String proxyList) { + _proxyList = (proxyList != null ? proxyList.trim() : null); + } + /** what port should this client/httpclient/ircclient listen on */ + public void setPort(int port) { + _port = port; + } + /** + * what interface should this client/httpclient/ircclient listen on + */ + public void setReachableBy(String reachableBy) { + _reachableBy = (reachableBy != null ? reachableBy.trim() : null); + } + /** What peer does this client tunnel point at */ + public void setTargetDestination(String dest) { + _targetDestination = (dest != null ? dest.trim() : null); + } + /** What host does this server tunnel point at */ + public void setTargetHost(String host) { + _targetHost = (host != null ? host.trim() : null); + } + /** What port does this server tunnel point at */ + public void setTargetPort(int port) { + _targetPort = port; + } + /** What host does this http server tunnel spoof */ + public void setSpoofedHost(String host) { + _spoofedHost = (host != null ? host.trim() : null); + } + /** What filename is this server tunnel's private keys stored in */ + public void setPrivKeyFile(String file) { + _privKeyFile = (file != null ? file.trim() : null); + } + public String getPrivKeyFile() { + return _privKeyFile; + } + /** + * If called with any value, we want this tunnel to start whenever it is + * loaded (aka right now and whenever the router is started up) + */ + public void setStartOnLoad(boolean val) { + _startOnLoad = val; + } + public void setShared(boolean val) { + _sharedClient = val; + } + public void setConnectDelay(boolean val) { + _connectDelay = val; + } + public void setProfile(String profile) { + _profile = profile; + } + + public void setReduce(boolean val) { + if (val) + _booleanOptions.add("i2cp.reduceOnIdle"); + else + _booleanOptions.remove("i2cp.reduceOnIdle"); + } + public void setClose(boolean val) { + if (val) + _booleanOptions.add("i2cp.closeOnIdle"); + else + _booleanOptions.remove("i2cp.closeOnIdle"); + } + public void setEncrypt(boolean val) { + if (val) + _booleanOptions.add("i2cp.encryptLeaseSet"); + else + _booleanOptions.remove("i2cp.encryptLeaseSet"); + } + public void setDCC(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelIRCClient.PROP_DCC); + else + _booleanOptions.remove(I2PTunnelIRCClient.PROP_DCC); + } + public void setUseSSL(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelServer.PROP_USE_SSL); + else + _booleanOptions.remove(I2PTunnelServer.PROP_USE_SSL); + } + public void setRejectInproxy(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelHTTPServer.OPT_REJECT_INPROXY); + else + _booleanOptions.remove(I2PTunnelHTTPServer.OPT_REJECT_INPROXY); + } + public void setUniqueLocal(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelServer.PROP_UNIQUE_LOCAL); + else + _booleanOptions.remove(I2PTunnelServer.PROP_UNIQUE_LOCAL); + } + + protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList"; + protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList"; + + /** + * Controls how other tunnels are checked for access. + *

+ * The list used for whitelisting/blacklisting can be set with + * {@link #setAccessList(String)}. + * + * @param mode 0 for no control, 1 for whitelist, 2 for blacklist + */ + public void setAccessMode(int mode) { + switch (mode) { + case 1: + _booleanOptions.add(PROP_ENABLE_ACCESS_LIST); + _booleanOptions.remove(PROP_ENABLE_BLACKLIST); + break; + case 2: + _booleanOptions.remove(PROP_ENABLE_ACCESS_LIST); + _booleanOptions.add(PROP_ENABLE_BLACKLIST); + break; + default: + _booleanOptions.remove(PROP_ENABLE_ACCESS_LIST); + _booleanOptions.remove(PROP_ENABLE_BLACKLIST); + } + } + + public void setDelayOpen(boolean val) { + if (val) + _booleanOptions.add("i2cp.delayOpen"); + else + _booleanOptions.remove("i2cp.delayOpen"); + } + + /** + * Controls how ephemeral the I2P Destination of a client tunnel is. + *

+ * If {@link #setClose(boolean)} is set to false then mode 1 == mode 0. + * + * @param mode 0 for new dest on restart, 1 for new dest on resume from idle, 2 for persistent key + */ + public void setNewDest(int mode) { + switch (mode) { + case 1: + _booleanOptions.add("i2cp.newDestOnResume"); + _booleanOptions.remove("persistentClientKey"); + break; + case 2: + _booleanOptions.remove("i2cp.newDestOnResume"); + _booleanOptions.add("persistentClientKey"); + break; + default: + _booleanOptions.remove("i2cp.newDestOnResume"); + _booleanOptions.remove("persistentClientKey"); + } + } + + public void setReduceTime(int val) { + _otherOptions.put("i2cp.reduceIdleTime", Integer.toString(val * 60*1000)); + } + public void setReduceCount(int val) { + _otherOptions.put("i2cp.reduceQuantity", Integer.toString(val)); + } + public void setEncryptKey(String val) { + if (val != null) + _otherOptions.put("i2cp.leaseSetKey", val.trim()); + } + + public void setAccessList(String val) { + if (val != null) + _otherOptions.put("i2cp.accessList", val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ",")); + } + + public void setJumpList(String val) { + if (val != null) + _otherOptions.put(I2PTunnelHTTPClient.PROP_JUMP_SERVERS, val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ",")); + } + + public void setCloseTime(int val) { + _otherOptions.put("i2cp.closeIdleTime", Integer.toString(val * 60*1000)); + } + + public void setAllowUserAgent(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelHTTPClient.PROP_USER_AGENT); + else + _booleanOptions.remove(I2PTunnelHTTPClient.PROP_USER_AGENT); + } + public void setAllowReferer(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelHTTPClient.PROP_REFERER); + else + _booleanOptions.remove(I2PTunnelHTTPClient.PROP_REFERER); + } + public void setAllowAccept(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelHTTPClient.PROP_ACCEPT); + else + _booleanOptions.remove(I2PTunnelHTTPClient.PROP_ACCEPT); + } + public void setAllowInternalSSL(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelHTTPClient.PROP_INTERNAL_SSL); + else + _booleanOptions.remove(I2PTunnelHTTPClient.PROP_INTERNAL_SSL); + } + + public void setMultihome(boolean val) { + if (val) + _booleanOptions.add("shouldBundleReplyInfo"); + else + _booleanOptions.remove("shouldBundleReplyInfo"); + } + + /** + * Sets whether authentication should be used for client proxy tunnels. + * Supported authentication types: "basic", "digest". + * + * @param authType the authentication type, or "false" for no authentication + */ + public void setProxyAuth(String authType) { + if (authType != null) + _otherOptions.put(I2PTunnelHTTPClientBase.PROP_AUTH, authType.trim()); + } + + public void setProxyUsername(String s) { + if (s != null) + _newProxyUser = s.trim(); + } + + public void setProxyPassword(String s) { + if (s != null) + _newProxyPW = s.trim(); + } + + /** + * Sets whether authentication is required for any of the configured + * outproxies. + * + * @param val true if authentication is required, false otherwise + */ + public void setOutproxyAuth(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH); + else + _booleanOptions.remove(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH); + } + + public void setOutproxyUsername(String s) { + if (s != null) + _otherOptions.put(I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER, s.trim()); + } + + public void setOutproxyPassword(String s) { + if (s != null) + _otherOptions.put(I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW, s.trim()); + } + + public void setSslProxies(String s) { + if (s != null) + _otherOptions.put(I2PTunnelHTTPClient.PROP_SSL_OUTPROXIES, s.trim().replace(" ", ",")); + } + + public void setUseOutproxyPlugin(boolean val) { + if (val) + _booleanOptions.add(I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN); + else + _booleanOptions.remove(I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN); + } + + /** + * all of these are @since 0.8.3 (moved from IndexBean) + */ + public static final String PROP_MAX_CONNS_MIN = "i2p.streaming.maxConnsPerMinute"; + public static final String PROP_MAX_CONNS_HOUR = "i2p.streaming.maxConnsPerHour"; + public static final String PROP_MAX_CONNS_DAY = "i2p.streaming.maxConnsPerDay"; + public static final String PROP_MAX_TOTAL_CONNS_MIN = "i2p.streaming.maxTotalConnsPerMinute"; + public static final String PROP_MAX_TOTAL_CONNS_HOUR = "i2p.streaming.maxTotalConnsPerHour"; + public static final String PROP_MAX_TOTAL_CONNS_DAY = "i2p.streaming.maxTotalConnsPerDay"; + public static final String PROP_MAX_STREAMS = "i2p.streaming.maxConcurrentStreams"; + + public void setLimitMinute(int val) { + _otherOptions.put(PROP_MAX_CONNS_MIN, Integer.toString(val)); + } + + public void setLimitHour(int val) { + _otherOptions.put(PROP_MAX_CONNS_HOUR, Integer.toString(val)); + } + + public void setLimitDay(int val) { + _otherOptions.put(PROP_MAX_CONNS_DAY, Integer.toString(val)); + } + + public void setTotalMinute(int val) { + _otherOptions.put(PROP_MAX_TOTAL_CONNS_MIN, Integer.toString(val)); + } + + public void setTotalHour(int val) { + _otherOptions.put(PROP_MAX_TOTAL_CONNS_HOUR, Integer.toString(val)); + } + + public void setTotalDay(int val) { + _otherOptions.put(PROP_MAX_TOTAL_CONNS_DAY, Integer.toString(val)); + } + + public void setMaxStreams(int val) { + _otherOptions.put(PROP_MAX_STREAMS, Integer.toString(val)); + } + + /** + * POST limits + */ + public void setPostMax(int val) { + _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_MAX, Integer.toString(val)); + } + + public void setPostTotalMax(int val) { + _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_TOTAL_MAX, Integer.toString(val)); + } + + public void setPostCheckTime(int val) { + _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_WINDOW, Integer.toString(val * 60)); + } + + public void setPostBanTime(int val) { + _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_BAN_TIME, Integer.toString(val * 60)); + } + + public void setPostTotalBanTime(int val) { + _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, Integer.toString(val * 60)); + } + + public void setSigType(String val) { + if (val != null) + _otherOptions.put(I2PClient.PROP_SIGTYPE, val.trim()); + } + + /** + * Random keys + */ + public void setInboundRandomKey(String s) { + if (s != null) + _otherOptions.put("inbound.randomKey", s.trim()); + } + + public void setOutboundRandomKey(String s) { + if (s != null) + _otherOptions.put("outbound.randomKey", s.trim()); + } + + public void setLeaseSetSigningPrivateKey(String s) { + if (s != null) + _otherOptions.put("i2cp.leaseSetSigningPrivateKey", s.trim()); + } + + public void setLeaseSetPrivateKey(String s) { + if (s != null) + _otherOptions.put("i2cp.leaseSetPrivateKey", s.trim()); + } + + /** + * This is easier than requiring TunnelConfig to talk to + * TunnelControllerGroup and TunnelController. + * + * @param dest the current Destination for this tunnel. + */ + public void setDestination(Destination dest) { + _dest = dest; + } + + /** + * Based on all provided data, create a set of configuration parameters + * suitable for use in a TunnelController. This will replace (not add to) + * any existing parameters, so this should return a comprehensive mapping. + * + */ + public Properties getConfig() { + Properties config = new Properties(); + updateConfigGeneric(config); + + if ((TunnelController.isClient(_type) && !TunnelController.TYPE_STREAMR_CLIENT.equals(_type)) || + TunnelController.TYPE_STREAMR_SERVER.equals(_type)) { + // streamrserver uses interface + if (_reachableBy != null) + config.setProperty(TunnelController.PROP_INTFC, _reachableBy); + else + config.setProperty(TunnelController.PROP_INTFC, ""); + } else { + // streamrclient uses targetHost + if (_targetHost != null) + config.setProperty(TunnelController.PROP_TARGET_HOST, _targetHost); + } + + if (TunnelController.isClient(_type)) { + // generic client stuff + if (_port >= 0) + config.setProperty(TunnelController.PROP_LISTEN_PORT, Integer.toString(_port)); + config.setProperty(TunnelController.PROP_SHARED, _sharedClient + ""); + for (String p : _booleanClientOpts) + config.setProperty(OPT + p, "" + _booleanOptions.contains(p)); + for (String p : _otherClientOpts) { + if (_otherOptions.containsKey(p)) + config.setProperty(OPT + p, _otherOptions.get(p)); + } + } else { + // generic server stuff + if (_targetPort >= 0) + config.setProperty(TunnelController.PROP_TARGET_PORT, Integer.toString(_targetPort)); + for (String p : _booleanServerOpts) + config.setProperty(OPT + p, "" + _booleanOptions.contains(p)); + for (String p : _otherServerOpts) { + if (_otherOptions.containsKey(p)) + config.setProperty(OPT + p, _otherOptions.get(p)); + } + } + + // generic proxy stuff + if (TunnelController.TYPE_HTTP_CLIENT.equals(_type) || TunnelController.TYPE_CONNECT.equals(_type) || + TunnelController.TYPE_SOCKS.equals(_type) ||TunnelController.TYPE_SOCKS_IRC.equals(_type)) { + for (String p : _booleanProxyOpts) + config.setProperty(OPT + p, "" + _booleanOptions.contains(p)); + if (_proxyList != null) + config.setProperty(TunnelController.PROP_PROXIES, _proxyList); + } + + // Proxy auth including migration to MD5 + if (TunnelController.TYPE_HTTP_CLIENT.equals(_type) || TunnelController.TYPE_CONNECT.equals(_type)) { + // Migrate even if auth is disabled + // go get the old from custom options that updateConfigGeneric() put in there + String puser = OPT + I2PTunnelHTTPClientBase.PROP_USER; + String user = config.getProperty(puser); + String ppw = OPT + I2PTunnelHTTPClientBase.PROP_PW; + String pw = config.getProperty(ppw); + if (user != null && pw != null && user.length() > 0 && pw.length() > 0) { + String pmd5 = OPT + I2PTunnelHTTPClientBase.PROP_PROXY_DIGEST_PREFIX + + user + I2PTunnelHTTPClientBase.PROP_PROXY_DIGEST_SUFFIX; + if (config.getProperty(pmd5) == null) { + // not in there, migrate + String realm = _type.equals(TunnelController.TYPE_HTTP_CLIENT) ? I2PTunnelHTTPClient.AUTH_REALM + : I2PTunnelConnectClient.AUTH_REALM; + String hex = PasswordManager.md5Hex(realm, user, pw); + if (hex != null) { + config.setProperty(pmd5, hex); + config.remove(puser); + config.remove(ppw); + } + } + } + // New user/password + String auth = _otherOptions.get(I2PTunnelHTTPClientBase.PROP_AUTH); + if (auth != null && !auth.equals("false")) { + if (_newProxyUser != null && _newProxyPW != null && + _newProxyUser.length() > 0 && _newProxyPW.length() > 0) { + String pmd5 = OPT + I2PTunnelHTTPClientBase.PROP_PROXY_DIGEST_PREFIX + + _newProxyUser + I2PTunnelHTTPClientBase.PROP_PROXY_DIGEST_SUFFIX; + String realm = _type.equals(TunnelController.TYPE_HTTP_CLIENT) ? I2PTunnelHTTPClient.AUTH_REALM + : I2PTunnelConnectClient.AUTH_REALM; + String hex = PasswordManager.md5Hex(realm, _newProxyUser, _newProxyPW); + if (hex != null) + config.setProperty(pmd5, hex); + } + } + } + + if (TunnelController.TYPE_IRC_CLIENT.equals(_type) || + TunnelController.TYPE_STD_CLIENT.equals(_type) || + TunnelController.TYPE_STREAMR_CLIENT.equals(_type)) { + if (_targetDestination != null) + config.setProperty(TunnelController.PROP_DEST, _targetDestination); + } else if (TunnelController.TYPE_HTTP_SERVER.equals(_type) || + TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(_type)) { + if (_spoofedHost != null) + config.setProperty(TunnelController.PROP_SPOOFED_HOST, _spoofedHost); + for (String p : _httpServerOpts) + if (_otherOptions.containsKey(p)) + config.setProperty(OPT + p, _otherOptions.get(p)); + } + if (TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(_type)) { + if (_port >= 0) + config.setProperty(TunnelController.PROP_LISTEN_PORT, Integer.toString(_port)); + if (_reachableBy != null) + config.setProperty(TunnelController.PROP_INTFC, _reachableBy); + else if (_targetHost != null) + config.setProperty(TunnelController.PROP_INTFC, _targetHost); + else + config.setProperty(TunnelController.PROP_INTFC, ""); + } + + if (TunnelController.TYPE_IRC_CLIENT.equals(_type)) { + boolean dcc = _booleanOptions.contains(I2PTunnelIRCClient.PROP_DCC); + config.setProperty(OPT + I2PTunnelIRCClient.PROP_DCC, + "" + dcc); + // add some sane server options since they aren't in the GUI (yet) + if (dcc) { + config.setProperty(OPT + PROP_MAX_CONNS_MIN, "3"); + config.setProperty(OPT + PROP_MAX_CONNS_HOUR, "10"); + config.setProperty(OPT + PROP_MAX_TOTAL_CONNS_MIN, "5"); + config.setProperty(OPT + PROP_MAX_TOTAL_CONNS_HOUR, "25"); + } + } + + if (!TunnelController.isClient(_type) || _booleanOptions.contains("persistentClientKey")) { + // As of 0.9.17, add a persistent random key if not present + String p = OPT + "inbound.randomKey"; + if (!config.containsKey(p)) { + byte[] rk = new byte[32]; + _context.random().nextBytes(rk); + config.setProperty(p, Base64.encode(rk)); + p = OPT + "outbound.randomKey"; + _context.random().nextBytes(rk); + config.setProperty(p, Base64.encode(rk)); + } + // As of 0.9.18, add persistent leaseset keys if not present + // but only if we know the sigtype + p = OPT + "i2cp.leaseSetSigningPrivateKey"; + if (_dest != null && !config.containsKey(p)) { + try { + SigType type = _dest.getSigType(); + SimpleDataStructure keys[] = KeyGenerator.getInstance().generateSigningKeys(type); + config.setProperty(p, type.name() + ':' + keys[1].toBase64()); + p = OPT + "i2cp.leaseSetPrivateKey"; + keys = KeyGenerator.getInstance().generatePKIKeys(); + config.setProperty(p, "ELGAMAL_2048:" + keys[1].toBase64()); + } catch (GeneralSecurityException gse) { + // so much for that + } + } + } + + return config; + } + + private static final String _noShowOpts[] = { + "inbound.length", "outbound.length", "inbound.lengthVariance", "outbound.lengthVariance", + "inbound.backupQuantity", "outbound.backupQuantity", "inbound.quantity", "outbound.quantity", + "inbound.nickname", "outbound.nickname", "i2p.streaming.connectDelay", "i2p.streaming.maxWindowSize", + I2PTunnelIRCClient.PROP_DCC + }; + private static final String _booleanClientOpts[] = { + "i2cp.reduceOnIdle", "i2cp.closeOnIdle", "i2cp.newDestOnResume", "persistentClientKey", "i2cp.delayOpen", + I2PTunnelClientBase.PROP_USE_SSL, + }; + private static final String _booleanProxyOpts[] = { + I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH, + I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN, + I2PTunnelHTTPClient.PROP_USER_AGENT, + I2PTunnelHTTPClient.PROP_REFERER, + I2PTunnelHTTPClient.PROP_ACCEPT, + I2PTunnelHTTPClient.PROP_INTERNAL_SSL + }; + private static final String _booleanServerOpts[] = { + "i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", PROP_ENABLE_ACCESS_LIST, PROP_ENABLE_BLACKLIST, + I2PTunnelServer.PROP_USE_SSL, + I2PTunnelHTTPServer.OPT_REJECT_INPROXY, + I2PTunnelServer.PROP_UNIQUE_LOCAL, + "shouldBundleReplyInfo" + }; + private static final String _otherClientOpts[] = { + "i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime", + "outproxyUsername", "outproxyPassword", + I2PTunnelHTTPClient.PROP_JUMP_SERVERS, + I2PTunnelHTTPClientBase.PROP_AUTH, + I2PClient.PROP_SIGTYPE, + I2PTunnelHTTPClient.PROP_SSL_OUTPROXIES, + // following are mostly server but could also be persistent client + "inbound.randomKey", "outbound.randomKey", "i2cp.leaseSetSigningPrivateKey", "i2cp.leaseSetPrivateKey" + }; + private static final String _otherServerOpts[] = { + "i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.leaseSetKey", "i2cp.accessList", + PROP_MAX_CONNS_MIN, PROP_MAX_CONNS_HOUR, PROP_MAX_CONNS_DAY, + PROP_MAX_TOTAL_CONNS_MIN, PROP_MAX_TOTAL_CONNS_HOUR, PROP_MAX_TOTAL_CONNS_DAY, + PROP_MAX_STREAMS, I2PClient.PROP_SIGTYPE, + "inbound.randomKey", "outbound.randomKey", "i2cp.leaseSetSigningPrivateKey", "i2cp.leaseSetPrivateKey" + }; + private static final String _httpServerOpts[] = { + I2PTunnelHTTPServer.OPT_POST_WINDOW, + I2PTunnelHTTPServer.OPT_POST_BAN_TIME, + I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, + I2PTunnelHTTPServer.OPT_POST_MAX, + I2PTunnelHTTPServer.OPT_POST_TOTAL_MAX + }; + + /** + * do NOT add these to noShoOpts, we must leave them in for HTTPClient and ConnectCLient + * so they will get migrated to MD5 + * TODO migrate socks to MD5 + */ + private static final String _otherProxyOpts[] = { + "proxyUsername", "proxyPassword" + }; + + public static final Set _noShowSet = new HashSet(128); + public static final Set _nonProxyNoShowSet = new HashSet(4); + static { + _noShowSet.addAll(Arrays.asList(_noShowOpts)); + _noShowSet.addAll(Arrays.asList(_booleanClientOpts)); + _noShowSet.addAll(Arrays.asList(_booleanProxyOpts)); + _noShowSet.addAll(Arrays.asList(_booleanServerOpts)); + _noShowSet.addAll(Arrays.asList(_otherClientOpts)); + _noShowSet.addAll(Arrays.asList(_otherServerOpts)); + _noShowSet.addAll(Arrays.asList(_httpServerOpts)); + _nonProxyNoShowSet.addAll(Arrays.asList(_otherProxyOpts)); + } + + private void updateConfigGeneric(Properties config) { + config.setProperty(TunnelController.PROP_TYPE, _type); + if (_name != null) + config.setProperty(TunnelController.PROP_NAME, _name); + if (_description != null) + config.setProperty(TunnelController.PROP_DESCR, _description); + if (!_context.isRouterContext()) { + if (_i2cpHost != null) + config.setProperty(TunnelController.PROP_I2CP_HOST, _i2cpHost); + if ( (_i2cpPort != null) && (_i2cpPort.trim().length() > 0) ) { + config.setProperty(TunnelController.PROP_I2CP_PORT, _i2cpPort); + } else { + config.setProperty(TunnelController.PROP_I2CP_PORT, "7654"); + } + } + if (_privKeyFile != null) + config.setProperty(TunnelController.PROP_FILE, _privKeyFile); + + if (_customOptions != null) { + StringTokenizer tok = new StringTokenizer(_customOptions); + while (tok.hasMoreTokens()) { + String pair = tok.nextToken(); + int eq = pair.indexOf('='); + if ( (eq <= 0) || (eq >= pair.length()) ) + continue; + String key = pair.substring(0, eq); + if (_noShowSet.contains(key)) + continue; + // leave in for HTTP and Connect so it can get migrated to MD5 + // hide for SOCKS until migrated to MD5 + if ((!TunnelController.TYPE_HTTP_CLIENT.equals(_type)) && + (!TunnelController.TYPE_CONNECT.equals(_type)) && + _nonProxyNoShowSet.contains(key)) + continue; + String val = pair.substring(eq+1); + config.setProperty(OPT + key, val); + } + } + + config.setProperty(TunnelController.PROP_START, _startOnLoad + ""); + + updateTunnelQuantities(config); + if (_connectDelay) + config.setProperty("option.i2p.streaming.connectDelay", "1000"); + else + config.setProperty("option.i2p.streaming.connectDelay", "0"); + if (TunnelController.isClient(_type) && _sharedClient) { + config.setProperty("option.inbound.nickname", SHARED_CLIENT_NICKNAME); + config.setProperty("option.outbound.nickname", SHARED_CLIENT_NICKNAME); + } else if (_name != null) { + config.setProperty("option.inbound.nickname", _name); + config.setProperty("option.outbound.nickname", _name); + } + if ("interactive".equals(_profile)) + // This was 1 which doesn't make much sense + // The real way to make it interactive is to make the streaming lib + // MessageInputStream flush faster but there's no option for that yet, + // Setting it to 16 instead of the default but not sure what good that is either. + config.setProperty("option.i2p.streaming.maxWindowSize", "16"); + else + config.remove("option.i2p.streaming.maxWindowSize"); + } + + /** + * Update tunnel quantities for the provided config from this TunnelConfig. + * + * @param config the config to update. + */ + public void updateTunnelQuantities(Properties config) { + if (_tunnelQuantity >= 0) { + config.setProperty("option.inbound.quantity", Integer.toString(_tunnelQuantity)); + config.setProperty("option.outbound.quantity", Integer.toString(_tunnelQuantity)); + } + if (_tunnelDepth >= 0) { + config.setProperty("option.inbound.length", Integer.toString(_tunnelDepth)); + config.setProperty("option.outbound.length", Integer.toString(_tunnelDepth)); + } + if (_tunnelVariance >= -2) { + config.setProperty("option.inbound.lengthVariance", Integer.toString(_tunnelVariance)); + config.setProperty("option.outbound.lengthVariance", Integer.toString(_tunnelVariance)); + } + if (_tunnelBackupQuantity >= 0) { + config.setProperty("option.inbound.backupQuantity", Integer.toString(_tunnelBackupQuantity)); + config.setProperty("option.outbound.backupQuantity", Integer.toString(_tunnelBackupQuantity)); + } + } +} diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/package.html b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/package.html new file mode 100644 index 000000000..93f5dc19c --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/ui/package.html @@ -0,0 +1,8 @@ + + +

+Classes for configuring tunnels, used externally by Android. +Separated out of net.i2p.i2ptunnel.web as a publicly supported API in 0.9.19. +

+ + diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java index 019e1faaa..d960dc93a 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java @@ -8,24 +8,18 @@ package net.i2p.i2ptunnel.web; * */ +import java.io.IOException; import java.util.List; -import java.util.Map; -import java.util.Properties; import java.util.Set; -import java.util.TreeMap; -import net.i2p.client.I2PClient; +import net.i2p.I2PException; import net.i2p.crypto.SigType; import net.i2p.data.Base64; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.PrivateKeyFile; import net.i2p.data.Signature; import net.i2p.data.SigningPrivateKey; -import net.i2p.i2ptunnel.I2PTunnelHTTPClient; -import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase; -import net.i2p.i2ptunnel.I2PTunnelHTTPServer; -import net.i2p.i2ptunnel.I2PTunnelIRCClient; -import net.i2p.i2ptunnel.I2PTunnelServer; import net.i2p.i2ptunnel.TunnelController; import net.i2p.i2ptunnel.TunnelControllerGroup; import net.i2p.util.Addresses; @@ -40,6 +34,11 @@ import net.i2p.util.Addresses; public class EditBean extends IndexBean { public EditBean() { super(); } + /** + * Is it a client or server in the UI and I2P side? + * Note that a streamr client is a UI and I2P client but a server on the localhost side. + * Note that a streamr server is a UI and I2P server but a client on the localhost side. + */ public static boolean staticIsClient(int tunnel) { TunnelControllerGroup group = TunnelControllerGroup.getInstance(); if (group == null) @@ -55,36 +54,20 @@ public class EditBean extends IndexBean { } public String getTargetHost(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null && tun.getTargetHost() != null) - return tun.getTargetHost(); - else - return "127.0.0.1"; + return DataHelper.escapeHTML(_helper.getTargetHost(tunnel)); } public String getTargetPort(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null && tun.getTargetPort() != null) - return tun.getTargetPort(); - else - return ""; + int port = _helper.getTargetPort(tunnel); + return port > 0 ? "" + port : ""; } public String getSpoofedHost(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null && tun.getSpoofedHost() != null) - return tun.getSpoofedHost(); - else - return ""; + return DataHelper.escapeHTML(_helper.getSpoofedHost(tunnel)); } public String getPrivateKeyFile(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null && tun.getPrivKeyFile() != null) - return tun.getPrivKeyFile(); - if (tunnel < 0) - tunnel = _group == null ? 999 : _group.getControllers().size(); - return "i2ptunnel" + tunnel + "-privKeys.dat"; + return _helper.getPrivateKeyFile(tunnel); } public String getNameSignature(int tunnel) { @@ -107,182 +90,193 @@ public class EditBean extends IndexBean { //System.err.println("Signing " + spoof + " with " + Base64.encode(privKey.getData())); Signature sig = _context.dsa().sign(spoof.getBytes("UTF-8"), privKey); return Base64.encode(sig.getData()); - } catch (Exception e) {} + } catch (I2PException e) { + } catch (IOException e) {} } return ""; } public boolean startAutomatically(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) - return tun.getStartOnLoad(); - else - return false; + return _helper.shouldStartAutomatically(tunnel); } public boolean isSharedClient(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) - return Boolean.parseBoolean(tun.getSharedClient()); - else - return false; + return _helper.isSharedClient(tunnel); } public boolean shouldDelay(int tunnel) { - return getProperty(tunnel, "i2p.streaming.connectDelay", 0) > 0; + return _helper.shouldDelayConnect(tunnel); } public boolean isInteractive(int tunnel) { - return getProperty(tunnel, "i2p.streaming.maxWindowSize", 128) == 16; + return _helper.isInteractive(tunnel); } public int getTunnelDepth(int tunnel, int defaultLength) { - return getProperty(tunnel, "inbound.length", defaultLength); + return _helper.getTunnelDepth(tunnel, defaultLength); } public int getTunnelQuantity(int tunnel, int defaultQuantity) { - return getProperty(tunnel, "inbound.quantity", defaultQuantity); + return _helper.getTunnelQuantity(tunnel, defaultQuantity); } public int getTunnelBackupQuantity(int tunnel, int defaultBackupQuantity) { - return getProperty(tunnel, "inbound.backupQuantity", defaultBackupQuantity); + return _helper.getTunnelBackupQuantity(tunnel, defaultBackupQuantity); } public int getTunnelVariance(int tunnel, int defaultVariance) { - return getProperty(tunnel, "inbound.lengthVariance", defaultVariance); + return _helper.getTunnelVariance(tunnel, defaultVariance); } public boolean getReduce(int tunnel) { - return getBooleanProperty(tunnel, "i2cp.reduceOnIdle"); + return _helper.getReduceOnIdle(tunnel, false); } public int getReduceCount(int tunnel) { - return getProperty(tunnel, "i2cp.reduceQuantity", 1); + return _helper.getReduceCount(tunnel, 1); } public int getReduceTime(int tunnel) { - return getProperty(tunnel, "i2cp.reduceIdleTime", 20*60*1000) / (60*1000); + return _helper.getReduceTime(tunnel, 20); } public int getCert(int tunnel) { - return 0; + return _helper.getCert(tunnel); } public int getEffort(int tunnel) { - return 23; + return _helper.getEffort(tunnel); } public String getSigner(int tunnel) { - return ""; + return _helper.getSigner(tunnel); } public boolean getEncrypt(int tunnel) { - return getBooleanProperty(tunnel, "i2cp.encryptLeaseSet"); + return _helper.getEncrypt(tunnel); } - /** @since 0.9.12 */ - public int getSigType(int tunnel) { - return getProperty(tunnel, I2PClient.PROP_SIGTYPE, 0); + /** + * @param newTunnelType used if tunnel < 0 + * @since 0.9.12 + */ + public int getSigType(int tunnel, String newTunnelType) { + return _helper.getSigType(tunnel, newTunnelType); } /** @since 0.9.12 */ public boolean isSigTypeAvailable(int code) { - SigType type = SigType.getByCode(code); - return type != null && type.isAvailable(); + return SigType.isAvailable(code); } + /** + * Random keys, hidden in forms + * @since 0.9.18 + */ + public String getKey1(int tunnel) { + return _helper.getInboundRandomKey(tunnel); + } + + public String getKey2(int tunnel) { + return _helper.getOutboundRandomKey(tunnel); + } + + public String getKey3(int tunnel) { + return _helper.getLeaseSetSigningPrivateKey(tunnel); + } + + public String getKey4(int tunnel) { + return _helper.getLeaseSetPrivateKey(tunnel); + } + /** @since 0.8.9 */ public boolean getDCC(int tunnel) { - return getBooleanProperty(tunnel, I2PTunnelIRCClient.PROP_DCC); + return _helper.getDCC(tunnel); } public String getEncryptKey(int tunnel) { - return getProperty(tunnel, "i2cp.leaseSetKey", ""); + return _helper.getEncryptKey(tunnel); } public String getAccessMode(int tunnel) { - if (getBooleanProperty(tunnel, PROP_ENABLE_ACCESS_LIST)) - return "1"; - if (getBooleanProperty(tunnel, PROP_ENABLE_BLACKLIST)) - return "2"; - return "0"; + return Integer.toString(_helper.getAccessMode(tunnel)); } public String getAccessList(int tunnel) { - return getProperty(tunnel, "i2cp.accessList", "").replace(",", "\n"); + return _helper.getAccessList(tunnel); } public String getJumpList(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPClient.PROP_JUMP_SERVERS, - I2PTunnelHTTPClient.DEFAULT_JUMP_SERVERS).replace(",", "\n"); + return _helper.getJumpList(tunnel); } public boolean getClose(int tunnel) { - return getBooleanProperty(tunnel, "i2cp.closeOnIdle"); + return _helper.getCloseOnIdle(tunnel, false); } public int getCloseTime(int tunnel) { - return getProperty(tunnel, "i2cp.closeIdleTime", 30*60*1000) / (60*1000); + return _helper.getCloseTime(tunnel, 30); } public boolean getNewDest(int tunnel) { - return getBooleanProperty(tunnel, "i2cp.newDestOnResume") && - getBooleanProperty(tunnel, "i2cp.closeOnIdle") && - !getBooleanProperty(tunnel, "persistentClientKey"); + return _helper.getNewDest(tunnel); } public boolean getPersistentClientKey(int tunnel) { - return getBooleanProperty(tunnel, "persistentClientKey"); + return _helper.getPersistentClientKey(tunnel); } public boolean getDelayOpen(int tunnel) { - return getBooleanProperty(tunnel, "i2cp.delayOpen"); + return _helper.getDelayOpen(tunnel); } /** @since 0.9.14 */ public boolean getAllowUserAgent(int tunnel) { - return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_USER_AGENT); + return _helper.getAllowUserAgent(tunnel); } /** @since 0.9.14 */ public boolean getAllowReferer(int tunnel) { - return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_REFERER); + return _helper.getAllowReferer(tunnel); } /** @since 0.9.14 */ public boolean getAllowAccept(int tunnel) { - return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_ACCEPT); + return _helper.getAllowAccept(tunnel); } /** @since 0.9.14 */ public boolean getAllowInternalSSL(int tunnel) { - return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_INTERNAL_SSL); + return _helper.getAllowInternalSSL(tunnel); + } + + /** @since 0.9.18 */ + public boolean getMultihome(int tunnel) { + return _helper.getMultihome(tunnel); } /** all proxy auth @since 0.8.2 */ public boolean getProxyAuth(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_AUTH, "false") != "false"; + return _helper.getProxyAuth(tunnel) != "false"; } - + // TODO think public boolean getOutproxyAuth(int tunnel) { - return getBooleanProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH) && + return _helper.getOutproxyAuth(tunnel) && getOutproxyUsername(tunnel).length() > 0 && getOutproxyPassword(tunnel).length() > 0; } public String getOutproxyUsername(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER, ""); + return _helper.getOutproxyUsername(tunnel); } public String getOutproxyPassword(int tunnel) { - if (getOutproxyUsername(tunnel).length() <= 0) - return ""; - return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW, ""); + return _helper.getOutproxyPassword(tunnel); } /** @since 0.9.11 */ public String getSslProxies(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPClient.PROP_SSL_OUTPROXIES, ""); + return _helper.getSslProxies(tunnel); } /** @@ -290,101 +284,65 @@ public class EditBean extends IndexBean { * @since 0.9.11 */ public boolean getUseOutproxyPlugin(int tunnel) { - return Boolean.parseBoolean(getProperty(tunnel, I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN, "true")); + return _helper.getUseOutproxyPlugin(tunnel); } /** all of these are @since 0.8.3 */ - public String getLimitMinute(int tunnel) { - return getProperty(tunnel, PROP_MAX_CONNS_MIN, "0"); + public int getLimitMinute(int tunnel) { + return _helper.getLimitMinute(tunnel); } - public String getLimitHour(int tunnel) { - return getProperty(tunnel, PROP_MAX_CONNS_HOUR, "0"); + public int getLimitHour(int tunnel) { + return _helper.getLimitHour(tunnel); } - public String getLimitDay(int tunnel) { - return getProperty(tunnel, PROP_MAX_CONNS_DAY, "0"); + public int getLimitDay(int tunnel) { + return _helper.getLimitDay(tunnel); } - public String getTotalMinute(int tunnel) { - return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_MIN, "0"); + public int getTotalMinute(int tunnel) { + return _helper.getTotalMinute(tunnel); } - public String getTotalHour(int tunnel) { - return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_HOUR, "0"); + public int getTotalHour(int tunnel) { + return _helper.getTotalHour(tunnel); } - public String getTotalDay(int tunnel) { - return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_DAY, "0"); + public int getTotalDay(int tunnel) { + return _helper.getTotalDay(tunnel); } - public String getMaxStreams(int tunnel) { - return getProperty(tunnel, PROP_MAX_STREAMS, "0"); + public int getMaxStreams(int tunnel) { + return _helper.getMaxStreams(tunnel); } /** * POST limits * @since 0.9.9 */ - public String getPostMax(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_MAX, "0"); + public int getPostMax(int tunnel) { + return _helper.getPostMax(tunnel); } - public String getPostTotalMax(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_TOTAL_MAX, "0"); + public int getPostTotalMax(int tunnel) { + return _helper.getPostTotalMax(tunnel); } public int getPostCheckTime(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_WINDOW, I2PTunnelHTTPServer.DEFAULT_POST_WINDOW) / 60; + return _helper.getPostCheckTime(tunnel); } public int getPostBanTime(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_BAN_TIME) / 60; + return _helper.getPostBanTime(tunnel); } public int getPostTotalBanTime(int tunnel) { - return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_TOTAL_BAN_TIME) / 60; + return _helper.getPostTotalBanTime(tunnel); } /** @since 0.9.13 */ public boolean getUniqueLocal(int tunnel) { - return getBooleanProperty(tunnel, I2PTunnelServer.PROP_UNIQUE_LOCAL); - } - - private int getProperty(int tunnel, String prop, int def) { - TunnelController tun = getController(tunnel); - if (tun != null) { - Properties opts = getOptions(tun); - if (opts != null) { - String s = opts.getProperty(prop); - if (s == null) return def; - try { - return Integer.parseInt(s); - } catch (NumberFormatException nfe) {} - } - } - return def; - } - - private String getProperty(int tunnel, String prop, String def) { - TunnelController tun = getController(tunnel); - if (tun != null) { - Properties opts = getOptions(tun); - if (opts != null) - return opts.getProperty(prop, def); - } - return def; - } - - /** default is false */ - private boolean getBooleanProperty(int tunnel, String prop) { - TunnelController tun = getController(tunnel); - if (tun != null) { - Properties opts = getOptions(tun); - if (opts != null) - return Boolean.parseBoolean(opts.getProperty(prop)); - } - return false; + return _helper.getUniqueLocal(tunnel); } /** @since 0.8.3 */ @@ -404,7 +362,7 @@ public class EditBean extends IndexBean { public String getI2CPHost(int tunnel) { if (_context.isRouterContext()) - return _("internal"); + return _t("internal"); TunnelController tun = getController(tunnel); if (tun != null) return tun.getI2CPHost(); @@ -414,7 +372,7 @@ public class EditBean extends IndexBean { public String getI2CPPort(int tunnel) { if (_context.isRouterContext()) - return _("internal"); + return _t("internal"); TunnelController tun = getController(tunnel); if (tun != null) return tun.getI2CPPort(); @@ -423,49 +381,7 @@ public class EditBean extends IndexBean { } public String getCustomOptions(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) { - Properties opts = getOptions(tun); - if (opts == null) return ""; - boolean isMD5Proxy = TunnelController.TYPE_HTTP_CLIENT.equals(tun.getType()) || - TunnelController.TYPE_CONNECT.equals(tun.getType()); - Map sorted = new TreeMap(); - for (Map.Entry e : opts.entrySet()) { - String key = (String)e.getKey(); - if (_noShowSet.contains(key)) - continue; - // leave in for HTTP and Connect so it can get migrated to MD5 - // hide for SOCKS until migrated to MD5 - if ((!isMD5Proxy) && - _nonProxyNoShowSet.contains(key)) - continue; - sorted.put(key, (String)e.getValue()); - } - if (sorted.isEmpty()) - return ""; - StringBuilder buf = new StringBuilder(64); - boolean space = false; - for (Map.Entry e : sorted.entrySet()) { - if (space) - buf.append(' '); - else - space = true; - buf.append(e.getKey()).append('=').append(e.getValue()); - } - return buf.toString(); - } else { - return ""; - } - } - - /** - * Retrieve the client options from the tunnel - * - * @return map of name=val to be used as I2P session options - */ - private static Properties getOptions(TunnelController controller) { - if (controller == null) return null; - return controller.getClientOptionProps(); + return _helper.getCustomOptionsString(tunnel); } private static final String PROP_ADVANCED = "routerconsole.advanced"; @@ -494,11 +410,11 @@ public class EditBean extends IndexBean { if (i <= 3) { buf.append(" ("); if (i == 1) - buf.append(_("lower bandwidth and reliability")); + buf.append(_t("lower bandwidth and reliability")); else if (i == 2) - buf.append(_("standard bandwidth and reliability")); + buf.append(_t("standard bandwidth and reliability")); else if (i == 3) - buf.append(_("higher bandwidth and reliability")); + buf.append(_t("higher bandwidth and reliability")); buf.append(')'); } buf.append("\n"); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java index fc5ca687b..2f2509c08 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java @@ -11,38 +11,29 @@ package net.i2p.i2ptunnel.web; import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.concurrent.ConcurrentHashMap; import net.i2p.I2PAppContext; +import net.i2p.I2PException; import net.i2p.app.ClientAppManager; import net.i2p.app.Outproxy; -import net.i2p.client.I2PClient; import net.i2p.data.Certificate; +import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.PrivateKeyFile; import net.i2p.data.SessionKey; -import net.i2p.i2ptunnel.I2PTunnelConnectClient; import net.i2p.i2ptunnel.I2PTunnelHTTPClient; import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase; import net.i2p.i2ptunnel.I2PTunnelHTTPServer; -import net.i2p.i2ptunnel.I2PTunnelIRCClient; import net.i2p.i2ptunnel.I2PTunnelServer; import net.i2p.i2ptunnel.TunnelController; import net.i2p.i2ptunnel.TunnelControllerGroup; +import net.i2p.i2ptunnel.ui.GeneralHelper; +import net.i2p.i2ptunnel.ui.TunnelConfig; import net.i2p.util.Addresses; -import net.i2p.util.ConcurrentHashSet; -import net.i2p.util.FileUtil; import net.i2p.util.Log; -import net.i2p.util.PasswordManager; -import net.i2p.util.SecureFile; /** * Simple accessor for exposing tunnel info, but also an ugly form handler @@ -55,6 +46,7 @@ public class IndexBean { protected final I2PAppContext _context; protected final Log _log; protected final TunnelControllerGroup _group; + protected final GeneralHelper _helper; private final String _fatalError; private String _action; private int _tunnel; @@ -63,41 +55,16 @@ public class IndexBean { private String _curNonce; //private long _nextNonce; - private String _type; - private String _name; - private String _description; - private String _i2cpHost; - private String _i2cpPort; - private String _tunnelDepth; - private String _tunnelQuantity; - private String _tunnelVariance; - private String _tunnelBackupQuantity; - private boolean _connectDelay; - private String _customOptions; - private String _proxyList; - private String _port; - private String _reachableBy; - private String _targetDestination; - private String _targetHost; - private String _targetPort; - private String _spoofedHost; - private String _privKeyFile; - private String _profile; - private boolean _startOnLoad; - private boolean _sharedClient; + private final TunnelConfig _config; private boolean _removeConfirmed; - private final Set _booleanOptions; - private final Map _otherOptions; private int _hashCashValue; private int _certType; private String _certSigner; - private String _newProxyUser; - private String _newProxyPW; - public static final int RUNNING = 1; - public static final int STARTING = 2; - public static final int NOT_RUNNING = 3; - public static final int STANDBY = 4; + public static final int RUNNING = GeneralHelper.RUNNING; + public static final int STARTING = GeneralHelper.STARTING; + public static final int NOT_RUNNING = GeneralHelper.NOT_RUNNING; + public static final int STANDBY = GeneralHelper.STANDBY; //static final String PROP_NONCE = IndexBean.class.getName() + ".nonce"; //static final String PROP_NONCE_OLD = PROP_NONCE + '2'; @@ -106,13 +73,11 @@ public class IndexBean { /** store nonces in a static FIFO instead of in System Properties @since 0.8.1 */ private static final List _nonces = new ArrayList(MAX_NONCES + 1); - static final String CLIENT_NICKNAME = "shared clients"; public static final String PROP_THEME_NAME = "routerconsole.theme"; public static final String DEFAULT_THEME = "light"; public static final String PROP_CSS_DISABLED = "routerconsole.css.disabled"; public static final String PROP_JS_DISABLED = "routerconsole.javascript.disabled"; private static final String PROP_PW_ENABLE = "routerconsole.auth.enable"; - private static final String OPT = TunnelController.PFX_OPTION; public IndexBean() { _context = I2PAppContext.getGlobalContext(); @@ -121,19 +86,19 @@ public class IndexBean { String error; try { tcg = TunnelControllerGroup.getInstance(); - error = tcg == null ? _("Tunnels are not initialized yet, please reload in two minutes.") + error = tcg == null ? _t("Tunnels are not initialized yet, please reload in two minutes.") : null; } catch (IllegalArgumentException iae) { tcg = null; error = iae.toString(); } _group = tcg; + _helper = new GeneralHelper(_context, _group); _fatalError = error; _tunnel = -1; _curNonce = "-1"; addNonce(); - _booleanOptions = new ConcurrentHashSet(4); - _otherOptions = new ConcurrentHashMap(4); + _config = new TunnelConfig(); } /** @@ -194,9 +159,9 @@ public class IndexBean { // If passwords are turned on, all is assumed good if (!_context.getBooleanProperty(PROP_PW_ENABLE) && !haveNonce(_curNonce)) - return _("Invalid form submission, probably because you used the 'back' or 'reload' button on your browser. Please resubmit.") + return _t("Invalid form submission, probably because you used the 'back' or 'reload' button on your browser. Please resubmit.") + ' ' + - _("If the problem persists, verify that you have cookies enabled in your browser."); + _t("If the problem persists, verify that you have cookies enabled in your browser."); if ("Stop all".equals(_action)) return stopAll(); else if ("Start all".equals(_action)) @@ -242,7 +207,7 @@ public class IndexBean { private String reloadConfig() { _group.reloadControllers(); - return _("Configuration reloaded for all tunnels"); + return _t("Configuration reloaded for all tunnels"); } private String start() { @@ -255,7 +220,8 @@ public class IndexBean { // give the messages a chance to make it to the window try { Thread.sleep(1000); } catch (InterruptedException ie) {} // and give them something to look at in any case - return _("Starting tunnel") + ' ' + getTunnelName(_tunnel) + "…"; + // FIXME name will be HTML escaped twice + return _t("Starting tunnel") + ' ' + getTunnelName(_tunnel) + "..."; } private String stop() { @@ -268,80 +234,15 @@ public class IndexBean { // give the messages a chance to make it to the window try { Thread.sleep(1000); } catch (InterruptedException ie) {} // and give them something to look at in any case - return _("Stopping tunnel") + ' ' + getTunnelName(_tunnel) + "…"; + // FIXME name will be HTML escaped twice + return _t("Stopping tunnel") + ' ' + getTunnelName(_tunnel) + "..."; } private String saveChanges() { - // Get current tunnel controller - TunnelController cur = getController(_tunnel); - - Properties config = getConfig(); - - if (cur == null) { - // creating new - cur = new TunnelController(config, "", true); - _group.addController(cur); - if (cur.getStartOnLoad()) - cur.startTunnelBackground(); - } else { - cur.setConfig(config, ""); - } - // Only modify other shared tunnels - // if the current tunnel is shared, and of supported type - if (Boolean.parseBoolean(cur.getSharedClient()) && isClient(cur.getType())) { - // all clients use the same I2CP session, and as such, use the same I2CP options - List controllers = _group.getControllers(); - - for (int i = 0; i < controllers.size(); i++) { - TunnelController c = controllers.get(i); - - // Current tunnel modified by user, skip - if (c == cur) continue; - - // Only modify this non-current tunnel - // if it belongs to a shared destination, and is of supported type - if (Boolean.parseBoolean(c.getSharedClient()) && isClient(c.getType())) { - Properties cOpt = c.getConfig(""); - if (_tunnelQuantity != null) { - cOpt.setProperty("option.inbound.quantity", _tunnelQuantity); - cOpt.setProperty("option.outbound.quantity", _tunnelQuantity); - } - if (_tunnelDepth != null) { - cOpt.setProperty("option.inbound.length", _tunnelDepth); - cOpt.setProperty("option.outbound.length", _tunnelDepth); - } - if (_tunnelVariance != null) { - cOpt.setProperty("option.inbound.lengthVariance", _tunnelVariance); - cOpt.setProperty("option.outbound.lengthVariance", _tunnelVariance); - } - if (_tunnelBackupQuantity != null) { - cOpt.setProperty("option.inbound.backupQuantity", _tunnelBackupQuantity); - cOpt.setProperty("option.outbound.backupQuantity", _tunnelBackupQuantity); - } - cOpt.setProperty("option.inbound.nickname", CLIENT_NICKNAME); - cOpt.setProperty("option.outbound.nickname", CLIENT_NICKNAME); - - c.setConfig(cOpt, ""); - } - } - } - - List msgs = doSave(); - return getMessages(msgs); + // FIXME name will be HTML escaped twice + return getMessages(_helper.saveTunnel(_tunnel, _config)); } - private List doSave() { - List rv = _group.clearAllMessages(); - try { - _group.saveConfig(); - rv.add(0, _("Configuration changes saved")); - } catch (IOException ioe) { - _log.error("Failed to save config file", ioe); - rv.add(0, _("Failed to save configuration") + ": " + ioe.toString()); - } - return rv; - } - /** * Stop the tunnel, delete from config, * rename the private key file if in the default directory @@ -349,54 +250,15 @@ public class IndexBean { private String deleteTunnel() { if (!_removeConfirmed) return "Please confirm removal"; - - TunnelController cur = getController(_tunnel); - if (cur == null) - return "Invalid tunnel number"; - - List msgs = _group.removeController(cur); - msgs.addAll(doSave()); - // Rename private key file if it was a default name in - // the default directory, so it doesn't get reused when a new - // tunnel is created. - // Use configured file name if available, not the one from the form. - String pk = cur.getPrivKeyFile(); - if (pk == null) - pk = _privKeyFile; - if (pk != null && pk.startsWith("i2ptunnel") && pk.endsWith("-privKeys.dat") && - ((!isClient(cur.getType())) || cur.getPersistentClientKey())) { - File pkf = new File(_context.getConfigDir(), pk); - if (pkf.exists()) { - String name = cur.getName(); - if (name == null) { - name = cur.getDescription(); - if (name == null) { - name = cur.getType(); - if (name == null) - name = Long.toString(_context.clock().now()); - } - } - name = "i2ptunnel-deleted-" + name.replace(' ', '_') + '-' + _context.clock().now() + "-privkeys.dat"; - File backupDir = new SecureFile(_context.getConfigDir(), TunnelController.KEY_BACKUP_DIR); - File to; - if (backupDir.isDirectory() || backupDir.mkdir()) - to = new File(backupDir, name); - else - to = new File(_context.getConfigDir(), name); - boolean success = FileUtil.rename(pkf, to); - if (success) - msgs.add("Private key file " + pkf.getAbsolutePath() + - " renamed to " + to.getAbsolutePath()); - } - } - return getMessages(msgs); + return getMessages(_helper.deleteTunnel(_tunnel, _config.getPrivKeyFile())); } /** * Executes any action requested (start/stop/etc) and dump out the * messages. * + * @return HTML escaped */ public String getMessages() { if (_group == null) @@ -405,13 +267,14 @@ public class IndexBean { StringBuilder buf = new StringBuilder(512); if (_action != null) { try { - buf.append(processAction()).append("\n"); - } catch (Exception e) { + buf.append(processAction()).append('\n'); + } catch (RuntimeException e) { _log.log(Log.CRIT, "Error processing " + _action, e); + buf.append("Error: ").append(e.toString()).append('\n'); } } getMessages(_group.clearAllMessages(), buf); - return buf.toString(); + return DataHelper.escapeHTML(buf.toString()); } //// @@ -424,13 +287,11 @@ public class IndexBean { } public boolean allowCSS() { - String css = _context.getProperty(PROP_CSS_DISABLED); - return (css == null); + return !_context.getBooleanProperty(PROP_CSS_DISABLED); } public boolean allowJS() { - String js = _context.getProperty(PROP_JS_DISABLED); - return (js == null); + return !_context.getBooleanProperty(PROP_JS_DISABLED); } public int getTunnelCount() { @@ -438,39 +299,40 @@ public class IndexBean { return _group.getControllers().size(); } + /** + * Is it a client or server in the UI and I2P side? + * Note that a streamr client is a UI and I2P client but a server on the localhost side. + * Note that a streamr server is a UI and I2P server but a client on the localhost side. + */ public boolean isClient(int tunnelNum) { TunnelController cur = getController(tunnelNum); if (cur == null) return false; - return isClient(cur.getType()); + return cur.isClient(); } + /** + * Is it a client or server in the UI and I2P side? + * Note that a streamr client is a UI and I2P client but a server on the localhost side. + * Note that a streamr server is a UI and I2P server but a client on the localhost side. + */ public static boolean isClient(String type) { - return ( (TunnelController.TYPE_STD_CLIENT.equals(type)) || - (TunnelController.TYPE_HTTP_CLIENT.equals(type)) || - (TunnelController.TYPE_SOCKS.equals(type)) || - (TunnelController.TYPE_SOCKS_IRC.equals(type)) || - (TunnelController.TYPE_CONNECT.equals(type)) || - (TunnelController.TYPE_STREAMR_CLIENT.equals(type)) || - (TunnelController.TYPE_IRC_CLIENT.equals(type))); + return TunnelController.isClient(type); } public String getTunnelName(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null && tun.getName() != null) - return tun.getName(); + String name = _helper.getTunnelName(tunnel); + if (name != null) + return DataHelper.escapeHTML(name); else - return _("New Tunnel"); + return _t("New Tunnel"); } /** * No validation */ public String getClientPort(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null && tun.getListenPort() != null) - return tun.getListenPort(); - else - return ""; + int port = _helper.getClientPort(tunnel); + return port > 0 ? Integer.toString(port) : ""; } /** @@ -482,13 +344,13 @@ public class IndexBean { if (tun != null && tun.getListenPort() != null) { String port = tun.getListenPort(); if (port.length() == 0) - return "" + _("Port not set") + ""; + return "" + _t("Port not set") + ""; int iport = Addresses.getPort(port); if (iport == 0) - return "" + _("Invalid port") + ' ' + port + ""; + return "" + _t("Invalid port") + ' ' + port + ""; if (iport < 1024) return "" + - _("Warning - ports less than 1024 are not recommended") + + _t("Warning - ports less than 1024 are not recommended") + ": " + port + ""; // dup check, O(n**2) List controllers = _group.getControllers(); @@ -497,12 +359,12 @@ public class IndexBean { continue; if (port.equals(controllers.get(i).getListenPort())) return "" + - _("Warning - duplicate port") + + _t("Warning - duplicate port") + ": " + port + ""; } return port; } - return "" + _("Port not set") + ""; + return "" + _t("Port not set") + ""; } public String getTunnelType(int tunnel) { @@ -514,58 +376,35 @@ public class IndexBean { } public String getTypeName(String internalType) { - if (TunnelController.TYPE_STD_CLIENT.equals(internalType)) return _("Standard client"); - else if (TunnelController.TYPE_HTTP_CLIENT.equals(internalType)) return _("HTTP/HTTPS client"); - else if (TunnelController.TYPE_IRC_CLIENT.equals(internalType)) return _("IRC client"); - else if (TunnelController.TYPE_STD_SERVER.equals(internalType)) return _("Standard server"); - else if (TunnelController.TYPE_HTTP_SERVER.equals(internalType)) return _("HTTP server"); - else if (TunnelController.TYPE_SOCKS.equals(internalType)) return _("SOCKS 4/4a/5 proxy"); - else if (TunnelController.TYPE_SOCKS_IRC.equals(internalType)) return _("SOCKS IRC proxy"); - else if (TunnelController.TYPE_CONNECT.equals(internalType)) return _("CONNECT/SSL/HTTPS proxy"); - else if (TunnelController.TYPE_IRC_SERVER.equals(internalType)) return _("IRC server"); - else if (TunnelController.TYPE_STREAMR_CLIENT.equals(internalType)) return _("Streamr client"); - else if (TunnelController.TYPE_STREAMR_SERVER.equals(internalType)) return _("Streamr server"); - else if (TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(internalType)) return _("HTTP bidir"); + if (TunnelController.TYPE_STD_CLIENT.equals(internalType)) return _t("Standard client"); + else if (TunnelController.TYPE_HTTP_CLIENT.equals(internalType)) return _t("HTTP/HTTPS client"); + else if (TunnelController.TYPE_IRC_CLIENT.equals(internalType)) return _t("IRC client"); + else if (TunnelController.TYPE_STD_SERVER.equals(internalType)) return _t("Standard server"); + else if (TunnelController.TYPE_HTTP_SERVER.equals(internalType)) return _t("HTTP server"); + else if (TunnelController.TYPE_SOCKS.equals(internalType)) return _t("SOCKS 4/4a/5 proxy"); + else if (TunnelController.TYPE_SOCKS_IRC.equals(internalType)) return _t("SOCKS IRC proxy"); + else if (TunnelController.TYPE_CONNECT.equals(internalType)) return _t("CONNECT/SSL/HTTPS proxy"); + else if (TunnelController.TYPE_IRC_SERVER.equals(internalType)) return _t("IRC server"); + else if (TunnelController.TYPE_STREAMR_CLIENT.equals(internalType)) return _t("Streamr client"); + else if (TunnelController.TYPE_STREAMR_SERVER.equals(internalType)) return _t("Streamr server"); + else if (TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(internalType)) return _t("HTTP bidir"); else return internalType; } public String getInternalType(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) - return tun.getType(); - else - return ""; + return _helper.getTunnelType(tunnel); } public String getClientInterface(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) { - if ("streamrclient".equals(tun.getType())) - return tun.getTargetHost(); - else - return tun.getListenOnInterface(); - } else - return "127.0.0.1"; + return _helper.getClientInterface(tunnel); } public int getTunnelStatus(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun == null) return NOT_RUNNING; - if (tun.getIsRunning()) { - if (isClient(tunnel) && tun.getIsStandby()) - return STANDBY; - else - return RUNNING; - } else if (tun.getIsStarting()) return STARTING; - else return NOT_RUNNING; + return _helper.getTunnelStatus(tunnel); } public String getTunnelDescription(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null && tun.getDescription() != null) - return tun.getDescription(); - else - return ""; + return DataHelper.escapeHTML(_helper.getTunnelDescription(tunnel)); } public String getSharedClient(int tunnel) { @@ -577,16 +416,7 @@ public class IndexBean { } public String getClientDestination(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun == null) return ""; - String rv; - if (TunnelController.TYPE_STD_CLIENT.equals(tun.getType()) || - TunnelController.TYPE_IRC_CLIENT.equals(tun.getType()) || - TunnelController.TYPE_STREAMR_CLIENT.equals(tun.getType())) - rv = tun.getTargetDestination(); - else - rv = tun.getProxyList(); - return rv != null ? rv : ""; + return _helper.getClientDestination(tunnel); } /** @@ -614,50 +444,48 @@ public class IndexBean { host = tun.getTargetHost(); String port = tun.getTargetPort(); if (host == null || host.length() == 0) - host = "" + _("Host not set") + ""; + host = "" + _t("Host not set") + ""; else if (Addresses.getIP(host) == null) - host = "" + _("Invalid address") + ' ' + host + ""; + host = "" + _t("Invalid address") + ' ' + host + ""; else if (host.indexOf(':') >= 0) host = '[' + host + ']'; if (port == null || port.length() == 0) - port = "" + _("Port not set") + ""; + port = "" + _t("Port not set") + ""; else if (Addresses.getPort(port) == 0) - port = "" + _("Invalid port") + ' ' + port + ""; + port = "" + _t("Invalid port") + ' ' + port + ""; return host + ':' + port; } else return ""; } + /** + * Works even if tunnel is not running. + * @return Destination or null + * @since 0.9.17 + */ + protected Destination getDestination(int tunnel) { + return _helper.getDestination(tunnel); + } + + /** + * Works even if tunnel is not running. + * @return Base64 or "" + */ public String getDestinationBase64(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) { - String rv = tun.getMyDestination(); - if (rv != null) - return rv; - // if not running, do this the hard way - String keyFile = tun.getPrivKeyFile(); - if (keyFile != null && keyFile.trim().length() > 0) { - PrivateKeyFile pkf = new PrivateKeyFile(keyFile); - try { - Destination d = pkf.getDestination(); - if (d != null) - return d.toBase64(); - } catch (Exception e) {} - } - } + Destination d = getDestination(tunnel); + if (d != null) + return d.toBase64(); return ""; } /** + * Works even if tunnel is not running. * @return "{52 chars}.b32.i2p" or "" */ public String getDestHashBase32(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) { - String rv = tun.getMyDestHashBase32(); - if (rv != null) - return rv; - } + Destination d = getDestination(tunnel); + if (d != null) + return d.toBase32(); return ""; } @@ -691,79 +519,103 @@ public class IndexBean { * */ public void setType(String type) { - _type = (type != null ? type.trim() : null); + _config.setType(type); } - String getType() { return _type; } + String getType() { return _config.getType(); } /** Short name of the tunnel */ public void setName(String name) { - _name = (name != null ? name.trim() : null); + _config.setName(name); } /** one line description */ - public void setDescription(String description) { - _description = (description != null ? description.trim() : null); + public void setNofilter_description(String description) { + _config.setDescription(description); } /** I2CP host the router is on, ignored when in router context */ public void setClientHost(String host) { - _i2cpHost = (host != null ? host.trim() : null); + _config.setClientHost(host); } /** I2CP port the router is on, ignored when in router context */ public void setClientport(String port) { - _i2cpPort = (port != null ? port.trim() : null); + _config.setClientPort(port); } /** how many hops to use for inbound tunnels */ - public void setTunnelDepth(String tunnelDepth) { - _tunnelDepth = (tunnelDepth != null ? tunnelDepth.trim() : null); + public void setTunnelDepth(String tunnelDepth) { + if (tunnelDepth != null) { + try { + _config.setTunnelDepth(Integer.parseInt(tunnelDepth.trim())); + } catch (NumberFormatException nfe) {} + } } /** how many parallel inbound tunnels to use */ - public void setTunnelQuantity(String tunnelQuantity) { - _tunnelQuantity = (tunnelQuantity != null ? tunnelQuantity.trim() : null); + public void setTunnelQuantity(String tunnelQuantity) { + if (tunnelQuantity != null) { + try { + _config.setTunnelQuantity(Integer.parseInt(tunnelQuantity.trim())); + } catch (NumberFormatException nfe) {} + } } /** how much randomisation to apply to the depth of tunnels */ - public void setTunnelVariance(String tunnelVariance) { - _tunnelVariance = (tunnelVariance != null ? tunnelVariance.trim() : null); + public void setTunnelVariance(String tunnelVariance) { + if (tunnelVariance != null) { + try { + _config.setTunnelVariance(Integer.parseInt(tunnelVariance.trim())); + } catch (NumberFormatException nfe) {} + } } /** how many tunnels to hold in reserve to guard against failures */ - public void setTunnelBackupQuantity(String tunnelBackupQuantity) { - _tunnelBackupQuantity = (tunnelBackupQuantity != null ? tunnelBackupQuantity.trim() : null); + public void setTunnelBackupQuantity(String tunnelBackupQuantity) { + if (tunnelBackupQuantity != null) { + try { + _config.setTunnelBackupQuantity(Integer.parseInt(tunnelBackupQuantity.trim())); + } catch (NumberFormatException nfe) {} + } } /** what I2P session overrides should be used */ - public void setCustomOptions(String customOptions) { - _customOptions = (customOptions != null ? customOptions.trim() : null); + public void setNofilter_customOptions(String customOptions) { + _config.setCustomOptions(customOptions); } /** what HTTP outproxies should be used (httpclient specific) */ public void setProxyList(String proxyList) { - _proxyList = (proxyList != null ? proxyList.trim() : null); + _config.setProxyList(proxyList); } /** what port should this client/httpclient/ircclient listen on */ public void setPort(String port) { - _port = (port != null ? port.trim() : null); + if (port != null) { + try { + _config.setPort(Integer.parseInt(port.trim())); + } catch (NumberFormatException nfe) {} + } } /** * what interface should this client/httpclient/ircclient listen on */ public void setReachableBy(String reachableBy) { - _reachableBy = (reachableBy != null ? reachableBy.trim() : null); + _config.setReachableBy(reachableBy); } /** What peer does this client tunnel point at */ public void setTargetDestination(String dest) { - _targetDestination = (dest != null ? dest.trim() : null); + _config.setTargetDestination(dest); } /** What host does this server tunnel point at */ public void setTargetHost(String host) { - _targetHost = (host != null ? host.trim() : null); + _config.setTargetHost(host); } /** What port does this server tunnel point at */ - public void setTargetPort(String port) { - _targetPort = (port != null ? port.trim() : null); + public void setTargetPort(String port) { + if (port != null) { + try { + _config.setTargetPort(Integer.parseInt(port.trim())); + } catch (NumberFormatException nfe) {} + } } /** What host does this http server tunnel spoof */ public void setSpoofedHost(String host) { - _spoofedHost = (host != null ? host.trim() : null); + _config.setSpoofedHost(host); } /** What filename is this server tunnel's private keys stored in */ public void setPrivKeyFile(String file) { - _privKeyFile = (file != null ? file.trim() : null); + _config.setPrivKeyFile(file); } /** * If called with any value (and the form submitted with action=Remove), @@ -777,228 +629,228 @@ public class IndexBean { * loaded (aka right now and whenever the router is started up) */ public void setStartOnLoad(String moo) { - _startOnLoad = true; + _config.setStartOnLoad(true); } public void setShared(String moo) { - _sharedClient=true; + _config.setShared(true); } public void setShared(boolean val) { - _sharedClient=val; + _config.setShared(val); } public void setConnectDelay(String moo) { - _connectDelay = true; + _config.setConnectDelay(true); } public void setProfile(String profile) { - _profile = profile; + _config.setProfile(profile); } public void setReduce(String moo) { - _booleanOptions.add("i2cp.reduceOnIdle"); + _config.setReduce(true); } public void setClose(String moo) { - _booleanOptions.add("i2cp.closeOnIdle"); + _config.setClose(true); } public void setEncrypt(String moo) { - _booleanOptions.add("i2cp.encryptLeaseSet"); + _config.setEncrypt(true); } /** @since 0.8.9 */ public void setDCC(String moo) { - _booleanOptions.add(I2PTunnelIRCClient.PROP_DCC); + _config.setDCC(true); } /** @since 0.9.9 */ public void setUseSSL(String moo) { - _booleanOptions.add(I2PTunnelServer.PROP_USE_SSL); + _config.setUseSSL(true); } /** @since 0.9.9 */ public boolean isSSLEnabled(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) { - Properties opts = tun.getClientOptionProps(); - return Boolean.parseBoolean(opts.getProperty(I2PTunnelServer.PROP_USE_SSL)); - } - return false; + return _helper.isSSLEnabled(tunnel); } /** @since 0.9.12 */ public void setRejectInproxy(String moo) { - _booleanOptions.add(I2PTunnelHTTPServer.OPT_REJECT_INPROXY); + _config.setRejectInproxy(true); } /** @since 0.9.12 */ public boolean isRejectInproxy(int tunnel) { - TunnelController tun = getController(tunnel); - if (tun != null) { - Properties opts = tun.getClientOptionProps(); - return Boolean.parseBoolean(opts.getProperty(I2PTunnelHTTPServer.OPT_REJECT_INPROXY)); - } - return false; + return _helper.getRejectInproxy(tunnel); } /** @since 0.9.13 */ public void setUniqueLocal(String moo) { - _booleanOptions.add(I2PTunnelServer.PROP_UNIQUE_LOCAL); + _config.setUniqueLocal(true); } - protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList"; - protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList"; - public void setAccessMode(String val) { - if ("1".equals(val)) - _booleanOptions.add(PROP_ENABLE_ACCESS_LIST); - else if ("2".equals(val)) - _booleanOptions.add(PROP_ENABLE_BLACKLIST); + if (val != null) { + try { + _config.setAccessMode(Integer.parseInt(val.trim())); + } catch (NumberFormatException nfe) {} + } } public void setDelayOpen(String moo) { - _booleanOptions.add("i2cp.delayOpen"); + _config.setDelayOpen(true); } public void setNewDest(String val) { - if ("1".equals(val)) - _booleanOptions.add("i2cp.newDestOnResume"); - else if ("2".equals(val)) - _booleanOptions.add("persistentClientKey"); + if (val != null) { + try { + _config.setNewDest(Integer.parseInt(val.trim())); + } catch (NumberFormatException nfe) {} + } } public void setReduceTime(String val) { if (val != null) { try { - _otherOptions.put("i2cp.reduceIdleTime", Integer.toString(Integer.parseInt(val.trim()) * 60*1000)); + _config.setReduceTime(Integer.parseInt(val.trim())); } catch (NumberFormatException nfe) {} } } public void setReduceCount(String val) { - if (val != null) - _otherOptions.put("i2cp.reduceQuantity", val.trim()); + if (val != null) { + try { + _config.setReduceCount(Integer.parseInt(val.trim())); + } catch (NumberFormatException nfe) {} + } } public void setEncryptKey(String val) { - if (val != null) - _otherOptions.put("i2cp.leaseSetKey", val.trim()); + _config.setEncryptKey(val); } public void setAccessList(String val) { - if (val != null) - _otherOptions.put("i2cp.accessList", val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ",")); + _config.setAccessList(val); } public void setJumpList(String val) { - if (val != null) - _otherOptions.put(I2PTunnelHTTPClient.PROP_JUMP_SERVERS, val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ",")); + _config.setJumpList(val); } public void setCloseTime(String val) { if (val != null) { try { - _otherOptions.put("i2cp.closeIdleTime", Integer.toString(Integer.parseInt(val.trim()) * 60*1000)); + _config.setCloseTime(Integer.parseInt(val.trim())); } catch (NumberFormatException nfe) {} } } /** @since 0.9.14 */ public void setAllowUserAgent(String moo) { - _booleanOptions.add(I2PTunnelHTTPClient.PROP_USER_AGENT); + _config.setAllowUserAgent(true); } /** @since 0.9.14 */ public void setAllowReferer(String moo) { - _booleanOptions.add(I2PTunnelHTTPClient.PROP_REFERER); + _config.setAllowReferer(true); } /** @since 0.9.14 */ public void setAllowAccept(String moo) { - _booleanOptions.add(I2PTunnelHTTPClient.PROP_ACCEPT); + _config.setAllowAccept(true); } /** @since 0.9.14 */ public void setAllowInternalSSL(String moo) { - _booleanOptions.add(I2PTunnelHTTPClient.PROP_INTERNAL_SSL); + _config.setAllowInternalSSL(true); + } + + /** @since 0.9.18 */ + public void setMultihome(String moo) { + _config.setMultihome(true); } /** all proxy auth @since 0.8.2 */ public void setProxyAuth(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPClientBase.PROP_AUTH, I2PTunnelHTTPClientBase.DIGEST_AUTH); + _config.setProxyAuth(I2PTunnelHTTPClientBase.DIGEST_AUTH); } public void setProxyUsername(String s) { - if (s != null) - _newProxyUser = s.trim(); + _config.setProxyUsername(s); } - public void setProxyPassword(String s) { - if (s != null) - _newProxyPW = s.trim(); + public void setNofilter_proxyPassword(String s) { + _config.setProxyPassword(s); } public void setOutproxyAuth(String s) { - _otherOptions.put(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH, I2PTunnelHTTPClientBase.DIGEST_AUTH); + _config.setOutproxyAuth(true); } public void setOutproxyUsername(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPClientBase.PROP_OUTPROXY_USER, s.trim()); + _config.setOutproxyUsername(s); } - public void setOutproxyPassword(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW, s.trim()); + public void setNofilter_outproxyPassword(String s) { + _config.setOutproxyPassword(s); } /** @since 0.9.11 */ public void setSslProxies(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPClient.PROP_SSL_OUTPROXIES, s.trim().replace(" ", ",")); + _config.setSslProxies(s); } /** @since 0.9.11 */ public void setUseOutproxyPlugin(String moo) { - _booleanOptions.add(I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN); + _config.setUseOutproxyPlugin(true); } - - /** all of these are @since 0.8.3 */ - protected static final String PROP_MAX_CONNS_MIN = "i2p.streaming.maxConnsPerMinute"; - protected static final String PROP_MAX_CONNS_HOUR = "i2p.streaming.maxConnsPerHour"; - protected static final String PROP_MAX_CONNS_DAY = "i2p.streaming.maxConnsPerDay"; - protected static final String PROP_MAX_TOTAL_CONNS_MIN = "i2p.streaming.maxTotalConnsPerMinute"; - protected static final String PROP_MAX_TOTAL_CONNS_HOUR = "i2p.streaming.maxTotalConnsPerHour"; - protected static final String PROP_MAX_TOTAL_CONNS_DAY = "i2p.streaming.maxTotalConnsPerDay"; - protected static final String PROP_MAX_STREAMS = "i2p.streaming.maxConcurrentStreams"; public void setLimitMinute(String s) { - if (s != null) - _otherOptions.put(PROP_MAX_CONNS_MIN, s.trim()); + if (s != null) { + try { + _config.setLimitMinute(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setLimitHour(String s) { - if (s != null) - _otherOptions.put(PROP_MAX_CONNS_HOUR, s.trim()); + if (s != null) { + try { + _config.setLimitHour(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setLimitDay(String s) { - if (s != null) - _otherOptions.put(PROP_MAX_CONNS_DAY, s.trim()); + if (s != null) { + try { + _config.setLimitDay(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setTotalMinute(String s) { - if (s != null) - _otherOptions.put(PROP_MAX_TOTAL_CONNS_MIN, s.trim()); + if (s != null) { + try { + _config.setTotalMinute(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setTotalHour(String s) { - if (s != null) - _otherOptions.put(PROP_MAX_TOTAL_CONNS_HOUR, s.trim()); + if (s != null) { + try { + _config.setTotalHour(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setTotalDay(String s) { - if (s != null) - _otherOptions.put(PROP_MAX_TOTAL_CONNS_DAY, s.trim()); + if (s != null) { + try { + _config.setTotalDay(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setMaxStreams(String s) { - if (s != null) - _otherOptions.put(PROP_MAX_STREAMS, s.trim()); + if (s != null) { + try { + _config.setMaxStreams(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } /** @@ -1006,28 +858,43 @@ public class IndexBean { * @since 0.9.9 */ public void setPostMax(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_MAX, s.trim()); + if (s != null) { + try { + _config.setPostMax(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setPostTotalMax(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_TOTAL_MAX, s.trim()); + if (s != null) { + try { + _config.setPostTotalMax(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setPostCheckTime(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_WINDOW, Integer.toString(Integer.parseInt(s.trim()) * 60)); + if (s != null) { + try { + _config.setPostCheckTime(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setPostBanTime(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_BAN_TIME, Integer.toString(Integer.parseInt(s.trim()) * 60)); + if (s != null) { + try { + _config.setPostBanTime(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } public void setPostTotalBanTime(String s) { - if (s != null) - _otherOptions.put(I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, Integer.toString(Integer.parseInt(s.trim()) * 60)); + if (s != null) { + try { + _config.setPostTotalBanTime(Integer.parseInt(s.trim())); + } catch (NumberFormatException nfe) {} + } } /** params needed for hashcash and dest modification */ @@ -1054,7 +921,7 @@ public class IndexBean { /** @since 0.9.12 */ public void setSigType(String val) { if (val != null) { - _otherOptions.put(I2PClient.PROP_SIGTYPE, val); + _config.setSigType(val); if (val.equals("0")) _certType = 0; else @@ -1064,9 +931,30 @@ public class IndexBean { // Otherwise this only works on a new tunnel... } + /** + * Random keys, hidden in forms + * @since 0.9.18 + */ + public void setKey1(String s) { + _config.setInboundRandomKey(s); + } + + public void setKey2(String s) { + _config.setOutboundRandomKey(s); + } + + public void setKey3(String s) { + _config.setLeaseSetSigningPrivateKey(s); + } + + public void setKey4(String s) { + _config.setLeaseSetPrivateKey(s); + } + /** Modify or create a destination */ private String modifyDestination() { - if (_privKeyFile == null || _privKeyFile.trim().length() <= 0) + String privKeyFile = _config.getPrivKeyFile(); + if (privKeyFile == null) return "Private Key File not specified"; TunnelController tun = getController(_tunnel); @@ -1080,13 +968,15 @@ public class IndexBean { return "Tunnel must be stopped before modifying destination"; } - File keyFile = new File(_privKeyFile); + File keyFile = new File(privKeyFile); if (!keyFile.isAbsolute()) - keyFile = new File(_context.getConfigDir(), _privKeyFile); + keyFile = new File(_context.getConfigDir(), privKeyFile); PrivateKeyFile pkf = new PrivateKeyFile(keyFile); try { pkf.createIfAbsent(); - } catch (Exception e) { + } catch (I2PException e) { + return "Create private key file failed: " + e; + } catch (IOException e) { return "Create private key file failed: " + e; } switch (_certType) { @@ -1112,7 +1002,7 @@ public class IndexBean { } if (signerPKF == null || signerPKF.length() <= 0) return "Signing destination " + _certSigner + " not found"; - if (_privKeyFile.equals(signerPKF)) + if (privKeyFile.equals(signerPKF)) return "Self-signed destinations not allowed"; Certificate c = pkf.setSignedCert(new PrivateKeyFile(signerPKF)); if (c == null) @@ -1125,7 +1015,9 @@ public class IndexBean { try { pkf.write(); newdest = pkf.getDestination(); - } catch (Exception e) { + } catch (I2PException e) { + return "Modification failed: " + e; + } catch (IOException e) { return "Modification failed: " + e; } return "Destination modified - " + @@ -1161,274 +1053,10 @@ public class IndexBean { * */ private Properties getConfig() { - Properties config = new Properties(); - updateConfigGeneric(config); - - if ((isClient(_type) && !TunnelController.TYPE_STREAMR_CLIENT.equals(_type)) || - TunnelController.TYPE_STREAMR_SERVER.equals(_type)) { - // streamrserver uses interface - if (_reachableBy != null) - config.setProperty(TunnelController.PROP_INTFC, _reachableBy); - else - config.setProperty(TunnelController.PROP_INTFC, ""); - } else { - // streamrclient uses targetHost - if (_targetHost != null) - config.setProperty(TunnelController.PROP_TARGET_HOST, _targetHost); - } - - if (isClient(_type)) { - // generic client stuff - if (_port != null) - config.setProperty(TunnelController.PROP_LISTEN_PORT, _port); - config.setProperty(TunnelController.PROP_SHARED, _sharedClient + ""); - for (String p : _booleanClientOpts) - config.setProperty(OPT + p, "" + _booleanOptions.contains(p)); - for (String p : _otherClientOpts) - if (_otherOptions.containsKey(p)) - config.setProperty(OPT + p, _otherOptions.get(p)); - } else { - // generic server stuff - if (_targetPort != null) - config.setProperty(TunnelController.PROP_TARGET_PORT, _targetPort); - for (String p : _booleanServerOpts) - config.setProperty(OPT + p, "" + _booleanOptions.contains(p)); - for (String p : _otherServerOpts) - if (_otherOptions.containsKey(p)) - config.setProperty(OPT + p, _otherOptions.get(p)); - } - - // generic proxy stuff - if (TunnelController.TYPE_HTTP_CLIENT.equals(_type) || TunnelController.TYPE_CONNECT.equals(_type) || - TunnelController.TYPE_SOCKS.equals(_type) ||TunnelController.TYPE_SOCKS_IRC.equals(_type)) { - for (String p : _booleanProxyOpts) - config.setProperty(OPT + p, "" + _booleanOptions.contains(p)); - if (_proxyList != null) - config.setProperty(TunnelController.PROP_PROXIES, _proxyList); - } - - // Proxy auth including migration to MD5 - if (TunnelController.TYPE_HTTP_CLIENT.equals(_type) || TunnelController.TYPE_CONNECT.equals(_type)) { - // Migrate even if auth is disabled - // go get the old from custom options that updateConfigGeneric() put in there - String puser = OPT + I2PTunnelHTTPClientBase.PROP_USER; - String user = config.getProperty(puser); - String ppw = OPT + I2PTunnelHTTPClientBase.PROP_PW; - String pw = config.getProperty(ppw); - if (user != null && pw != null && user.length() > 0 && pw.length() > 0) { - String pmd5 = OPT + I2PTunnelHTTPClientBase.PROP_PROXY_DIGEST_PREFIX + - user + I2PTunnelHTTPClientBase.PROP_PROXY_DIGEST_SUFFIX; - if (config.getProperty(pmd5) == null) { - // not in there, migrate - String realm = _type.equals(TunnelController.TYPE_HTTP_CLIENT) ? I2PTunnelHTTPClient.AUTH_REALM - : I2PTunnelConnectClient.AUTH_REALM; - String hex = PasswordManager.md5Hex(realm, user, pw); - if (hex != null) { - config.setProperty(pmd5, hex); - config.remove(puser); - config.remove(ppw); - } - } - } - // New user/password - String auth = _otherOptions.get(I2PTunnelHTTPClientBase.PROP_AUTH); - if (auth != null && !auth.equals("false")) { - if (_newProxyUser != null && _newProxyPW != null && - _newProxyUser.length() > 0 && _newProxyPW.length() > 0) { - String pmd5 = OPT + I2PTunnelHTTPClientBase.PROP_PROXY_DIGEST_PREFIX + - _newProxyUser + I2PTunnelHTTPClientBase.PROP_PROXY_DIGEST_SUFFIX; - String realm = _type.equals(TunnelController.TYPE_HTTP_CLIENT) ? I2PTunnelHTTPClient.AUTH_REALM - : I2PTunnelConnectClient.AUTH_REALM; - String hex = PasswordManager.md5Hex(realm, _newProxyUser, _newProxyPW); - if (hex != null) - config.setProperty(pmd5, hex); - } - } - } - - if (TunnelController.TYPE_IRC_CLIENT.equals(_type) || - TunnelController.TYPE_STD_CLIENT.equals(_type) || - TunnelController.TYPE_STREAMR_CLIENT.equals(_type)) { - if (_targetDestination != null) - config.setProperty(TunnelController.PROP_DEST, _targetDestination); - } else if (TunnelController.TYPE_HTTP_SERVER.equals(_type) || - TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(_type)) { - if (_spoofedHost != null) - config.setProperty(TunnelController.PROP_SPOOFED_HOST, _spoofedHost); - for (String p : _httpServerOpts) - if (_otherOptions.containsKey(p)) - config.setProperty(OPT + p, _otherOptions.get(p)); - } - if (TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(_type)) { - if (_port != null) - config.setProperty(TunnelController.PROP_LISTEN_PORT, _port); - if (_reachableBy != null) - config.setProperty(TunnelController.PROP_INTFC, _reachableBy); - else if (_targetHost != null) - config.setProperty(TunnelController.PROP_INTFC, _targetHost); - else - config.setProperty(TunnelController.PROP_INTFC, ""); - } - - if (TunnelController.TYPE_IRC_CLIENT.equals(_type)) { - boolean dcc = _booleanOptions.contains(I2PTunnelIRCClient.PROP_DCC); - config.setProperty(OPT + I2PTunnelIRCClient.PROP_DCC, - "" + dcc); - // add some sane server options since they aren't in the GUI (yet) - if (dcc) { - config.setProperty(OPT + PROP_MAX_CONNS_MIN, "3"); - config.setProperty(OPT + PROP_MAX_CONNS_HOUR, "10"); - config.setProperty(OPT + PROP_MAX_TOTAL_CONNS_MIN, "5"); - config.setProperty(OPT + PROP_MAX_TOTAL_CONNS_HOUR, "25"); - } - } - - return config; - } - - private static final String _noShowOpts[] = { - "inbound.length", "outbound.length", "inbound.lengthVariance", "outbound.lengthVariance", - "inbound.backupQuantity", "outbound.backupQuantity", "inbound.quantity", "outbound.quantity", - "inbound.nickname", "outbound.nickname", "i2p.streaming.connectDelay", "i2p.streaming.maxWindowSize", - I2PTunnelIRCClient.PROP_DCC - }; - private static final String _booleanClientOpts[] = { - "i2cp.reduceOnIdle", "i2cp.closeOnIdle", "i2cp.newDestOnResume", "persistentClientKey", "i2cp.delayOpen" - }; - private static final String _booleanProxyOpts[] = { - I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH, - I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN, - I2PTunnelHTTPClient.PROP_USER_AGENT, - I2PTunnelHTTPClient.PROP_REFERER, - I2PTunnelHTTPClient.PROP_ACCEPT, - I2PTunnelHTTPClient.PROP_INTERNAL_SSL - }; - private static final String _booleanServerOpts[] = { - "i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", PROP_ENABLE_ACCESS_LIST, PROP_ENABLE_BLACKLIST, - I2PTunnelServer.PROP_USE_SSL, - I2PTunnelHTTPServer.OPT_REJECT_INPROXY, - I2PTunnelServer.PROP_UNIQUE_LOCAL - }; - private static final String _otherClientOpts[] = { - "i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime", - "outproxyUsername", "outproxyPassword", - I2PTunnelHTTPClient.PROP_JUMP_SERVERS, - I2PTunnelHTTPClientBase.PROP_AUTH, - I2PClient.PROP_SIGTYPE, - I2PTunnelHTTPClient.PROP_SSL_OUTPROXIES - }; - private static final String _otherServerOpts[] = { - "i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.leaseSetKey", "i2cp.accessList", - PROP_MAX_CONNS_MIN, PROP_MAX_CONNS_HOUR, PROP_MAX_CONNS_DAY, - PROP_MAX_TOTAL_CONNS_MIN, PROP_MAX_TOTAL_CONNS_HOUR, PROP_MAX_TOTAL_CONNS_DAY, - PROP_MAX_STREAMS, I2PClient.PROP_SIGTYPE - }; - private static final String _httpServerOpts[] = { - I2PTunnelHTTPServer.OPT_POST_WINDOW, - I2PTunnelHTTPServer.OPT_POST_BAN_TIME, - I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, - I2PTunnelHTTPServer.OPT_POST_MAX, - I2PTunnelHTTPServer.OPT_POST_TOTAL_MAX - }; - - /** - * do NOT add these to noShoOpts, we must leave them in for HTTPClient and ConnectCLient - * so they will get migrated to MD5 - * TODO migrate socks to MD5 - */ - private static final String _otherProxyOpts[] = { - "proxyUsername", "proxyPassword" - }; - - protected static final Set _noShowSet = new HashSet(128); - protected static final Set _nonProxyNoShowSet = new HashSet(4); - static { - _noShowSet.addAll(Arrays.asList(_noShowOpts)); - _noShowSet.addAll(Arrays.asList(_booleanClientOpts)); - _noShowSet.addAll(Arrays.asList(_booleanProxyOpts)); - _noShowSet.addAll(Arrays.asList(_booleanServerOpts)); - _noShowSet.addAll(Arrays.asList(_otherClientOpts)); - _noShowSet.addAll(Arrays.asList(_otherServerOpts)); - _noShowSet.addAll(Arrays.asList(_httpServerOpts)); - _nonProxyNoShowSet.addAll(Arrays.asList(_otherProxyOpts)); - } - - private void updateConfigGeneric(Properties config) { - config.setProperty(TunnelController.PROP_TYPE, _type); - if (_name != null) - config.setProperty(TunnelController.PROP_NAME, _name); - if (_description != null) - config.setProperty(TunnelController.PROP_DESCR, _description); - if (!_context.isRouterContext()) { - if (_i2cpHost != null) - config.setProperty(TunnelController.PROP_I2CP_HOST, _i2cpHost); - if ( (_i2cpPort != null) && (_i2cpPort.trim().length() > 0) ) { - config.setProperty(TunnelController.PROP_I2CP_PORT, _i2cpPort); - } else { - config.setProperty(TunnelController.PROP_I2CP_PORT, "7654"); - } - } - if (_privKeyFile != null) - config.setProperty(TunnelController.PROP_FILE, _privKeyFile); - - if (_customOptions != null) { - StringTokenizer tok = new StringTokenizer(_customOptions); - while (tok.hasMoreTokens()) { - String pair = tok.nextToken(); - int eq = pair.indexOf('='); - if ( (eq <= 0) || (eq >= pair.length()) ) - continue; - String key = pair.substring(0, eq); - if (_noShowSet.contains(key)) - continue; - // leave in for HTTP and Connect so it can get migrated to MD5 - // hide for SOCKS until migrated to MD5 - if ((!TunnelController.TYPE_HTTP_CLIENT.equals(_type)) && - (!TunnelController.TYPE_CONNECT.equals(_type)) && - _nonProxyNoShowSet.contains(key)) - continue; - String val = pair.substring(eq+1); - config.setProperty(OPT + key, val); - } - } - - config.setProperty(TunnelController.PROP_START, _startOnLoad + ""); - - if (_tunnelQuantity != null) { - config.setProperty("option.inbound.quantity", _tunnelQuantity); - config.setProperty("option.outbound.quantity", _tunnelQuantity); - } - if (_tunnelDepth != null) { - config.setProperty("option.inbound.length", _tunnelDepth); - config.setProperty("option.outbound.length", _tunnelDepth); - } - if (_tunnelVariance != null) { - config.setProperty("option.inbound.lengthVariance", _tunnelVariance); - config.setProperty("option.outbound.lengthVariance", _tunnelVariance); - } - if (_tunnelBackupQuantity != null) { - config.setProperty("option.inbound.backupQuantity", _tunnelBackupQuantity); - config.setProperty("option.outbound.backupQuantity", _tunnelBackupQuantity); - } - if (_connectDelay) - config.setProperty("option.i2p.streaming.connectDelay", "1000"); - else - config.setProperty("option.i2p.streaming.connectDelay", "0"); - if (isClient(_type) && _sharedClient) { - config.setProperty("option.inbound.nickname", CLIENT_NICKNAME); - config.setProperty("option.outbound.nickname", CLIENT_NICKNAME); - } else if (_name != null) { - config.setProperty("option.inbound.nickname", _name); - config.setProperty("option.outbound.nickname", _name); - } - if ("interactive".equals(_profile)) - // This was 1 which doesn't make much sense - // The real way to make it interactive is to make the streaming lib - // MessageInputStream flush faster but there's no option for that yet, - // Setting it to 16 instead of the default but not sure what good that is either. - config.setProperty("option.i2p.streaming.maxWindowSize", "16"); - else - config.remove("option.i2p.streaming.maxWindowSize"); + // This is easier than requiring TunnelConfig to talk to + // TunnelControllerGroup and TunnelController + _config.setDestination(getDestination(_tunnel)); + return _config.getConfig(); } /// @@ -1436,13 +1064,7 @@ public class IndexBean { /// protected TunnelController getController(int tunnel) { - if (tunnel < 0) return null; - if (_group == null) return null; - List controllers = _group.getControllers(); - if (controllers.size() > tunnel) - return controllers.get(tunnel); - else - return null; + return _helper.getController(tunnel); } private static String getMessages(List msgs) { @@ -1458,8 +1080,8 @@ public class IndexBean { } } - protected String _(String key) { - return Messages._(key, _context); + protected String _t(String key) { + return Messages._t(key, _context); } /** translate (ngettext) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/Messages.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/Messages.java index d4a2fb4bd..88911b041 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/Messages.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/Messages.java @@ -16,11 +16,11 @@ public class Messages { } /** lang in routerconsole.lang property, else current locale */ - public String _(String key) { + public String _t(String key) { return Translate.getString(key, _context, BUNDLE_NAME); } - public static String _(String key, I2PAppContext ctx) { + public static String _t(String key, I2PAppContext ctx) { return Translate.getString(key, ctx, BUNDLE_NAME); } @@ -32,11 +32,11 @@ public class Messages { * The {0} will be replaced by the parameter. * Single quotes must be doubled, i.e. ' -> '' in the string. * @param o parameter, not translated. - * To tranlslate parameter also, use _("foo {0} bar", _("baz")) + * To translate parameter also, use _t("foo {0} bar", _t("baz")) * Do not double the single quotes in the parameter. * Use autoboxing to call with ints, longs, floats, etc. */ - public String _(String s, Object o) { + public String _t(String s, Object o) { return Translate.getString(s, o, _context, BUNDLE_NAME); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/package.html b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/package.html new file mode 100644 index 000000000..61d2d3b56 --- /dev/null +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/package.html @@ -0,0 +1,9 @@ + + +

+The UI for adding tunnels and editing their configurations, +implemented as a webapp packaged in i2ptunnel.war. +Not be maintained as a stable API. +

+ + diff --git a/apps/i2ptunnel/java/test/junit/net/i2p/i2ptunnel/I2PTunnelHTTPServerTest.java b/apps/i2ptunnel/java/test/junit/net/i2p/i2ptunnel/I2PTunnelHTTPServerTest.java index 8cd7cf322..7132a7da2 100644 --- a/apps/i2ptunnel/java/test/junit/net/i2p/i2ptunnel/I2PTunnelHTTPServerTest.java +++ b/apps/i2ptunnel/java/test/junit/net/i2p/i2ptunnel/I2PTunnelHTTPServerTest.java @@ -9,6 +9,7 @@ import java.io.OutputStreamWriter; import java.util.Map; import java.util.List; +import net.i2p.I2PAppContext; import junit.framework.TestCase; public class I2PTunnelHTTPServerTest extends TestCase { @@ -27,7 +28,7 @@ public class I2PTunnelHTTPServerTest extends TestCase { headerString += "BLAH: something\r\n"; headerString += "\r\n"; InputStream in = fillInputStream(headerString); - Map> headers = I2PTunnelHTTPServer.readHeaders(in, new StringBuilder(128), new String[0], null); + Map> headers = I2PTunnelHTTPServer.readHeaders(null, in, new StringBuilder(128), new String[0], I2PAppContext.getGlobalContext()); assertEquals(headers.size(), 1); //One header } @@ -37,7 +38,7 @@ public class I2PTunnelHTTPServerTest extends TestCase { headerString += "someHeader: oh my, duplication!\r\n"; headerString += "\r\n"; InputStream in = fillInputStream(headerString); - Map> headers = I2PTunnelHTTPServer.readHeaders(in, new StringBuilder(128), new String[0], null); + Map> headers = I2PTunnelHTTPServer.readHeaders(null, in, new StringBuilder(128), new String[0], I2PAppContext.getGlobalContext()); assertEquals(headers.size(), 1); assertEquals(headers.get("someHeader").size(), 2); } @@ -50,7 +51,7 @@ public class I2PTunnelHTTPServerTest extends TestCase { headerString += "\r\n"; InputStream in = fillInputStream(headerString); StringBuilder builder = new StringBuilder(128); - Map> headers = I2PTunnelHTTPServer.readHeaders(in, builder, new String[0], null); + Map> headers = I2PTunnelHTTPServer.readHeaders(null, in, builder, new String[0], I2PAppContext.getGlobalContext()); String result = I2PTunnelHTTPServer.formatHeaders(headers, builder); int first = result.indexOf("abc"); assertTrue(first >= 0); diff --git a/apps/i2ptunnel/jsp/edit.jsp b/apps/i2ptunnel/jsp/edit.jsp index c61d4de71..06eeee371 100644 --- a/apps/i2ptunnel/jsp/edit.jsp +++ b/apps/i2ptunnel/jsp/edit.jsp @@ -2,13 +2,16 @@ // NOTE: Do the header carefully so there is no whitespace before the <%@page pageEncoding="UTF-8" %><%@page trimDirectiveWhitespaces="true" %><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean" %><% String tun = request.getParameter("tunnel"); - if (tun != null) { +if (tun != null) { try { int curTunnel = Integer.parseInt(tun); if (EditBean.staticIsClient(curTunnel)) { diff --git a/apps/i2ptunnel/jsp/editClient.jsp b/apps/i2ptunnel/jsp/editClient.jsp index 6ac65d76f..b09b2ed54 100644 --- a/apps/i2ptunnel/jsp/editClient.jsp +++ b/apps/i2ptunnel/jsp/editClient.jsp @@ -16,7 +16,7 @@ %> - <%=intl._("I2P Tunnel Manager - Edit Client Tunnel")%> + <%=intl._t("Hidden Services Manager")%> - <%=intl._t("Edit Client Tunnel")%> @@ -44,20 +44,40 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
<% - String tunnelTypeName = ""; - String tunnelType = ""; + String tunnelTypeName; + String tunnelType; if (curTunnel >= 0) { tunnelTypeName = editBean.getTunnelType(curTunnel); tunnelType = editBean.getInternalType(curTunnel); - %>

<%=intl._("Edit proxy settings")%>

<% + %>

<%=intl._t("Edit proxy settings")%>

<% } else { tunnelTypeName = editBean.getTypeName(request.getParameter("type")); - tunnelType = request.getParameter("type"); - %>

<%=intl._("New proxy settings")%>

<% + tunnelType = net.i2p.data.DataHelper.stripHTML(request.getParameter("type")); + %>

<%=intl._t("New proxy settings")%>

<% } %> - " /> - + + + <% + // these are four keys that are generated automatically on first save, + // and we want to persist in i2ptunnel.config, but don't want to + // show clogging up the custom options form. + String key = editBean.getKey1(curTunnel); + if (key != null && key.length() > 0) { %> + + <% } + key = editBean.getKey2(curTunnel); + if (key != null && key.length() > 0) { %> + + <% } + key = editBean.getKey3(curTunnel); + if (key != null && key.length() > 0) { %> + + <% } + key = editBean.getKey4(curTunnel); + if (key != null && key.length() > 0) { %> + + <% } %>
@@ -67,19 +87,19 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
- + <%=tunnelTypeName%>
- +
@@ -88,9 +108,9 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
<% if ("streamrclient".equals(tunnelType)) { %> - + <% } else { %> - + <% } /* streamrclient */ %>
@@ -99,7 +119,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; } <% String value = editBean.getClientPort(curTunnel); if (value == null || "".equals(value.trim())) { out.write(" ("); - out.write(intl._("required")); + out.write(intl._t("required")); out.write(")"); } %> @@ -114,14 +134,14 @@ input.default { width: 1px; height: 1px; visibility: hidden; } String targetHost = editBean.getTargetHost(curTunnel); if (targetHost == null || "".equals(targetHost.trim())) { out.write(" ("); - out.write(intl._("required")); + out.write(intl._t("required")); out.write(")"); } %> <% } else { %> - <%=intl._("Reachable by")%>(R): + <%=intl._t("Reachable by")%>(R): <% } /* streamrclient */ %>
+ <% if ("client".equals(tunnelType) || "ircclient".equals(tunnelType)) { + %>
+ + class="tickbox" /> +
+ <% } /* tunnel types */ %>

@@ -148,41 +176,41 @@ input.default { width: 1px; height: 1px; visibility: hidden; } <% if ("httpclient".equals(tunnelType) || "connectclient".equals(tunnelType) || "sockstunnel".equals(tunnelType) || "socksirctunnel".equals(tunnelType)) { %>
<% if ("httpclient".equals(tunnelType)) { %>
<% } // httpclient %>
class="tickbox" /> - <%=intl._("(Check the Box for 'YES')")%> + <%=intl._t("(Check the Box for 'YES')")%>
<% } else if ("client".equals(tunnelType) || "ircclient".equals(tunnelType) || "streamrclient".equals(tunnelType)) { %>
- (<%=intl._("name, name:port, or destination")%> + (<%=intl._t("name, name:port, or destination")%> <% if ("streamrclient".equals(tunnelType)) { /* deferred resolution unimplemented in streamr client */ %> - - <%=intl._("b32 not recommended")%> + - <%=intl._t("b32 not recommended")%> <% } %> )
@@ -190,26 +218,26 @@ input.default { width: 1px; height: 1px; visibility: hidden; } <% if (!"streamrclient".equals(tunnelType)) { %>
class="tickbox" /> - <%=intl._("(Share tunnels with other clients and irc/httpclients? Change requires restart of client proxy)")%> + <%=intl._t("(Share tunnels with other clients and irc/httpclients? Change requires restart of client proxy)")%>
<% } // !streamrclient %>
class="tickbox" /> - <%=intl._("(Check the Box for 'YES')")%> + <%=intl._t("(Check the Box for 'YES')")%>
<% if ("ircclient".equals(tunnelType)) { %>
class="tickbox" /> - <%=intl._("(Check the Box for 'YES')")%> + <%=intl._t("(Check the Box for 'YES')")%>
<% } // ircclient %> @@ -219,8 +247,8 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
-

<%=intl._("Advanced networking options")%>


- <%=intl._("(NOTE: when this client proxy is configured to share tunnels, then these options are for all the shared proxy clients!)")%> +

<%=intl._t("Advanced networking options")%>


+ <%=intl._t("(NOTE: when this client proxy is configured to share tunnels, then these options are for all the shared proxy clients!)")%>
@@ -228,42 +256,47 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
- +
<% int tunnelBackupQuantity = editBean.getTunnelBackupQuantity(curTunnel, 0); - %> - - - + %> + + + <% if (tunnelBackupQuantity > 3) { - %> + %> <% } %>
@@ -292,20 +325,20 @@ input.default { width: 1px; height: 1px; visibility: hidden; } <% if (!"streamrclient".equals(tunnelType)) { %>
class="tickbox" /> - (<%=intl._("for request/response connections")%>) + (<%=intl._t("for request/response connections")%>)
@@ -314,17 +347,17 @@ input.default { width: 1px; height: 1px; visibility: hidden; } <% } // !streamrclient %>
- +
readonly="readonly" <% } %> />
readonly="readonly" <% } %> />
@@ -333,27 +366,44 @@ input.default { width: 1px; height: 1px; visibility: hidden; }

+ +
+ +
+
+ + class="tickbox" /> +
+ <% } // !streamrclient %> + +
+
+
class="tickbox" />
@@ -364,31 +414,31 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
class="tickbox" />
- + - +
class="tickbox" /><%=intl._("Enable")%><%=intl._t("Enable")%> class="tickbox" /><%=intl._("Disable")%>
<%=intl._t("Disable")%>
@@ -397,36 +447,19 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
-
- -
-
- - class="tickbox" /> -
- <% } // !streamrclient %> - -
-
-
- <% if ("client".equals(tunnelType) || "ircclient".equals(tunnelType) || "socksirctunnel".equals(tunnelType) || "sockstunnel".equals(tunnelType)) { %>
- + class="tickbox" />
- +
<% @@ -434,12 +467,12 @@ input.default { width: 1px; height: 1px; visibility: hidden; } if (destb64.length() > 0) { %>
- + <%=editBean.getDestHashBase32(curTunnel)%>
<% } // if destb64 %> @@ -451,31 +484,31 @@ input.default { width: 1px; height: 1px; visibility: hidden; } <% if ("httpclient".equals(tunnelType)) { %>
- +
- + class="tickbox" />

- +
- + class="tickbox" />

- +
- + class="tickbox" />

- +
- + class="tickbox" />
@@ -483,34 +516,42 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
<% } // if httpclient %> - <% if (true /* editBean.isAdvanced() */ ) { %> + <% if (true /* editBean.isAdvanced() */ ) { + int currentSigType = editBean.getSigType(curTunnel, tunnelType); + %>
- class="tickbox" /> + class="tickbox" />
<% if (editBean.isSigTypeAvailable(1)) { %>
- class="tickbox" /> + class="tickbox" />
<% } if (editBean.isSigTypeAvailable(2)) { %>
- class="tickbox" /> + class="tickbox" />
<% } if (editBean.isSigTypeAvailable(3)) { %>
- class="tickbox" /> + class="tickbox" /> +
+ <% } + if (editBean.isSigTypeAvailable(7)) { %> +
+ + class="tickbox" />
<% } // isAvailable %>
@@ -522,49 +563,49 @@ input.default { width: 1px; height: 1px; visibility: hidden; } <% if ("httpclient".equals(tunnelType) || "connectclient".equals(tunnelType) || "sockstunnel".equals(tunnelType) || "socksirctunnel".equals(tunnelType)) { %>
- +
class="tickbox" />
- +

- +
class="tickbox" />
- +

@@ -573,7 +614,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; } <% if ("httpclient".equals(tunnelType)) { %>
- +
@@ -585,9 +626,9 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
- +
diff --git a/apps/i2ptunnel/jsp/editServer.jsp b/apps/i2ptunnel/jsp/editServer.jsp index 437f8775b..22810a2ee 100644 --- a/apps/i2ptunnel/jsp/editServer.jsp +++ b/apps/i2ptunnel/jsp/editServer.jsp @@ -16,7 +16,7 @@ %> - <%=intl._("I2P Tunnel Manager - Edit Server Tunnel")%> + <%=intl._t("Hidden Services Manager")%> - <%=intl._t("Edit Hidden Service")%> @@ -44,20 +44,40 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
<% - String tunnelTypeName = ""; - String tunnelType = ""; + String tunnelTypeName; + String tunnelType; if (curTunnel >= 0) { tunnelTypeName = editBean.getTunnelType(curTunnel); tunnelType = editBean.getInternalType(curTunnel); - %>

<%=intl._("Edit server settings")%>

<% + %>

<%=intl._t("Edit server settings")%>

<% } else { tunnelTypeName = editBean.getTypeName(request.getParameter("type")); - tunnelType = request.getParameter("type"); - %>

<%=intl._("New server settings")%>

<% + tunnelType = net.i2p.data.DataHelper.stripHTML(request.getParameter("type")); + %>

<%=intl._t("New server settings")%>

<% } %> - " /> - + + + <% + // these are four keys that are generated automatically on first save, + // and we want to persist in i2ptunnel.config, but don't want to + // show clogging up the custom options form. + String key = editBean.getKey1(curTunnel); + if (key != null && key.length() > 0) { %> + + <% } + key = editBean.getKey2(curTunnel); + if (key != null && key.length() > 0) { %> + + <% } + key = editBean.getKey3(curTunnel); + if (key != null && key.length() > 0) { %> + + <% } + key = editBean.getKey4(curTunnel); + if (key != null && key.length() > 0) { %> + + <% } %>
@@ -67,26 +87,26 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
- + <%=tunnelTypeName%>
- +
class="tickbox" /> - <%=intl._("(Check the Box for 'YES')")%> + <%=intl._t("(Check the Box for 'YES')")%>
@@ -95,26 +115,26 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
<% if ("streamrserver".equals(tunnelType)) { %> - + <% } else { %> - + <% } %>
<% if (!"streamrserver".equals(tunnelType)) { %>
<% } /* !streamrserver */ %>
- +