From 01b153488ad4a8bd590a7dbac5cdf11c23e8ab97 Mon Sep 17 00:00:00 2001 From: zzz Date: Mon, 16 Dec 2013 16:12:32 +0000 Subject: [PATCH 01/40] i2psnark: - Move config file and DHT persistence file to a config dir - Move per-torrent configuration from "zmeta" in the main config file to a per-torrent config file (ticket #1132) - Split timestamp and bitfield into separate configs - Fix misspelling of autoStart config - Remove two unused SnarkManager methods --- .../src/org/klomp/snark/SnarkManager.java | 298 ++++++++++++++---- .../java/src/org/klomp/snark/dht/KRPC.java | 13 +- 2 files changed, 248 insertions(+), 63 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 3fe2b2ade3..dc1a9e92d6 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -14,6 +14,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; @@ -38,6 +39,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 @@ -53,7 +55,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; @@ -79,14 +84,19 @@ 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_STAMP = "stamp"; + private static final String PROP_META_BITFIELD = "bitfield"; + private static final String PROP_META_PRIORITY = "priority"; + 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:///"; @@ -107,6 +117,9 @@ public class SnarkManager implements CompleteListener { 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 String CONFIG_DIR_SUFFIX = ".d"; + private static final String SUBDIR_PREFIX = "s"; + private static final String B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"; /** * "name", "announceURL=websiteURL" pairs @@ -167,9 +180,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); } @@ -324,20 +339,179 @@ 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 16 subdirs for per-torrent config files + * Caller must synch. + * + * @return the new config directory, non-null + * @throws RuntimeException on creation fail + * @since 0.9.10 + */ + 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.10 + */ + 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.10 + */ + 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.10 + */ + 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); + } + /** 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); } } } @@ -371,6 +545,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 @@ -488,6 +663,18 @@ public class SnarkManager implements CompleteListener { 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, refreshDelay, + startDelay, pageSize, seedPct, eepHost, + eepPort, i2cpHost, i2cpPort, i2cpOpts, + upLimit, upBW, useOpenTrackers, useDHT, theme); + } + } + + private void locked_updateConfig(String dataDir, boolean filesPublic, boolean autoStart, 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) { boolean changed = false; boolean interruptMonitor = false; //if (eepHost != null) { @@ -819,7 +1006,7 @@ public class SnarkManager implements CompleteListener { public void saveConfig() { try { - synchronized (_configFile) { + synchronized (_configLock) { DataHelper.storeProps(_config, _configFile); } } catch (IOException ioe) { @@ -827,13 +1014,6 @@ public class SnarkManager implements CompleteListener { } } - 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; @@ -1218,16 +1398,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; } @@ -1241,16 +1415,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); @@ -1277,10 +1445,8 @@ 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(); @@ -1298,9 +1464,7 @@ public class SnarkManager implements CompleteListener { /** * 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. @@ -1309,10 +1473,13 @@ public class SnarkManager implements CompleteListener { * @param priorities may be null */ public void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities) { + synchronized (_configLock) { + locked_saveTorrentStatus(metainfo, bitfield, priorities); + } + } + + private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities) { byte[] ih = metainfo.getInfoHash(); - String infohash = Base64.encode(ih); - infohash = infohash.replace('=', '$'); - String now = "" + System.currentTimeMillis(); String bfs; if (bitfield.complete()) { bfs = "."; @@ -1320,10 +1487,11 @@ public class SnarkManager implements CompleteListener { byte[] bf = bitfield.getFieldBytes(); bfs = Base64.encode(bf); } - _config.setProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX, now + "," + bfs); + Properties config = getConfig(ih); + config.setProperty(PROP_META_STAMP, Long.toString(System.currentTimeMillis())); + config.setProperty(PROP_META_BITFIELD, bfs); // 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++) { @@ -1341,30 +1509,40 @@ 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); } // TODO save closest DHT nodes too - saveConfig(); + File conf = configFile(_configDir, ih); + File subdir = conf.getParentFile(); + if (!subdir.exists()) + subdir.mkdirs(); + try { + DataHelper.storeProps(config, conf); + } catch (IOException ioe) { + _log.error("Unable to save the config to " + conf); + } } /** - * Remove the status of a torrent from the config file. - * This may help the config file from growing too big. + * Remove the status of a torrent by removing the config file. */ 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(); + File conf = configFile(_configDir, ih); + synchronized (_configLock) { + conf.delete(); + File subdir = conf.getParentFile(); + String[] files = subdir.list(); + if (files != null && files.length == 0) + subdir.delete(); + } } /** 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 1ea2c9917e..652ef0e9da 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java @@ -39,6 +39,7 @@ import net.i2p.util.I2PAppThread; import net.i2p.util.Log; import net.i2p.util.SimpleTimer2; +import org.klomp.snark.SnarkManager; import org.klomp.snark.TrackerClient; import org.klomp.snark.bencode.BDecoder; import org.klomp.snark.bencode.BEncoder; @@ -151,7 +152,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; @@ -184,8 +185,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(); From 30ccf1b33402e1f2a75b4809dc6945e96c657416 Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 22 Dec 2013 13:52:35 +0000 Subject: [PATCH 02/40] i2psnark: - Refactor file deletion in prep for better file name handling (ticket #571) - Don't use canonical files in directory listings, for speed and to avoid file comparison problems (tickets #1079, #1148) - Set base file/dir in Storage constructor, make final, in prep for arbitrary locations (ticket #1028) --- .../java/src/org/klomp/snark/Snark.java | 19 ++- .../java/src/org/klomp/snark/Storage.java | 142 ++++++++++-------- .../org/klomp/snark/web/I2PSnarkServlet.java | 63 ++++---- 3 files changed, 114 insertions(+), 110 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java index ba4dfc286c..398d9bd6ea 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java @@ -223,7 +223,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; @@ -291,7 +291,7 @@ public class Snark acceptor = connectionAcceptor; this.torrent = torrent; - this.rootDataDir = rootDir; + this.rootDataDir = new File(rootDir); stopped = true; activity = "Network setup"; @@ -395,13 +395,12 @@ public class Snark try { activity = "Checking storage"; - storage = new Storage(_util, meta, slistener); + storage = new Storage(_util, rootDataDir, meta, slistener); 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) @@ -453,7 +452,7 @@ public class Snark this.torrent = torrent; this.infoHash = ih; this.additionalTrackerURL = trackerURL; - this.rootDataDir = rootDir; + this.rootDataDir = new File(rootDir); stopped = true; id = generateID(); @@ -548,7 +547,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(); @@ -1104,8 +1103,8 @@ public class Snark public void gotMetaInfo(PeerCoordinator coordinator, MetaInfo metainfo) { try { // The following two may throw IOE... - storage = new Storage(_util, metainfo, this); - storage.check(rootDataDir); + storage = new Storage(_util, rootDataDir, metainfo, this); + storage.check(); // ... so don't set meta until here meta = metainfo; if (completeListener != null) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 8b2b5a39b9..e9bf050b8c 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -32,7 +32,9 @@ 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; @@ -52,6 +54,7 @@ public class Storage { private final MetaInfo metainfo; private final List _torrentFiles; + private final File _base; private final StorageListener listener; private final I2PSnarkUtil _util; private final Log _log; @@ -88,10 +91,15 @@ public class Storage * * Does not check storage. Caller MUST call check() */ - public Storage(I2PSnarkUtil util, MetaInfo metainfo, StorageListener listener) + public Storage(I2PSnarkUtil util, File rootDir, MetaInfo metainfo, StorageListener listener) { _util = util; _log = util.getContext().logManager().getLog(Storage.class); + boolean areFilesPublic = _util.getFilesPublic(); + if (areFilesPublic) + _base = new File(rootDir, filterName(metainfo.getName())); + else + _base = new SecureFile(rootDir, filterName(metainfo.getName())); this.metainfo = metainfo; this.listener = listener; needed = metainfo.getPieces(); @@ -121,6 +129,7 @@ public class Storage throws IOException { _util = util; + _base = baseFile; _log = util.getContext().logManager().getLog(Storage.class); this.listener = listener; // Create names, rafs and lengths arrays. @@ -305,24 +314,15 @@ public class Storage } /** - * @param file canonical path (non-directory) + * @param file non-canonical path (non-directory) * @return number of bytes remaining; -1 if unknown file * @since 0.7.14 */ - public long remaining(String file) { + public long remaining(File file) { 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 (f.equals(file)) { if (complete()) return 0; int psz = piece_size; @@ -348,22 +348,16 @@ public class Storage } /** - * @param file canonical path (non-directory) + * @param file non-canonical path (non-directory) * @since 0.8.1 */ - public int getPriority(String file) { + public int getPriority(File file) { 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) {} - } + if (f.equals(file)) + return tf.priority; } return 0; } @@ -371,24 +365,18 @@ public class Storage /** * Must call Snark.updatePiecePriorities() * (which calls getPiecePriorities()) after calling this. - * @param file canonical path (non-directory) + * @param file non-canonical path (non-directory) * @param pri default 0; <0 to disable * @since 0.8.1 */ - public void setPriority(String file, int pri) { + public void setPriority(File file, 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 (f.equals(file)) { + tf.priority = pri; + return; } } } @@ -490,9 +478,9 @@ public class Storage * Creates (and/or checks) all files from the metainfo file list. * Only call this once, and only after the constructor with the metainfo. */ - public void check(String rootDir) throws IOException + public void check() throws IOException { - check(rootDir, 0, null); + check(0, null); } /** @@ -500,14 +488,9 @@ public class Storage * Use a saved bitfield and timestamp from a config file. * Only call this once, and only after the constructor with the metainfo. */ - 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,16 +500,16 @@ public class Storage { // Create base as file. if (_log.shouldLog(Log.INFO)) - _log.info("Creating/Checking file: " + base); - if (!base.createNewFile() && !base.exists()) - throw new IOException("Could not create file " + base); + _log.info("Creating/Checking file: " + _base); + if (!_base.createNewFile() && !_base.exists()) + 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; } } @@ -534,9 +517,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(); @@ -544,7 +527,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)) { @@ -560,12 +543,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(); @@ -612,7 +595,7 @@ public class Storage * @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"); @@ -688,6 +671,8 @@ 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 { @@ -721,15 +706,46 @@ 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 a new List + */ + public File getBase() { + return _base; + } + + /** + * Does not include directories. Unsorted. + * @since 0.9.10 + * @return a new List + */ + public List getFiles() { + List rv = new ArrayList(_torrentFiles.size()); + for (TorrentFile tf : _torrentFiles) { + rv.add(tf.RAFfile); } - return base; + return rv; + } + + /** + * Includes the base for a multi-file torrent. + * Sorted bottom-up for easy deletion. + * Slow. Use for deletion only. + * @since 0.9.10 + * @return a new Set or null for a single-file torrent + */ + 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; } /** 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 a77fbf0938..466c8d897d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -17,7 +17,6 @@ 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; @@ -828,42 +827,36 @@ public class I2PSnarkServlet extends BasicServlet { _manager.addMessage(_("Data file could not be deleted: {0}", f.getAbsolutePath())); break; } + Storage storage = snark.getStorage(); + if (storage == null) + break; // step 1 delete files - for (int i = 0; i < files.size(); i++) { - // multifile torrents have the getFiles() return lists of lists of filenames, but - // each of those lists just contain a single file afaict... - File df = Storage.getFileFromNames(f, files.get(i)); + for (File df : storage.getFiles()) { if (df.delete()) { //_manager.addMessage(_("Data file deleted: {0}", df.getAbsolutePath())); } else { _manager.addMessage(_("Data file could not be deleted: {0}", df.getAbsolutePath())); } } - // step 2 make Set of dirs with reverse sort - Set dirs = new TreeSet(Collections.reverseOrder()); - for (List list : files) { - for (int i = 1; i < list.size(); i++) { - dirs.add(Storage.getFileFromNames(f, list.subList(0, i))); - } - } - // step 3 delete dirs bottom-up + // step 2 delete dirs bottom-up + Set dirs = storage.getDirectories(); + if (_log.shouldLog(Log.INFO)) + _log.info("Dirs to delete: " + DataHelper.toString(dirs)); + boolean ok = false; for (File df : dirs) { if (df.delete()) { + ok = true; //_manager.addMessage(_("Data dir deleted: {0}", df.getAbsolutePath())); } else { + ok = false; _manager.addMessage(_("Directory could not be deleted: {0}", df.getAbsolutePath())); if (_log.shouldLog(Log.WARN)) _log.warn("Could not delete dir " + df); } } - // step 4 delete base - if (f.delete()) { - _manager.addMessage(_("Directory deleted: {0}", f.getAbsolutePath())); - } else { - _manager.addMessage(_("Directory could not be deleted: {0}", f.getAbsolutePath())); - if (_log.shouldLog(Log.WARN)) - _log.warn("Could not delete dir " + f); - } + // step 3 message for base (last one) + if (ok) + _manager.addMessage(_("Directory deleted: {0}", storage.getBase())); break; } } @@ -2462,6 +2455,7 @@ public class I2PSnarkServlet extends BasicServlet { boolean complete = false; String status = ""; long length = item.length(); + int priority = 0; if (item.isDirectory()) { complete = true; //status = toImg("tick") + ' ' + _("Directory"); @@ -2472,9 +2466,8 @@ public class I2PSnarkServlet extends BasicServlet { status = toImg("cancel") + ' ' + _("Torrent not found?"); } else { Storage storage = snark.getStorage(); - try { - File f = item; - long remaining = storage.remaining(f.getCanonicalPath()); + + long remaining = storage.remaining(item); if (remaining < 0) { complete = true; status = toImg("cancel") + ' ' + _("File not found in torrent?"); @@ -2482,7 +2475,7 @@ public class I2PSnarkServlet extends BasicServlet { complete = true; status = toImg("tick") + ' ' + _("Complete"); } else { - int priority = storage.getPriority(f.getCanonicalPath()); + priority = storage.getPriority(item); if (priority < 0) status = toImg("cancel"); else if (priority == 0) @@ -2493,9 +2486,7 @@ public class I2PSnarkServlet extends BasicServlet { (100 * (length - remaining) / length) + "% " + _("complete") + " (" + DataHelper.formatSize2(remaining) + "B " + _("remaining") + ")"; } - } catch (IOException ioe) { - status = "Not a file? " + ioe; - } + } } @@ -2534,21 +2525,19 @@ public class I2PSnarkServlet extends BasicServlet { buf.append(""); if (showPriority) { buf.append(""); - File f = item; if ((!complete) && (!item.isDirectory())) { - int pri = snark.getStorage().getPriority(f.getCanonicalPath()); - buf.append(" 0) + buf.append(" 0) buf.append("checked=\"true\""); buf.append('>').append(_("High")); - buf.append("').append(_("Normal")); - buf.append("').append(_("Skip")); showSaveButton = true; @@ -2643,7 +2632,7 @@ public class I2PSnarkServlet extends BasicServlet { String key = entry.getKey(); if (key.startsWith("pri.")) { try { - String file = key.substring(4); + File file = new File(key.substring(4)); String val = entry.getValue()[0]; // jetty arrays int pri = Integer.parseInt(val); storage.setPriority(file, pri); From a2e7fa8b7bac17f6bfab3cc29d4edfc210f6e655 Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 22 Dec 2013 14:23:01 +0000 Subject: [PATCH 03/40] another minor dir listing speedup --- .../java/src/org/klomp/snark/web/I2PSnarkServlet.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 466c8d897d..acadc8aaa4 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -2154,9 +2154,11 @@ public class I2PSnarkServlet extends BasicServlet { private final Comparator collator = Collator.getInstance(); public int compare(File l, File r) { - if (l.isDirectory() && !r.isDirectory()) + boolean ld = l.isDirectory(); + boolean rd = r.isDirectory(); + if (ld && !rd) return -1; - if (r.isDirectory() && !l.isDirectory()) + if (rd && !ld) return 1; return collator.compare(l.getName(), r.getName()); } From 18146daad837cfd9884fdf931747258e316ede61 Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 26 Jan 2014 14:26:16 +0000 Subject: [PATCH 04/40] i2psnark: - Add missing nonce protection for file priority setting - Add torrent mime type - String append cleanup --- .../org/klomp/snark/web/I2PSnarkServlet.java | 46 ++++++++++++------- apps/i2psnark/mime.properties | 1 + 2 files changed, 30 insertions(+), 17 deletions(-) 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 acadc8aaa4..be980112ab 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -185,7 +185,8 @@ 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() @@ -2219,7 +2220,14 @@ public class I2PSnarkServlet extends BasicServlet { if (snark != null && postParams != null) { // caller must P-R-G - savePriorities(snark, postParams); + String[] val = postParams.get("nonce"); + if (val != null) { + String nonce = val[0]; + if (String.valueOf(_nonce).equals(nonce)) + savePriorities(snark, postParams); + else + _manager.addMessage("Please retry form submission (bad nonce)"); + } return null; } @@ -2232,7 +2240,7 @@ public class I2PSnarkServlet extends BasicServlet { buf.append(title); buf.append("").append(HEADER_A).append(_themePath).append(HEADER_B).append("" + "\n
\"\"  "); + buf.append(" class=\"snarkRefresh\">\"\"  "); if (_contextName.equals(DEFAULT_NAME)) buf.append(_("I2PSnark")); else @@ -2242,8 +2250,10 @@ public class I2PSnarkServlet extends BasicServlet { if (parent) // always true buf.append("
"); boolean showPriority = ls != null && snark != null && snark.getStorage() != null && !snark.getStorage().complete(); - if (showPriority) + if (showPriority) { buf.append("
\n"); + buf.append("\n"); + } if (snark != null) { // first table - torrent info buf.append("\n"); @@ -2256,7 +2266,7 @@ public class I2PSnarkServlet extends BasicServlet { String fullPath = snark.getName(); String baseName = urlEncode((new File(fullPath)).getName()); buf.append(""); buf.append("
") - .append("\"\" ") + .append("\"\" ") .append(_("Torrent file")) .append(": ") .append(fullPath) @@ -2348,40 +2358,40 @@ public class I2PSnarkServlet extends BasicServlet { // .append(MAGGOT).append(hex).append(':').append(hex).append("
") - .append("\"\" ") + .append("\"\" ") .append(_("Size")) .append(": ") .append(formatSize(snark.getTotalLength())); int pieces = snark.getPieces(); double completion = (pieces - snark.getNeeded()) / (double) pieces; if (completion < 1.0) - buf.append(" \"\" ") + buf.append(" \"\" ") .append(_("Completion")) .append(": ") .append((new DecimalFormat("0.00%")).format(completion)); else - buf.append(" \"\" ") + buf.append(" \"\" ") .append(_("Complete")); // else unknown long needed = snark.getNeededLength(); if (needed > 0) - buf.append(" \"\" ") + buf.append(" \"\" ") .append(_("Remaining")) .append(": ") .append(formatSize(needed)); if (meta != null) { List> files = meta.getFiles(); int fileCount = files != null ? files.size() : 1; - buf.append(" \"\" ") + buf.append(" \"\" ") .append(_("Files")) .append(": ") .append(fileCount); } - buf.append(" \"\" ") + buf.append(" \"\" ") .append(_("Pieces")) .append(": ") .append(pieces); - buf.append(" \"\" ") + buf.append(" \"\" ") .append(_("Piece size")) .append(": ") .append(formatSize(snark.getPieceLength(0))) @@ -2404,7 +2414,7 @@ public class I2PSnarkServlet extends BasicServlet { buf.append("\n"); buf.append("\n") .append("\n"); buf.append("\n"); buf.append("\n"); if (showPriority) buf.append("\n"); buf.append("\n"); @@ -2610,6 +2620,8 @@ 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; diff --git a/apps/i2psnark/mime.properties b/apps/i2psnark/mime.properties index 927155d9a7..b251fb72ea 100644 --- a/apps/i2psnark/mime.properties +++ b/apps/i2psnark/mime.properties @@ -24,6 +24,7 @@ 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 From 47712a39aca0606f34eca9762cf12c5624a43885 Mon Sep 17 00:00:00 2001 From: zzz Date: Mon, 27 Jan 2014 13:41:38 +0000 Subject: [PATCH 05/40] i2psnark: - Support arbitrary location for torrent data. Save location in per-torrent config file. TODO: Fix torrent browse pages (ticket #1028) - Enhance idle shutdown message - Javadocs --- .../java/src/org/klomp/snark/IdleChecker.java | 3 +- .../java/src/org/klomp/snark/PeerState.java | 2 +- .../java/src/org/klomp/snark/Snark.java | 49 ++++++++++++-- .../src/org/klomp/snark/SnarkManager.java | 64 ++++++++++++++----- .../java/src/org/klomp/snark/Storage.java | 21 +++--- .../org/klomp/snark/web/I2PSnarkServlet.java | 46 +++++++++---- 6 files changed, 138 insertions(+), 47 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/IdleChecker.java b/apps/i2psnark/java/src/org/klomp/snark/IdleChecker.java index ff6454ee23..58a73b668f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/IdleChecker.java +++ b/apps/i2psnark/java/src/org/klomp/snark/IdleChecker.java @@ -66,7 +66,8 @@ 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; } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java index 35008394e8..cf295a530d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java @@ -163,7 +163,7 @@ class PeerState implements DataLoader _log.debug(peer + " rcv bitfield"); 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; diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java index 398d9bd6ea..20d8f4294d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java @@ -34,6 +34,7 @@ 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. @@ -238,13 +239,21 @@ public class Snark private volatile boolean _autoStoppable; - /** 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); @@ -275,11 +284,28 @@ public class Snark this.startTorrent(); } - /** multitorrent */ + /** + * multitorrent + */ 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 + * @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; @@ -395,7 +421,14 @@ public class Snark try { activity = "Checking storage"; - storage = new Storage(_util, rootDataDir, meta, slistener); + if (baseFile == null) { + String base = Storage.filterName(meta.getName()); + if (_util.getFilesPublic()) + baseFile = new File(rootDataDir, base); + else + baseFile = new SecureFile(rootDataDir, base); + } + storage = new Storage(_util, baseFile, meta, slistener); if (completeListener != null) { storage.check(completeListener.getSavedTorrentTime(this), completeListener.getSavedTorrentBitField(this)); @@ -1102,8 +1135,14 @@ 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, rootDataDir, metainfo, this); + storage = new Storage(_util, baseFile, metainfo, this); storage.check(); // ... so don't set meta until here meta = metainfo; diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index dc1a9e92d6..92a14e400a 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -86,6 +86,7 @@ public class SnarkManager implements CompleteListener { public static final String PROP_DIR = "i2psnark.dir"; private static final String PROP_META_PREFIX = "i2psnark.zmeta."; 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_BITFIELD_SUFFIX = ".bitfield"; @@ -347,7 +348,7 @@ public class SnarkManager implements CompleteListener { * * @return the new config directory, non-null * @throws RuntimeException on creation fail - * @since 0.9.10 + * @since 0.9.11 */ private File migrateConfig(File oldFile) { File dir = new SecureDirectory(oldFile + CONFIG_DIR_SUFFIX); @@ -455,7 +456,7 @@ public class SnarkManager implements CompleteListener { /** * The config for a torrent * @return non-null, possibly empty - * @since 0.9.10 + * @since 0.9.11 */ private Properties getConfig(Snark snark) { return getConfig(snark.getInfoHash()); @@ -465,7 +466,7 @@ public class SnarkManager implements CompleteListener { * The config for a torrent * @param ih 20-byte infohash * @return non-null, possibly empty - * @since 0.9.10 + * @since 0.9.11 */ private Properties getConfig(byte[] ih) { Properties rv = new OrderedProperties(); @@ -482,7 +483,7 @@ public class SnarkManager implements CompleteListener { * The config file for a torrent * @param confDir the config directory * @param ih 20-byte infohash - * @since 0.9.10 + * @since 0.9.11 */ private static File configFile(File confDir, byte[] ih) { String hex = I2PSnarkUtil.toHex(ih); @@ -1071,15 +1072,23 @@ 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 rootDataDir * @throws RuntimeException via Snark.fatal() */ - private void addTorrent(String filename) { addTorrent(filename, false); } + private void addTorrent(String filename) { + addTorrent(filename, null, false); + } /** * 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 rootDataDir * @throws RuntimeException via Snark.fatal() */ - private void addTorrent(String filename, boolean dontAutoStart) { + private void addTorrent(String filename, File baseFile, boolean dontAutoStart) { if ((!dontAutoStart) && !_util.connected()) { addMessage(_("Connecting to I2P")); boolean ok = _util.connect(); @@ -1160,9 +1169,13 @@ public class SnarkManager implements CompleteListener { } else { // 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, - false, dataDir.getPath()); + false, dataDir.getPath(), baseFile); loadSavedFilePriorities(torrent); synchronized (_snarks) { _snarks.put(filename, torrent); @@ -1305,14 +1318,17 @@ 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. + * * @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() * @since 0.8.4 */ - public void addTorrent(MetaInfo metainfo, BitField bitfield, String filename, boolean dontAutoStart) throws IOException { + public void addTorrent(MetaInfo metainfo, BitField bitfield, String filename, File baseFile, boolean dontAutoStart) throws IOException { // prevent interference by DirMonitor synchronized (_snarks) { Snark snark = getTorrentByInfoHash(metainfo.getInfoHash()); @@ -1321,11 +1337,11 @@ public class SnarkManager implements CompleteListener { return; } // so addTorrent won't recheck - saveTorrentStatus(metainfo, bitfield, null); // no file priorities + saveTorrentStatus(metainfo, bitfield, null, baseFile); // no file priorities 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)); _log.error("Failed to write torrent file", ioe); @@ -1461,6 +1477,19 @@ 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.11 + */ + public File getSavedBaseFile(byte[] ih) { + Properties config = getConfig(ih); + String base = config.getProperty(PROP_META_BASE); + if (base == null) + return null; + return new File(base); + } /** * Save the completion status of a torrent and the current time in the config file @@ -1471,14 +1500,15 @@ public class SnarkManager implements CompleteListener { * * @param bitfield non-null * @param priorities may be null + * @param base may be null */ - public void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities) { + public void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, File base) { synchronized (_configLock) { - locked_saveTorrentStatus(metainfo, bitfield, priorities); + locked_saveTorrentStatus(metainfo, bitfield, priorities, base); } } - private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities) { + private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, File base) { byte[] ih = metainfo.getInfoHash(); String bfs; if (bitfield.complete()) { @@ -1490,6 +1520,8 @@ public class SnarkManager implements CompleteListener { Properties config = getConfig(ih); config.setProperty(PROP_META_STAMP, Long.toString(System.currentTimeMillis())); config.setProperty(PROP_META_BITFIELD, bfs); + if (base != null) + config.setProperty(PROP_META_BASE, base.getAbsolutePath()); // now the file priorities if (priorities != null) { @@ -1742,7 +1774,7 @@ 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()); } /** @@ -1764,7 +1796,7 @@ public class SnarkManager implements CompleteListener { snark.stopTorrent(); return null; } - saveTorrentStatus(meta, storage.getBitField(), null); // no file priorities + saveTorrentStatus(meta, storage.getBitField(), null, storage.getBase()); // no file priorities // temp for addMessage() in case canonical throws String name = storage.getBaseName(); try { @@ -1865,7 +1897,7 @@ public class SnarkManager implements CompleteListener { try { // Snark.fatal() throws a RuntimeException // don't let one bad torrent kill the whole loop - addTorrent(name, !shouldAutoStart()); + addTorrent(name, null, !shouldAutoStart()); } catch (Exception e) { addMessage(_("Error: Could not add the torrent {0}", name) + ": " + e); _log.error("Unable to add the torrent " + name, e); diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index e9bf050b8c..b353f4284f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -86,20 +86,18 @@ public class Storage 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 */ - public Storage(I2PSnarkUtil util, File rootDir, MetaInfo metainfo, StorageListener listener) + public Storage(I2PSnarkUtil util, File baseFile, MetaInfo metainfo, StorageListener listener) { _util = util; _log = util.getContext().logManager().getLog(Storage.class); - boolean areFilesPublic = _util.getFilesPublic(); - if (areFilesPublic) - _base = new File(rootDir, filterName(metainfo.getName())); - else - _base = new SecureFile(rootDir, filterName(metainfo.getName())); + _base = baseFile; this.metainfo = metainfo; this.listener = listener; needed = metainfo.getPieces(); @@ -708,7 +706,8 @@ public class Storage /** * The base file or directory. - * @return a new List + * @return the File + * @since 0.9.11 */ public File getBase() { return _base; @@ -716,8 +715,8 @@ public class Storage /** * Does not include directories. Unsorted. - * @since 0.9.10 * @return a new List + * @since 0.9.11 */ public List getFiles() { List rv = new ArrayList(_torrentFiles.size()); @@ -731,7 +730,7 @@ public class Storage * Includes the base for a multi-file torrent. * Sorted bottom-up for easy deletion. * Slow. Use for deletion only. - * @since 0.9.10 + * @since 0.9.11 * @return a new Set or null for a single-file torrent */ public SortedSet getDirectories() { 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 be980112ab..82c0345d7c 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -896,7 +896,9 @@ public class I2PSnarkServlet extends BasicServlet { } else if ("Create".equals(action)) { String baseData = req.getParameter("baseFile"); if (baseData != null && baseData.trim().length() > 0) { - File baseFile = new File(_manager.getDataDir(), baseData); + File baseFile = new File(baseData.trim()); + if (!baseFile.isAbsolute()) + baseFile = new File(_manager.getDataDir(), baseData); String announceURL = req.getParameter("announceURL"); // make the user add a tracker on the config form now //String announceURLOther = req.getParameter("announceURLOther"); @@ -956,7 +958,7 @@ public class I2PSnarkServlet extends BasicServlet { File torrentFile = new File(_manager.getDataDir(), s.getBaseName() + ".torrent"); // FIXME is the storage going to stay around thanks to the info reference? // now add it, but don't automatically start it - _manager.addTorrent(info, s.getBitField(), torrentFile.getAbsolutePath(), true); + _manager.addTorrent(info, s.getBitField(), torrentFile.getAbsolutePath(), baseFile, true); _manager.addMessage(_("Torrent created for \"{0}\"", baseFile.getName()) + ": " + torrentFile.getAbsolutePath()); if (announceURL != null && !_manager.util().getOpenTrackers().contains(announceURL)) _manager.addMessage(_("Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\"", baseFile.getName())); @@ -1708,10 +1710,11 @@ public class I2PSnarkServlet extends BasicServlet { out.write("
\n
") - .append("") - .append("\"")") - .append("\"")") - .append("\"")\n
\"\" ") + buf.append("\">\"\" ") .append(_("Up to higher level directory")) .append("
\n"); String fullPath = snark.getName(); - String baseName = urlEncode((new File(fullPath)).getName()); + String baseName = encodePath((new File(fullPath)).getName()); buf.append("\n"); buf.append("\n"); String announce = null; @@ -2593,7 +2635,7 @@ public class I2PSnarkServlet extends BasicServlet { .append("\">\n"); buf.append("\n\n"); buf.append("\n"); @@ -2604,7 +2646,7 @@ public class I2PSnarkServlet extends BasicServlet { boolean showSaveButton = false; for (int i=0 ; i< ls.length ; i++) { - 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 @@ -2653,10 +2695,10 @@ public class I2PSnarkServlet extends BasicServlet { } } - String path=addPaths(base,encoded); + String path = addPaths(decodedBase, ls[i].getName()); if (item.isDirectory() && !path.endsWith("/")) path=addPaths(path,"/"); - path = urlEncode(path); + path = encodePath(path); String icon = toIcon(item); buf.append("
"); //out.write("From file:
\n"); out.write(_("Data to seed")); - out.write(":
" + _manager.getDataDir().getAbsolutePath() + File.separatorChar - + "" + + "
\n"); out.write(_("Trackers")); out.write(":\n"); + buf.append("\n"); MetaInfo meta = snark.getMetaInfo(); if (meta != null) { @@ -2404,6 +2408,22 @@ public class I2PSnarkServlet extends BasicServlet { .append("\"\n"); } buf.append("
"); @@ -2198,12 +2201,6 @@ public class I2PSnarkServlet extends BasicServlet { private String getListHTML(File r, String base, boolean parent, Map postParams) throws IOException { - File[] ls = null; - if (r.isDirectory()) { - ls = r.listFiles(); - Arrays.sort(ls, new ListingComparator()); - } // if r is not a directory, we are only showing torrent info section - String title = decodePath(base); String cpath = _contextPath + '/'; if (title.startsWith(cpath)) @@ -2249,7 +2246,8 @@ public class I2PSnarkServlet extends BasicServlet { if (parent) // always true buf.append("
"); - boolean showPriority = ls != null && snark != null && snark.getStorage() != null && !snark.getStorage().complete(); + boolean showPriority = snark != null && snark.getStorage() != null && !snark.getStorage().complete() && + r.isDirectory(); if (showPriority) { buf.append("\n"); buf.append("\n"); @@ -2271,6 +2269,12 @@ public class I2PSnarkServlet extends BasicServlet { .append(": ") .append(fullPath) .append("
") + .append("\"\" ") + .append(_("Data location")) + .append(": ") + .append(urlEncode(snark.getStorage().getBase().getPath())) + .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(); + Arrays.sort(ls, new ListingComparator()); + } // 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(""); @@ -2655,6 +2675,6 @@ public class I2PSnarkServlet extends BasicServlet { } } snark.updatePiecePriorities(); - _manager.saveTorrentStatus(snark.getMetaInfo(), storage.getBitField(), storage.getFilePriorities()); + _manager.saveTorrentStatus(snark.getMetaInfo(), storage.getBitField(), storage.getFilePriorities(), storage.getBase()); } } From c987a9735d5b801dd7f79f8897ea2b5a5fbe44a5 Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 21 Jun 2014 13:16:38 +0000 Subject: [PATCH 06/40] fixup after prop --- apps/i2psnark/java/src/org/klomp/snark/Storage.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index abb80bd942..f0477b4787 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -498,11 +498,11 @@ 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())); if (useSavedBitField) { From 8f2dc67430d19a9c6876fc7d156ab91083d52028 Mon Sep 17 00:00:00 2001 From: zzz Date: Wed, 25 Jun 2014 13:58:34 +0000 Subject: [PATCH 07/40] - Fix files not found in listing at top level of torrent - Fix loading of files outside of snark dir --- .../src/org/klomp/snark/web/BasicServlet.java | 7 +- .../org/klomp/snark/web/I2PSnarkServlet.java | 66 ++++++++++++++++--- 2 files changed, 60 insertions(+), 13 deletions(-) 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 53a501af37..350a6bb689 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; 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 6b6d62a408..e196017154 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -58,6 +58,7 @@ 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 = "/.icons/"; public I2PSnarkServlet() { super(); @@ -83,7 +84,7 @@ public class I2PSnarkServlet extends BasicServlet { _manager.start(); loadMimeMap("org/klomp/snark/web/mime"); setResourceBase(_manager.getDataDir()); - setWarBase("/.icons/"); + setWarBase(WARBASE); } @Override @@ -94,17 +95,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); } @@ -187,6 +206,14 @@ public class I2PSnarkServlet extends BasicServlet { return; } + // 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); + } + 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") || @@ -2251,14 +2278,14 @@ public class I2PSnarkServlet extends BasicServlet { * * * Get the resource list as a HTML directory listing. - * @param r The Resource + * @param xxxr The Resource unused * @param base The base URL * @param parent True if the parent directory should be included * @param postParams map of POST parameters or null if not a POST * @return String of HTML or null if postParams != null * @since 0.7.14 */ - private String getListHTML(File r, String base, boolean parent, Map postParams) + private String getListHTML(File xxxr, String base, boolean parent, Map postParams) throws IOException { String title = decodePath(base); @@ -2268,11 +2295,15 @@ public class I2PSnarkServlet extends BasicServlet { // Get the snark associated with this directory String torrentName; + String pathInTorrent; int slash = title.indexOf('/'); - if (slash > 0) + if (slash > 0) { torrentName = title.substring(0, slash); - else + pathInTorrent = title.substring(slash); + } else { torrentName = title; + pathInTorrent = "/"; + } Snark snark = _manager.getTorrentByBaseName(torrentName); if (snark != null && postParams != null) { @@ -2288,6 +2319,23 @@ public class I2PSnarkServlet extends BasicServlet { return null; } + File r; + if (snark != null) { + Storage storage = snark.getStorage(); + if (storage != null) { + File sbase = storage.getBase(); + if (pathInTorrent.equals("/")) + r = sbase; + else + r = new File(sbase, pathInTorrent); + } else { + // magnet, dummy + r = new File(""); + } + } else { + // dummy + r = new File(""); + } StringBuilder buf=new StringBuilder(4096); buf.append(DOCTYPE).append(""); if (title.endsWith("/")) From d48991f71f9b919b5c8e6d959faaeae9236f2202 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 9 Jul 2014 13:52:26 +0000 Subject: [PATCH 08/40] Crypto: Move TransientSessionKeyManager from core to router. I2PAppContext will return the dummy SessionKeyManager which is sufficient for non-tag uses (e.g. Bote). Client use of end-to-end encryption using SessionTags was disabled in release 0.6, 2005-07-27. --- core/java/src/net/i2p/I2PAppContext.java | 12 +++++++----- .../src/net/i2p/router/RouterContext.java | 19 ++++++++++++++++++- .../router/client/ClientConnectionRunner.java | 2 +- .../crypto/TransientSessionKeyManager.java | 4 +++- .../src/net/i2p/router/crypto/package.html | 7 +++++++ 5 files changed, 36 insertions(+), 8 deletions(-) rename {core/java/src/net/i2p => router/java/src/net/i2p/router}/crypto/TransientSessionKeyManager.java (99%) create mode 100644 router/java/src/net/i2p/router/crypto/package.html diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java index 69e110632e..8357a485ac 100644 --- a/core/java/src/net/i2p/I2PAppContext.java +++ b/core/java/src/net/i2p/I2PAppContext.java @@ -22,7 +22,6 @@ import net.i2p.crypto.HMACGenerator; import net.i2p.crypto.KeyGenerator; import net.i2p.crypto.SHA256Generator; import net.i2p.crypto.SessionKeyManager; -import net.i2p.crypto.TransientSessionKeyManager; import net.i2p.data.Base64; import net.i2p.data.RoutingKeyGenerator; import net.i2p.internal.InternalClientManager; @@ -76,7 +75,7 @@ public class I2PAppContext { protected final I2PProperties _overrideProps; private StatManager _statManager; - private SessionKeyManager _sessionKeyManager; + protected SessionKeyManager _sessionKeyManager; private NamingService _namingService; private ElGamalEngine _elGamalEngine; private ElGamalAESEngine _elGamalAESEngine; @@ -96,7 +95,7 @@ public class I2PAppContext { private SimpleTimer2 _simpleTimer2; private final PortMapper _portMapper; private volatile boolean _statManagerInitialized; - private volatile boolean _sessionKeyManagerInitialized; + protected volatile boolean _sessionKeyManagerInitialized; private volatile boolean _namingServiceInitialized; private volatile boolean _elGamalEngineInitialized; private volatile boolean _elGamalAESEngineInitialized; @@ -599,6 +598,9 @@ public class I2PAppContext { * For client crypto within the router, * use RouterContext.clientManager.getClientSessionKeyManager(dest) * + * As of 0.9.15, this returns a dummy SessionKeyManager in I2PAppContext. + * The dummy SKM does NOT handle session tags. + * Overridden in RouterContext to return the full TransientSessionKeyManager. */ public SessionKeyManager sessionKeyManager() { if (!_sessionKeyManagerInitialized) @@ -606,11 +608,11 @@ public class I2PAppContext { return _sessionKeyManager; } - private void initializeSessionKeyManager() { + protected void initializeSessionKeyManager() { synchronized (_lock3) { if (_sessionKeyManager == null) //_sessionKeyManager = new PersistentSessionKeyManager(this); - _sessionKeyManager = new TransientSessionKeyManager(this); + _sessionKeyManager = new SessionKeyManager(this); _sessionKeyManagerInitialized = true; } } diff --git a/router/java/src/net/i2p/router/RouterContext.java b/router/java/src/net/i2p/router/RouterContext.java index 0afd98a7b5..1f8a38af68 100644 --- a/router/java/src/net/i2p/router/RouterContext.java +++ b/router/java/src/net/i2p/router/RouterContext.java @@ -13,6 +13,7 @@ import net.i2p.data.Hash; import net.i2p.data.RouterInfo; import net.i2p.internal.InternalClientManager; import net.i2p.router.client.ClientManagerFacadeImpl; +import net.i2p.router.crypto.TransientSessionKeyManager; import net.i2p.router.dummy.*; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; import net.i2p.router.peermanager.PeerManagerFacadeImpl; @@ -67,7 +68,7 @@ public class RouterContext extends I2PAppContext { private final Set<Runnable> _finalShutdownTasks; // split up big lock on this to avoid deadlocks private volatile boolean _initialized; - private final Object _lock1 = new Object(), _lock2 = new Object(); + private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object(); private static final List<RouterContext> _contexts = new CopyOnWriteArrayList<RouterContext>(); @@ -565,4 +566,20 @@ public class RouterContext extends I2PAppContext { public RouterAppManager routerAppManager() { return _appManager; } + + /** + * As of 0.9.15, this returns a dummy SessionKeyManager in I2PAppContext. + * Overridden in RouterContext to return the full TransientSessionKeyManager. + * + * @since 0.9.15 + */ + @Override + protected void initializeSessionKeyManager() { + synchronized (_lock3) { + if (_sessionKeyManager == null) + //_sessionKeyManager = new PersistentSessionKeyManager(this); + _sessionKeyManager = new TransientSessionKeyManager(this); + _sessionKeyManagerInitialized = true; + } + } } diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java index 0fcceb23e2..9befe3c0f9 100644 --- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java +++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java @@ -25,7 +25,6 @@ import java.util.concurrent.atomic.AtomicInteger; import net.i2p.client.I2PClient; import net.i2p.crypto.SessionKeyManager; -import net.i2p.crypto.TransientSessionKeyManager; import net.i2p.data.Destination; import net.i2p.data.Hash; import net.i2p.data.LeaseSet; @@ -43,6 +42,7 @@ import net.i2p.data.i2cp.SessionId; import net.i2p.router.Job; import net.i2p.router.JobImpl; import net.i2p.router.RouterContext; +import net.i2p.router.crypto.TransientSessionKeyManager; import net.i2p.util.ConcurrentHashSet; import net.i2p.util.I2PThread; import net.i2p.util.Log; diff --git a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java b/router/java/src/net/i2p/router/crypto/TransientSessionKeyManager.java similarity index 99% rename from core/java/src/net/i2p/crypto/TransientSessionKeyManager.java rename to router/java/src/net/i2p/router/crypto/TransientSessionKeyManager.java index 7134bcb417..14c5c0510a 100644 --- a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java +++ b/router/java/src/net/i2p/router/crypto/TransientSessionKeyManager.java @@ -1,4 +1,4 @@ -package net.i2p.crypto; +package net.i2p.router.crypto; /* * free (adj.): unencumbered; not under the control of others @@ -25,6 +25,8 @@ import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; import net.i2p.I2PAppContext; +import net.i2p.crypto.SessionKeyManager; +import net.i2p.crypto.TagSetHandle; import net.i2p.data.DataHelper; import net.i2p.data.PublicKey; import net.i2p.data.SessionKey; diff --git a/router/java/src/net/i2p/router/crypto/package.html b/router/java/src/net/i2p/router/crypto/package.html new file mode 100644 index 0000000000..a1e75c6717 --- /dev/null +++ b/router/java/src/net/i2p/router/crypto/package.html @@ -0,0 +1,7 @@ +<html> +<body> +<p> +Classes formerly in net.i2p.crypto but moved here as they are only used by the router. +</p> +</body> +</html> From 328d7d00080ba06421a4398108764129b5e5e3f4 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Tue, 22 Jul 2014 14:52:08 +0000 Subject: [PATCH 09/40] SAM: - Don't spawn a thread for each transmitted datagram - Set protocol field for raw and signed datagrams - Enforce a 60s timeout for HELLO - Use naming service cache to reduce Destination object churn - Get Log object from the log manager - Log spelling fixes --- apps/sam/java/src/net/i2p/sam/SAMBridge.java | 1 + .../src/net/i2p/sam/SAMDatagramSession.java | 5 ++- apps/sam/java/src/net/i2p/sam/SAMHandler.java | 3 +- .../src/net/i2p/sam/SAMHandlerFactory.java | 17 ++++--- .../src/net/i2p/sam/SAMMessageSession.java | 19 ++++---- .../java/src/net/i2p/sam/SAMRawSession.java | 5 ++- .../src/net/i2p/sam/SAMStreamSession.java | 5 ++- apps/sam/java/src/net/i2p/sam/SAMUtils.java | 44 ++++++++----------- .../java/src/net/i2p/sam/SAMv1Handler.java | 4 +- .../java/src/net/i2p/sam/SAMv3Handler.java | 17 ++++++- 10 files changed, 72 insertions(+), 48 deletions(-) diff --git a/apps/sam/java/src/net/i2p/sam/SAMBridge.java b/apps/sam/java/src/net/i2p/sam/SAMBridge.java index 1894c97198..4679f68b68 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMBridge.java +++ b/apps/sam/java/src/net/i2p/sam/SAMBridge.java @@ -161,6 +161,7 @@ public class SAMBridge implements Runnable, ClientApp { * * @param name name of the destination * @return null if the name does not exist, or if it is improperly formatted + * @deprecated unused */ public Destination getDestination(String name) { synchronized (nameToPrivKeys) { diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java index b9367e24db..32611065da 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; +import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.client.datagram.I2PDatagramDissector; import net.i2p.client.datagram.I2PDatagramMaker; @@ -88,7 +89,9 @@ class SAMDatagramSession extends SAMMessageSession { synchronized (dgramMaker) { dgram = dgramMaker.makeI2PDatagram(data); } - return sendBytesThroughMessageSession(dest, dgram); + // TODO pass ports through + return sendBytesThroughMessageSession(dest, dgram, I2PSession.PROTO_DATAGRAM, + I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); } protected void messageReceived(byte[] msg) { diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandler.java b/apps/sam/java/src/net/i2p/sam/SAMHandler.java index be4d99dab3..30213ca6d7 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMHandler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMHandler.java @@ -13,6 +13,7 @@ import java.nio.channels.SocketChannel; import java.nio.ByteBuffer; import java.util.Properties; +import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; @@ -54,7 +55,7 @@ abstract class SAMHandler implements Runnable { */ protected SAMHandler(SocketChannel s, int verMajor, int verMinor, Properties i2cpProps) throws IOException { - _log = new Log(getClass()); + _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); socket = s; this.verMajor = verMajor; diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java index 4da5792387..d605d57f90 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java +++ b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java @@ -9,12 +9,13 @@ package net.i2p.sam; */ import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.net.Socket; +import java.net.SocketTimeoutException; import java.nio.channels.SocketChannel; -import java.nio.ByteBuffer; import java.util.Properties; import java.util.StringTokenizer; +import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; import net.i2p.util.Log; import net.i2p.util.VersionComparator; @@ -26,6 +27,8 @@ class SAMHandlerFactory { private static final String VERSION = "3.1"; + private static final int HELLO_TIMEOUT = 60*1000; + /** * Return the right SAM handler depending on the protocol version * required by the client. @@ -36,17 +39,21 @@ class SAMHandlerFactory { * @return A SAM protocol handler, or null if the client closed before the handshake */ public static SAMHandler createSAMHandler(SocketChannel s, Properties i2cpProps) throws SAMException { - String line; StringTokenizer tok; - Log log = new Log(SAMHandlerFactory.class); + Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMHandlerFactory.class); try { - line = DataHelper.readLine(s.socket().getInputStream()); + Socket sock = s.socket(); + sock.setSoTimeout(HELLO_TIMEOUT); + String line = DataHelper.readLine(sock.getInputStream()); + sock.setSoTimeout(0); if (line == null) { log.debug("Connection closed by client"); return null; } tok = new StringTokenizer(line.trim(), " "); + } catch (SocketTimeoutException e) { + throw new SAMException("Timeout waiting for HELLO VERSION", e); } catch (IOException e) { throw new SAMException("Error reading from socket", e); } catch (Exception e) { diff --git a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java index 452bbe0fb9..e15c6668d2 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; +import net.i2p.I2PAppContext; import net.i2p.client.I2PClient; import net.i2p.client.I2PClientFactory; import net.i2p.client.I2PSession; @@ -33,10 +34,8 @@ import net.i2p.util.Log; abstract class SAMMessageSession { protected final Log _log; - - private I2PSession session = null; - - private SAMMessageSessionHandler handler = null; + private I2PSession session; + private SAMMessageSessionHandler handler; /** * Initialize a new SAM message-based session. @@ -48,7 +47,7 @@ abstract class SAMMessageSession { * @throws I2PSessionException */ protected SAMMessageSession(String dest, Properties props) throws IOException, DataFormatException, I2PSessionException { - _log = new Log(getClass()); + _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(dest)); initSAMMessageSession(bais, props); } @@ -103,11 +102,15 @@ abstract class SAMMessageSession { * * @param dest Destination * @param data Bytes to be sent + * @param proto I2CP protocol + * @param fromPort I2CP from port + * @param toPort I2CP to port * * @return True if the data was sent, false otherwise - * @throws DataFormatException + * @throws DataFormatException on unknown / bad dest */ - protected boolean sendBytesThroughMessageSession(String dest, byte[] data) throws DataFormatException { + protected boolean sendBytesThroughMessageSession(String dest, byte[] data, + int proto, int fromPort, int toPort) throws DataFormatException { Destination d = SAMUtils.getDest(dest); if (_log.shouldLog(Log.DEBUG)) { @@ -115,7 +118,7 @@ abstract class SAMMessageSession { } try { - return session.sendMessage(d, data); + return session.sendMessage(d, data, proto, fromPort, toPort); } catch (I2PSessionException e) { _log.error("I2PSessionException while sending data", e); return false; diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java index 08e98c2589..01cbde75a7 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; +import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.data.DataFormatException; import net.i2p.util.Log; @@ -73,7 +74,9 @@ class SAMRawSession extends SAMMessageSession { public boolean sendBytes(String dest, byte[] data) throws DataFormatException { if (data.length > RAW_SIZE_MAX) throw new DataFormatException("Data size limit exceeded (" + data.length + ")"); - return sendBytesThroughMessageSession(dest, data); + // TODO pass ports through + return sendBytesThroughMessageSession(dest, data, I2PSession.PROTO_DATAGRAM_RAW, + I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); } protected void messageReceived(byte[] msg) { diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java index db5d39d49a..6235d92a4c 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java @@ -25,6 +25,7 @@ import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import net.i2p.I2PAppContext; import net.i2p.I2PException; import net.i2p.client.I2PClient; import net.i2p.client.streaming.I2PServerSocket; @@ -107,9 +108,9 @@ class SAMStreamSession { public SAMStreamSession(InputStream destStream, String dir, Properties props, SAMStreamReceiver recv) throws IOException, DataFormatException, SAMException { this.recv = recv; - _log = new Log(getClass()); + _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass()); if (_log.shouldLog(Log.DEBUG)) - _log.debug("SAM STREAM session instantiated"); + _log.debug("SAM STREAM session instantiated"); Properties allprops = (Properties) System.getProperties().clone(); allprops.putAll(props); diff --git a/apps/sam/java/src/net/i2p/sam/SAMUtils.java b/apps/sam/java/src/net/i2p/sam/SAMUtils.java index 15ecb1143f..7adaadf7b5 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMUtils.java +++ b/apps/sam/java/src/net/i2p/sam/SAMUtils.java @@ -123,26 +123,12 @@ class SAMUtils { * Resolved the specified hostname. * * @param name Hostname to be resolved - * @param pubKey A stream to write the Destination public key (may be null) * * @return the Destination for the specified hostname, or null if not found */ - public static Destination lookupHost(String name, OutputStream pubKey) { + private static Destination lookupHost(String name) { NamingService ns = I2PAppContext.getGlobalContext().namingService(); Destination dest = ns.lookup(name); - - if ((pubKey != null) && (dest != null)) { - try { - dest.writeBytes(pubKey); - } catch (IOException e) { - e.printStackTrace(); - return null; - } catch (DataFormatException e) { - e.printStackTrace(); - return null; - } - } - return dest; } @@ -151,20 +137,26 @@ class SAMUtils { * * @param s Hostname or key to be resolved * - * @return the Destination for the specified hostname, or null if not found + * @return the Destination for the specified hostname, non-null + * @throws DataFormatException on bad Base 64 or name not found */ public static Destination getDest(String s) throws DataFormatException { - Destination d = new Destination() ; - try { - d.fromBase64(s); - } catch (DataFormatException e) { - d = lookupHost(s, null); - if ( d==null ) { - throw e ; - } - } - return d ; + // NamingService caches b64 so just use it for everything + // TODO: Add a static local cache here so SAM doesn't flush the + // NamingService cache + Destination d = lookupHost(s); + if (d == null) { + String msg; + if (s.length() >= 516) + msg = "Bad Base64 dest: "; + else if (s.length() == 60 && s.endsWith(".b32.i2p")) + msg = "Lease set not found: "; + else + msg = "Host name not found: "; + throw new DataFormatException(msg + s); + } + return d; } /** diff --git a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java index 2ffba654f5..47a2c29e55 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java @@ -246,7 +246,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece destKeystream = bridge.getKeystream(dest); if (destKeystream == null) { if (_log.shouldLog(Log.DEBUG)) - _log.debug("Custom destination specified [" + dest + "] but it isnt know, creating a new one"); + _log.debug("Custom destination specified [" + dest + "] but it isn't known, creating a new one"); ByteArrayOutputStream baos = new ByteArrayOutputStream(640); SAMUtils.genRandomKey(baos, null); destKeystream = Base64.encode(baos.toByteArray()); @@ -284,7 +284,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece if (!dir.equals("CREATE") && !dir.equals("RECEIVE") && !dir.equals("BOTH")) { if (_log.shouldLog(Log.DEBUG)) - _log.debug("Unknow DIRECTION parameter value: [" + dir + "]"); + _log.debug("Unknown DIRECTION parameter value: [" + dir + "]"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unknown DIRECTION parameter\"\n"); } props.remove("DIRECTION"); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java index 043baba68d..062e5f9fb4 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java @@ -25,6 +25,7 @@ import java.util.Properties; import java.util.HashMap; import java.util.StringTokenizer; +import net.i2p.I2PAppContext; import net.i2p.I2PException; import net.i2p.client.I2PClient; import net.i2p.client.I2PSessionException; @@ -159,7 +160,13 @@ class SAMv3Handler extends SAMv1Handler ByteBuffer outBuf = ByteBuffer.wrap(new byte[inBuf.remaining()]); outBuf.put(inBuf); outBuf.flip(); - new I2PAppThread(new MessageDispatcher(outBuf.array()), "MessageDispatcher").start(); + // A new thread for every message is wildly inefficient... + //new I2PAppThread(new MessageDispatcher(outBuf.array()), "MessageDispatcher").start(); + // inline + // Even though we could be sending messages through multiple sessions, + // that isn't a common use case, and blocking should be rare. + // Inside router context, I2CP drops on overflow. + (new MessageDispatcher(outBuf.array())).run(); } } } @@ -194,9 +201,15 @@ class SAMv3Handler extends SAMv1Handler SessionRecord rec = sSessionsHash.get(nick); if (rec!=null) { rec.getHandler().session.sendBytes(dest,data); + } else { + Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3Handler.class); + if (log.shouldLog(Log.WARN)) + log.warn("Dropping datagram, no session for " + nick); } } catch (Exception e) { - // FIXME log? throw? + Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3Handler.class); + if (log.shouldLog(Log.WARN)) + log.warn("Error handling datagram", e); } } } From 89764c12e767fecd66dd1c55a266b62c6c66212c Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 23 Jul 2014 13:12:32 +0000 Subject: [PATCH 10/40] bob finals, synch --- apps/BOB/src/net/i2p/BOB/BOB.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/BOB/src/net/i2p/BOB/BOB.java b/apps/BOB/src/net/i2p/BOB/BOB.java index 8277fd2592..6dbbe3712c 100644 --- a/apps/BOB/src/net/i2p/BOB/BOB.java +++ b/apps/BOB/src/net/i2p/BOB/BOB.java @@ -119,15 +119,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 +144,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 +191,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(); From 086381d958a4c431739de5ff96c154375fa3270f Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 6 Aug 2014 16:32:10 +0000 Subject: [PATCH 11/40] SU3File: Add support for XML and NEWS types --- core/java/src/net/i2p/crypto/SU3File.java | 79 +++++++++++++++++------ 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/core/java/src/net/i2p/crypto/SU3File.java b/core/java/src/net/i2p/crypto/SU3File.java index 1794b0ac47..a6fb62e5e8 100644 --- a/core/java/src/net/i2p/crypto/SU3File.java +++ b/core/java/src/net/i2p/crypto/SU3File.java @@ -49,6 +49,7 @@ public class SU3File { private int _versionLength; private String _signer; private int _signerLength; + private int _fileType = -1; private ContentType _contentType; private long _contentLength; private PublicKey _signerPubkey; @@ -60,18 +61,21 @@ public class SU3File { private static final int MIN_VERSION_BYTES = 16; private static final int VERSION_OFFSET = 40; // Signature.SIGNATURE_BYTES; avoid early ctx init - private static final int TYPE_ZIP = 0; + public static final int TYPE_ZIP = 0; + public static final int TYPE_XML = 1; public static final int CONTENT_UNKNOWN = 0; public static final int CONTENT_ROUTER = 1; public static final int CONTENT_PLUGIN = 2; public static final int CONTENT_RESEED = 3; + public static final int CONTENT_NEWS = 4; private enum ContentType { UNKNOWN(CONTENT_UNKNOWN, "unknown"), ROUTER(CONTENT_ROUTER, "router"), PLUGIN(CONTENT_PLUGIN, "plugin"), - RESEED(CONTENT_RESEED, "reseed") + RESEED(CONTENT_RESEED, "reseed"), + NEWS(CONTENT_NEWS, "news") ; private final int code; @@ -153,6 +157,15 @@ public class SU3File { return _contentType != null ? _contentType.getCode() : -1; } + /** + * @return -1 if unknown + * @since 0.9.15 + */ + public int getFileType() throws IOException { + verifyHeader(); + return _fileType; + } + /** * Throws IOE if verify vails. */ @@ -204,9 +217,9 @@ public class SU3File { if (_contentLength <= 0) throw new IOException("bad content length"); skip(in, 1); - foo = in.read(); - if (foo != TYPE_ZIP) - throw new IOException("bad type"); + _fileType = in.read(); + if (_fileType != TYPE_ZIP && _fileType != TYPE_XML) + throw new IOException("bad file type"); skip(in, 1); int cType = in.read(); _contentType = BY_CODE.get(Integer.valueOf(cType)); @@ -352,11 +365,12 @@ public class SU3File { * Throws on all errors. * * @param content the input file, probably in zip format - * @param contentType 0-255, 0 for zip + * @param fileType 0-255, 0 for zip + * @param contentType 0-255 * @param version 1-255 bytes when converted to UTF-8 * @param signer ID of the public key, 1-255 bytes when converted to UTF-8 */ - public void write(File content, int contentType, String version, + public void write(File content, int fileType, int contentType, String version, String signer, PrivateKey privkey, SigType sigType) throws IOException { InputStream in = null; DigestOutputStream out = null; @@ -386,7 +400,9 @@ public class SU3File { throw new IllegalArgumentException("No content"); DataHelper.writeLong(out, 8, contentLength); out.write((byte) 0); - out.write((byte) TYPE_ZIP); + if (fileType < 0 || fileType > 255) + throw new IllegalArgumentException("bad content type"); + out.write((byte) fileType); out.write((byte) 0); if (contentType < 0 || contentType > 255) throw new IllegalArgumentException("bad content type"); @@ -443,8 +459,9 @@ public class SU3File { // defaults String stype = null; String ctype = null; + String ftype = null; boolean error = false; - Getopt g = new Getopt("SU3File", args, "t:c:"); + Getopt g = new Getopt("SU3File", args, "t:c:f:"); int c; while ((c = g.getopt()) != -1) { switch (c) { @@ -456,6 +473,10 @@ public class SU3File { ctype = g.getOptarg(); break; + case 'f': + ftype = g.getOptarg(); + break; + case '?': case ':': default: @@ -476,7 +497,7 @@ public class SU3File { Properties props = new Properties(); props.setProperty("prng.bufferSize", "16384"); new I2PAppContext(props); - ok = signCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4), ""); + ok = signCLI(stype, ctype, ftype, a.get(0), a.get(1), a.get(2), a.get(3), a.get(4), ""); } else if ("bulksign".equals(cmd)) { Properties props = new Properties(); props.setProperty("prng.bufferSize", "16384"); @@ -502,11 +523,11 @@ public class SU3File { private static final void showUsageCLI() { System.err.println("Usage: SU3File keygen [-t type|code] publicKeyFile keystore.ks you@mail.i2p"); - System.err.println(" SU3File sign [-c type|code] [-t type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p"); - System.err.println(" SU3File bulksign [-c type|code] [-t type|code] directory keystore.ks version you@mail.i2p"); + System.err.println(" SU3File sign [-t type|code] [-c type|code] [-f type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p"); + System.err.println(" SU3File bulksign [-t type|code] [-c type|code] directory keystore.ks version you@mail.i2p"); System.err.println(" SU3File showversion signedFile.su3"); System.err.println(" SU3File verifysig signedFile.su3"); - System.err.println(" SU3File extract signedFile.su3 outFile.zip"); + System.err.println(" SU3File extract signedFile.su3 outFile"); System.err.println(dumpTypes()); } @@ -529,6 +550,9 @@ public class SU3File { buf.append(" DEFAULT"); buf.append('\n'); } + buf.append("Available file types (-f):\n"); + buf.append(" ZIP\t(code: 0) DEFAULT\n"); + buf.append(" XML\t(code: 1)\n"); return buf.toString(); } @@ -574,6 +598,7 @@ public class SU3File { } /** + * Zip only * @return success * @since 0.9.9 */ @@ -608,7 +633,7 @@ public class SU3File { if (!inputFile.endsWith(".zip")) continue; String signedFile = inputFile.substring(0, inputFile.length() - 4) + ".su3"; - boolean rv = signCLI(stype, ctype, inputFile, signedFile, privateKeyFile, version, signerName, keypw); + boolean rv = signCLI(stype, ctype, null, inputFile, signedFile, privateKeyFile, version, signerName, keypw); if (!rv) return false; success++; @@ -622,7 +647,7 @@ public class SU3File { * @return success * @since 0.9.9 */ - private static final boolean signCLI(String stype, String ctype, String inputFile, String signedFile, + private static final boolean signCLI(String stype, String ctype, String ftype, String inputFile, String signedFile, String privateKeyFile, String version, String signerName, String keypw) { SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : SigType.parseSigType(stype); if (type == null) { @@ -634,14 +659,32 @@ public class SU3File { System.out.println("Content type " + ctype + " is not supported"); return false; } - return signCLI(type, ct, inputFile, signedFile, privateKeyFile, version, signerName, keypw); + int ft = TYPE_ZIP; + if (ftype != null) { + if (ftype.equalsIgnoreCase("ZIP")) { + ft = TYPE_ZIP; + } else if (ftype.equalsIgnoreCase("XML")) { + ft = TYPE_XML; + } else { + try { + ft = Integer.parseInt(ftype); + } catch (NumberFormatException nfe) { + ft = -1; + } + if (ft != TYPE_ZIP && ft != TYPE_XML) { + System.out.println("File type " + ftype + " is not supported"); + return false; + } + } + } + return signCLI(type, ct, ft, inputFile, signedFile, privateKeyFile, version, signerName, keypw); } /** * @return success * @since 0.9.9 */ - private static final boolean signCLI(SigType type, ContentType ctype, String inputFile, String signedFile, + private static final boolean signCLI(SigType type, ContentType ctype, int ftype, String inputFile, String signedFile, String privateKeyFile, String version, String signerName, String keypw) { try { while (keypw.length() < 6) { @@ -657,7 +700,7 @@ public class SU3File { return false; } SU3File file = new SU3File(signedFile); - file.write(new File(inputFile), ctype.getCode(), version, signerName, pk, type); + file.write(new File(inputFile), ftype, ctype.getCode(), version, signerName, pk, type); System.out.println("Input file '" + inputFile + "' signed and written to '" + signedFile + "'"); return true; } catch (GeneralSecurityException gse) { From d1a2e24f0e053215d56a379223a2cb5ae5defa20 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 6 Aug 2014 16:35:08 +0000 Subject: [PATCH 12/40] SSU: Speed up introductions by responding to HolePunch (ticket #1333) --- .../transport/udp/EstablishmentManager.java | 26 +++++++++++++++++++ .../transport/udp/OutboundEstablishState.java | 22 +++++++++++++++- .../i2p/router/transport/udp/UDPReceiver.java | 11 +++++--- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java index 41b0eeddd6..267c4fc2a5 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -967,6 +967,32 @@ class EstablishmentManager { notifyActivity(); } + /** + * Called from UDPReceiver. + * Accelerate response to RelayResponse if we haven't sent it yet. + * + * @since 0.9.15 + */ + void receiveHolePunch(InetAddress from, int fromPort) { + RemoteHostId id = new RemoteHostId(from.getAddress(), fromPort); + OutboundEstablishState state = _outboundStates.get(id); + if (state != null) { + boolean sendNow = state.receiveHolePunch(); + if (sendNow) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Hole punch from " + state + ", sending SessionRequest now"); + notifyActivity(); + } else { + if (_log.shouldLog(Log.WARN)) + _log.warn("Hole punch from " + state + ", already sent SessionRequest"); + } + } else { + // HolePunch received before RelayResponse, and we didn't know the IP/port, or it changed + if (_log.shouldLog(Log.WARN)) + _log.warn("No state found for hole punch from " + from + " port " + fromPort); + } + } + /** * Are IP and port valid? This is only for checking the relay response. * Reject all IPv6, for now, even if we are configured for it. diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java index 39adc9b24b..ba4375dbdb 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java @@ -99,6 +99,8 @@ class OutboundEstablishState { /** max delay including backoff */ private static final long MAX_DELAY = 15*1000; + private static final long WAIT_FOR_HOLE_PUNCH_DELAY = 500; + /** * @param claimedAddress an IP/port based RemoteHostId, or null if unknown * @param remoteHostId non-null, == claimedAddress if direct, or a hash-based one if indirect @@ -556,7 +558,7 @@ class OutboundEstablishState { public synchronized void introduced(byte bobIP[], int bobPort) { if (_currentState != OutboundState.OB_STATE_PENDING_INTRO) return; // we've already successfully been introduced, so don't overwrite old settings - _nextSend = _context.clock().now() + 500; // wait briefly for the hole punching + _nextSend = _context.clock().now() + WAIT_FOR_HOLE_PUNCH_DELAY; // wait briefly for the hole punching _currentState = OutboundState.OB_STATE_INTRODUCED; if (_claimedAddress != null && bobPort == _bobPort && DataHelper.eq(bobIP, _bobIP)) { // he's who he said he was @@ -570,6 +572,24 @@ class OutboundEstablishState { if (_log.shouldLog(Log.INFO)) _log.info("Introduced to " + _remoteHostId + ", now lets get on with establishing"); } + + /** + * Accelerate response to RelayResponse if we haven't sent it yet. + * + * @return true if we should send the SessionRequest now + * @since 0.9.15 + */ + synchronized boolean receiveHolePunch() { + if (_currentState != OutboundState.OB_STATE_INTRODUCED) + return false; + if (_requestSentCount > 0) + return false; + long now = _context.clock().now(); + if (_log.shouldLog(Log.WARN)) + _log.warn(toString() + " accelerating SessionRequest by " + (_nextSend - now) + " ms"); + _nextSend = now; + return true; + } /** how long have we been trying to establish this session? */ public long getLifetime() { return _context.clock().now() - _establishBegin; } diff --git a/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java b/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java index be5b97dcf8..65a7a81cbf 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java @@ -1,6 +1,7 @@ package net.i2p.router.transport.udp; import java.io.IOException; +import java.net.DatagramPacket; import java.net.DatagramSocket; import java.util.Arrays; @@ -220,11 +221,12 @@ class UDPReceiver { // _socketChanged = false; //} UDPPacket packet = UDPPacket.acquire(_context, true); + DatagramPacket dpacket = packet.getPacket(); // Android ICS bug // http://code.google.com/p/android/issues/detail?id=24748 if (_isAndroid) - packet.getPacket().setLength(UDPPacket.MAX_PACKET_SIZE); + dpacket.setLength(UDPPacket.MAX_PACKET_SIZE); // block before we read... //if (_log.shouldLog(Log.DEBUG)) @@ -236,9 +238,9 @@ class UDPReceiver { //if (_log.shouldLog(Log.INFO)) // _log.info("Before blocking socket.receive on " + System.identityHashCode(packet)); //synchronized (Runner.this) { - _socket.receive(packet.getPacket()); + _socket.receive(dpacket); //} - int size = packet.getPacket().getLength(); + int size = dpacket.getLength(); if (_log.shouldLog(Log.INFO)) _log.info("After blocking socket.receive: packet is " + size + " bytes on " + System.identityHashCode(packet)); packet.resetBegin(); @@ -266,7 +268,8 @@ class UDPReceiver { _context.statManager().addRateData("udp.receiveHolePunch", 1); // nat hole punch packets are 0 bytes if (_log.shouldLog(Log.INFO)) - _log.info("Received a 0 byte udp packet from " + packet.getPacket().getAddress() + ":" + packet.getPacket().getPort()); + _log.info("Received a 0 byte udp packet from " + dpacket.getAddress() + ":" + dpacket.getPort()); + _transport.getEstablisher().receiveHolePunch(dpacket.getAddress(), dpacket.getPort()); packet.release(); } } catch (IOException ioe) { From 9655e79d26c934292b116e27db126850e82de3b2 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 6 Aug 2014 18:13:54 +0000 Subject: [PATCH 13/40] UPnP: Disable external entities in XML parser --- .../cybergarage/xml/parser/JaxpParser.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/router/java/src/org/cybergarage/xml/parser/JaxpParser.java b/router/java/src/org/cybergarage/xml/parser/JaxpParser.java index 139f59f487..1d6e97f6a8 100644 --- a/router/java/src/org/cybergarage/xml/parser/JaxpParser.java +++ b/router/java/src/org/cybergarage/xml/parser/JaxpParser.java @@ -21,18 +21,21 @@ package org.cybergarage.xml.parser; +import java.io.ByteArrayInputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import org.cybergarage.xml.Node; import org.cybergarage.xml.Parser; import org.cybergarage.xml.ParserException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; +import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; @@ -116,8 +119,25 @@ public class JaxpParser extends Parser org.cybergarage.xml.Node root = null; try { + // https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setValidating(false); + factory.setNamespaceAware(true); + factory.setExpandEntityReferences(false); + try { + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + } catch (ParserConfigurationException pce) {} + try { + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + } catch (ParserConfigurationException pce) {} + try { + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } catch (ParserConfigurationException pce) {} + try { + factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + } catch (ParserConfigurationException pce) {} DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setEntityResolver(new BlankingResolver()); InputSource inSrc = new InputSource(new NullFilterInputStream(inStream)); Document doc = builder.parse(inSrc); @@ -163,4 +183,16 @@ public class JaxpParser extends Parser return rv; } } + + /** + * I2P - + * http://stackoverflow.com/questions/5883542/disable-xml-validation-based-on-external-dtd-xsd + */ + private static class BlankingResolver implements EntityResolver { + private static final byte[] DUMMY = new byte[0]; + + public InputSource resolveEntity(String arg0, String arg1) { + return new InputSource(new ByteArrayInputStream(DUMMY)); + } + } } From 2878a6487e20094eba0e2ec362c818f9e4e85a6b Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 7 Aug 2014 17:05:25 +0000 Subject: [PATCH 14/40] KeysAndCert: Change hashcode to prevent possible collisions caused by apps with zeroed pubkey --- core/java/src/net/i2p/data/KeysAndCert.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/java/src/net/i2p/data/KeysAndCert.java b/core/java/src/net/i2p/data/KeysAndCert.java index 6936c0f3e4..b0a8a845b7 100644 --- a/core/java/src/net/i2p/data/KeysAndCert.java +++ b/core/java/src/net/i2p/data/KeysAndCert.java @@ -130,17 +130,19 @@ public class KeysAndCert extends DataStructureImpl { && DataHelper.eq(_certificate, ident._certificate); } - /** the public key has enough randomness in it to use it by itself for speed */ + /** the signing key has enough randomness in it to use it by itself for speed */ @Override public int hashCode() { - if (_publicKey == null) + // don't use public key, some app devs thinking of using + // an all-zeros or leading-zeros public key for destinations + if (_signingKey == null) return 0; - return _publicKey.hashCode(); + return _signingKey.hashCode(); } @Override public String toString() { - StringBuilder buf = new StringBuilder(64); + StringBuilder buf = new StringBuilder(256); buf.append('[').append(getClass().getSimpleName()).append(": "); buf.append("\n\tHash: ").append(getHash().toBase64()); buf.append("\n\tCertificate: ").append(_certificate); From 79fe799aeb2b172edad2f1bcfd1b2ad4b6ebe18b Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 7 Aug 2014 18:45:04 +0000 Subject: [PATCH 15/40] Plugins: Stub out SU3 support --- .../i2p/router/update/PluginUpdateRunner.java | 53 ++++++++++++++++++- core/java/src/net/i2p/crypto/SU3File.java | 13 ++--- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java index d532a9c5c6..65df785db2 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java @@ -1,6 +1,7 @@ package net.i2p.router.update; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.lang.IllegalArgumentException; import java.net.URI; @@ -9,6 +10,7 @@ import java.util.Map; import java.util.Properties; import net.i2p.CoreVersion; +import net.i2p.crypto.SU3File; import net.i2p.crypto.TrustedUpdate; import net.i2p.data.DataHelper; import net.i2p.router.RouterContext; @@ -118,7 +120,6 @@ class PluginUpdateRunner extends UpdateRunner { @Override public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) { - boolean update = false; updateStatus("<b>" + _("Plugin downloaded") + "</b>"); File f = new File(_updateFile); File appDir = new SecureDirectory(_context.getConfigDir(), PLUGIN_DIR); @@ -127,7 +128,43 @@ class PluginUpdateRunner extends UpdateRunner { statusDone("<b>" + _("Cannot create plugin directory {0}", appDir.getAbsolutePath()) + "</b>"); return; } + boolean isSU3; + try { + isSU3 = isSU3File(f); + } catch (IOException ioe) { + f.delete(); + statusDone("<b>" + ioe + "</b>"); + return; + } + if (isSU3) + processSU3(f, appDir, url); + else + processSUD(f, appDir, url); + } + /** + * @since 0.9.15 + * @return if SU3 + */ + private static boolean isSU3File(File f) throws IOException { + FileInputStream fis = null; + try { + fis = new FileInputStream(f); + for (int i = 0; i < SU3File.MAGIC.length(); i++) { + if (fis.read() != SU3File.MAGIC.charAt(i)) + return false; + } + return true; + } finally { + if (fis != null) try { fis.close(); } catch (IOException ioe) {} + } + } + + /** + * @since 0.9.15 + * @return success + */ + private void processSUD(File f, File appDir, String url) { TrustedUpdate up = new TrustedUpdate(_context); File to = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + ZIP); // extract to a zip file whether the sig is good or not, so we can get the properties file @@ -222,7 +259,21 @@ class PluginUpdateRunner extends UpdateRunner { String sudVersion = TrustedUpdate.getVersionString(f); f.delete(); + processFinal(to, appDir, tempDir, url, props, sudVersion, pubkey, signer); + } + /** + * @since 0.9.15 + */ + private void processSU3(File f, File appDir, String url) { + // TODO + } + + /** + * @since 0.9.15 + */ + private void processFinal(File to, File appDir, File tempDir, String url, Properties props, String sudVersion, String pubkey, String signer) { + boolean update = false; String appName = props.getProperty("name"); String version = props.getProperty("version"); if (appName == null || version == null || appName.length() <= 0 || version.length() <= 0 || diff --git a/core/java/src/net/i2p/crypto/SU3File.java b/core/java/src/net/i2p/crypto/SU3File.java index a6fb62e5e8..30e172d4db 100644 --- a/core/java/src/net/i2p/crypto/SU3File.java +++ b/core/java/src/net/i2p/crypto/SU3File.java @@ -56,7 +56,8 @@ public class SU3File { private boolean _headerVerified; private SigType _sigType; - private static final byte[] MAGIC = DataHelper.getUTF8("I2Psu3"); + public static final String MAGIC = "I2Psu3"; + private static final byte[] MAGIC_BYTES = DataHelper.getASCII(MAGIC); private static final int FILE_VERSION = 0; private static final int MIN_VERSION_BYTES = 16; private static final int VERSION_OFFSET = 40; // Signature.SIGNATURE_BYTES; avoid early ctx init @@ -189,9 +190,9 @@ public class SU3File { * Throws if verify vails. */ private void verifyHeader(InputStream in) throws IOException, DataFormatException { - byte[] magic = new byte[MAGIC.length]; + byte[] magic = new byte[MAGIC_BYTES.length]; DataHelper.read(in, magic); - if (!DataHelper.eq(magic, MAGIC)) + if (!DataHelper.eq(magic, MAGIC_BYTES)) throw new IOException("Not an su3 file"); skip(in, 1); int foo = in.read(); @@ -300,9 +301,9 @@ public class SU3File { // read 10 bytes to get the sig type in.mark(10); // following is a dup of that in verifyHeader() - byte[] magic = new byte[MAGIC.length]; + byte[] magic = new byte[MAGIC_BYTES.length]; DataHelper.read(in, magic); - if (!DataHelper.eq(magic, MAGIC)) + if (!DataHelper.eq(magic, MAGIC_BYTES)) throw new IOException("Not an su3 file"); skip(in, 1); int foo = in.read(); @@ -379,7 +380,7 @@ public class SU3File { in = new BufferedInputStream(new FileInputStream(content)); MessageDigest md = sigType.getDigestInstance(); out = new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(_file)), md); - out.write(MAGIC); + out.write(MAGIC_BYTES); out.write((byte) 0); out.write((byte) FILE_VERSION); DataHelper.writeLong(out, 2, sigType.getCode()); From 35bb8c5348ead682534072278bd8ce7540bf459c Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 7 Aug 2014 19:06:41 +0000 Subject: [PATCH 16/40] Plugins: partial SU3 support --- .../i2p/router/update/PluginUpdateRunner.java | 94 ++++++++++++++----- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java index 65df785db2..0025436a54 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java @@ -175,27 +175,9 @@ class PluginUpdateRunner extends UpdateRunner { to.delete(); return; } - File tempDir = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + "-unzip"); - if (!FileUtil.extractZip(to, tempDir, Log.ERROR)) { - f.delete(); - to.delete(); - FileUtil.rmdir(tempDir, false); - statusDone("<b>" + _("Plugin from {0} is corrupt", url) + "</b>"); + Properties props = getPluginConfig(f, to, url); + if (props == null) return; - } - File installProps = new File(tempDir, "plugin.config"); - Properties props = new OrderedProperties(); - try { - DataHelper.loadProps(props, installProps); - } catch (IOException ioe) { - f.delete(); - to.delete(); - FileUtil.rmdir(tempDir, false); - statusDone("<b>" + _("Plugin from {0} does not contain the required configuration file", url) + "</b>"); - return; - } - // we don't need this anymore, we will unzip again - FileUtil.rmdir(tempDir, false); // ok, now we check sigs and deal with a bad sig String pubkey = props.getProperty("key"); @@ -259,20 +241,85 @@ class PluginUpdateRunner extends UpdateRunner { String sudVersion = TrustedUpdate.getVersionString(f); f.delete(); - processFinal(to, appDir, tempDir, url, props, sudVersion, pubkey, signer); + processFinal(to, appDir, url, props, sudVersion, pubkey, signer); } /** * @since 0.9.15 */ private void processSU3(File f, File appDir, String url) { - // TODO + SU3File su3 = new SU3File(_context, f); + File to = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + ZIP); + String sudVersion; + String signingKeyName; + try { + su3.verifyAndMigrate(to); + sudVersion = su3.getVersionString(); + signingKeyName = su3.getSignerString(); + } catch (IOException ioe) { + statusDone("<b>" + ioe + ' ' + _("from {0}", url) + " </b>"); + f.delete(); + to.delete(); + return; + } + Properties props = getPluginConfig(f, to, url); + if (props == null) + return; + String pubkey = props.getProperty("key"); + String signer = props.getProperty("signer"); + if (pubkey == null || signer == null || pubkey.length() != 172 || signer.length() <= 0) { + f.delete(); + to.delete(); + statusDone("<b>" + _("Plugin from {0} contains an invalid key", url) + "</b>"); + return; + } + if (!signer.equals(signingKeyName)) { + f.delete(); + to.delete(); + if (signingKeyName == null) + _log.error("Failed to verify plugin signature, corrupt plugin or bad signature, signed by: " + signer); + else + // shouldn't happen + _log.error("Plugin signer \"" + signer + "\" does not match new signer in plugin.config file \"" + signingKeyName + "\""); + statusDone("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>"); + return; + } + processFinal(to, appDir, url, props, sudVersion, pubkey, signer); + } + + /** + * @since 0.9.15 + * @return null on error + */ + private Properties getPluginConfig(File f, File to, String url) { + File tempDir = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + "-unzip"); + if (!FileUtil.extractZip(to, tempDir, Log.ERROR)) { + f.delete(); + to.delete(); + FileUtil.rmdir(tempDir, false); + statusDone("<b>" + _("Plugin from {0} is corrupt", url) + "</b>"); + return null; + } + File installProps = new File(tempDir, "plugin.config"); + Properties props = new OrderedProperties(); + try { + DataHelper.loadProps(props, installProps); + } catch (IOException ioe) { + f.delete(); + to.delete(); + statusDone("<b>" + _("Plugin from {0} does not contain the required configuration file", url) + "</b>"); + return null; + } finally { + // we don't need this anymore, we will unzip again + FileUtil.rmdir(tempDir, false); + } + return props; } /** * @since 0.9.15 */ - private void processFinal(File to, File appDir, File tempDir, String url, Properties props, String sudVersion, String pubkey, String signer) { + private void processFinal(File to, File appDir, String url, Properties props, String sudVersion, String pubkey, String signer) { boolean update = false; String appName = props.getProperty("name"); String version = props.getProperty("version"); @@ -324,7 +371,6 @@ class PluginUpdateRunner extends UpdateRunner { DataHelper.loadProps(oldProps, oldPropFile); } catch (IOException ioe) { to.delete(); - FileUtil.rmdir(tempDir, false); statusDone("<b>" + _("Installed plugin does not contain the required configuration file", url) + "</b>"); return; } From 506419964b930792e8b155e286ad9786ba9de6e3 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 7 Aug 2014 19:27:53 +0000 Subject: [PATCH 17/40] Plugins: SU3 support in form, type checking, don't require DSA key in SU3 --- .../net/i2p/router/update/PluginUpdateHandler.java | 4 +++- .../net/i2p/router/update/PluginUpdateRunner.java | 12 ++++++++---- .../src/net/i2p/router/web/ConfigClientsHandler.java | 4 +++- .../src/net/i2p/router/web/ConfigClientsHelper.java | 4 +++- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateHandler.java index 64304bd3bc..f327f739da 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateHandler.java @@ -43,7 +43,9 @@ class PluginUpdateHandler implements Checker, Updater { Properties props = PluginStarter.pluginProperties(_context, appName); String oldVersion = props.getProperty("version"); - String xpi2pURL = props.getProperty("updateURL"); + String xpi2pURL = props.getProperty("updateURL.su3"); + if (xpi2pURL == null) + xpi2pURL = props.getProperty("updateURL"); List<URI> updateSources = null; if (xpi2pURL != null) { try { diff --git a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java index 0025436a54..e42df7877e 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java @@ -254,6 +254,10 @@ class PluginUpdateRunner extends UpdateRunner { String signingKeyName; try { su3.verifyAndMigrate(to); + if (su3.getFileType() != SU3File.TYPE_ZIP) + throw new IOException("bad file type"); + if (su3.getContentType() != SU3File.CONTENT_PLUGIN) + throw new IOException("bad content type"); sudVersion = su3.getVersionString(); signingKeyName = su3.getSignerString(); } catch (IOException ioe) { @@ -265,9 +269,8 @@ class PluginUpdateRunner extends UpdateRunner { Properties props = getPluginConfig(f, to, url); if (props == null) return; - String pubkey = props.getProperty("key"); String signer = props.getProperty("signer"); - if (pubkey == null || signer == null || pubkey.length() != 172 || signer.length() <= 0) { + if (signer == null || signer.length() <= 0) { f.delete(); to.delete(); statusDone("<b>" + _("Plugin from {0} contains an invalid key", url) + "</b>"); @@ -284,7 +287,7 @@ class PluginUpdateRunner extends UpdateRunner { statusDone("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>"); return; } - processFinal(to, appDir, url, props, sudVersion, pubkey, signer); + processFinal(to, appDir, url, props, sudVersion, null, signer); } /** @@ -317,6 +320,7 @@ class PluginUpdateRunner extends UpdateRunner { } /** + * @param pubkey null OK for su3 * @since 0.9.15 */ private void processFinal(File to, File appDir, String url, Properties props, String sudVersion, String pubkey, String signer) { @@ -377,7 +381,7 @@ class PluginUpdateRunner extends UpdateRunner { String oldPubkey = oldProps.getProperty("key"); String oldKeyName = oldProps.getProperty("signer"); String oldAppName = oldProps.getProperty("name"); - if ((!pubkey.equals(oldPubkey)) || (!signer.equals(oldKeyName)) || (!appName.equals(oldAppName))) { + if ((pubkey != null && !pubkey.equals(oldPubkey)) || (!signer.equals(oldKeyName)) || (!appName.equals(oldAppName))) { to.delete(); statusDone("<b>" + _("Signature of downloaded plugin does not match installed plugin") + "</b>"); return; diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java index 1c1c28568d..443b9f093e 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java @@ -344,7 +344,9 @@ public class ConfigClientsHandler extends FormHandler { private void updatePlugin(String app) { Properties props = PluginStarter.pluginProperties(_context, app); - String url = props.getProperty("updateURL"); + String url = props.getProperty("updateURL.su3"); + if (url == null) + url = props.getProperty("updateURL"); if (url == null) { addFormError(_("No update URL specified for {0}",app)); return; diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java index c1463000bc..8d33a365ef 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java @@ -232,7 +232,9 @@ public class ConfigClientsHelper extends HelperBase { desc.append("<tr><td>") .append("<a href=\"").append(s).append("\">").append(_("Website")).append("</a><td> "); } - String updateURL = stripHTML(appProps, "updateURL"); + String updateURL = stripHTML(appProps, "updateURL.su3"); + if (updateURL == null) + updateURL = stripHTML(appProps, "updateURL"); if (updateURL != null) { desc.append("<tr><td>") .append("<a href=\"").append(updateURL).append("\">").append(_("Update link")).append("</a><td> "); From 381f494754d21166b4c0e6ea5af723d180e76ffc Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 7 Aug 2014 20:17:51 +0000 Subject: [PATCH 18/40] SU3File: Fix NPE on EOF reading input --- core/java/src/net/i2p/crypto/SU3File.java | 28 +++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/core/java/src/net/i2p/crypto/SU3File.java b/core/java/src/net/i2p/crypto/SU3File.java index 30e172d4db..455e43d628 100644 --- a/core/java/src/net/i2p/crypto/SU3File.java +++ b/core/java/src/net/i2p/crypto/SU3File.java @@ -619,7 +619,12 @@ public class SU3File { try { while (keypw.length() < 6) { System.out.print("Enter password for key \"" + signerName + "\": "); - keypw = DataHelper.readLine(System.in).trim(); + keypw = DataHelper.readLine(System.in); + if (keypw == null) { + System.out.println("\nEOF reading password"); + return false; + } + keypw = keypw.trim(); if (keypw.length() > 0 && keypw.length() < 6) System.out.println("Key password must be at least 6 characters"); } @@ -690,7 +695,12 @@ public class SU3File { try { while (keypw.length() < 6) { System.out.print("Enter password for key \"" + signerName + "\": "); - keypw = DataHelper.readLine(System.in).trim(); + keypw = DataHelper.readLine(System.in); + if (keypw == null) { + System.out.println("\nEOF reading password"); + return false; + } + keypw = keypw.trim(); if (keypw.length() > 0 && keypw.length() < 6) System.out.println("Key password must be at least 6 characters"); } @@ -784,11 +794,21 @@ public class SU3File { try { while (alias.length() == 0) { System.out.print("Enter key name (example@mail.i2p): "); - alias = DataHelper.readLine(System.in).trim(); + alias = DataHelper.readLine(System.in); + if (alias == null) { + System.out.println("\nEOF reading key name"); + return false; + } + alias = alias.trim(); } while (keypw.length() < 6) { System.out.print("Enter new key password: "); - keypw = DataHelper.readLine(System.in).trim(); + keypw = DataHelper.readLine(System.in); + if (keypw == null) { + System.out.println("\nEOF reading password"); + return false; + } + keypw = keypw.trim(); if (keypw.length() > 0 && keypw.length() < 6) System.out.println("Key password must be at least 6 characters"); } From c9e20c5d23b3e0e88f6f5b41ad13539aedc64f6d Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Thu, 7 Aug 2014 21:22:18 +0000 Subject: [PATCH 19/40] log tweak --- core/java/src/net/i2p/crypto/SU3File.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/src/net/i2p/crypto/SU3File.java b/core/java/src/net/i2p/crypto/SU3File.java index 455e43d628..8b09338a76 100644 --- a/core/java/src/net/i2p/crypto/SU3File.java +++ b/core/java/src/net/i2p/crypto/SU3File.java @@ -255,7 +255,7 @@ public class SU3File { } if (_signerPubkey == null) - throw new IOException("unknown signer: " + _signer); + throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName()); _headerVerified = true; } @@ -325,7 +325,7 @@ public class SU3File { else skip(in, getContentOffset()); if (_signerPubkey == null) - throw new IOException("unknown signer: " + _signer); + throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName()); if (migrateTo != null) // else verify only out = new FileOutputStream(migrateTo); byte[] buf = new byte[16*1024]; From b1d60122a3e1b16227599668362c5f2ce4455522 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Fri, 8 Aug 2014 16:40:48 +0000 Subject: [PATCH 20/40] better msg to client on unsupported sigtype --- .../router/client/ClientMessageEventListener.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index 6dd0d833bb..cdcc0008cf 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -11,6 +11,7 @@ package net.i2p.router.client; import java.util.Properties; import net.i2p.CoreVersion; +import net.i2p.crypto.SigType; import net.i2p.data.Hash; import net.i2p.data.Payload; import net.i2p.data.i2cp.BandwidthLimitsMessage; @@ -195,10 +196,16 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi if (_log.shouldLog(Log.DEBUG)) _log.debug("Signature verified correctly on create session message"); } else { - if (_log.shouldLog(Log.ERROR)) - _log.error("Signature verification *FAILED* on a create session message. Hijack attempt?"); // For now, we do NOT send a SessionStatusMessage - see javadoc above - _runner.disconnectClient("Invalid signature on CreateSessionMessage"); + int itype = in.getDestination().getCertificate().getCertificateType(); + SigType stype = SigType.getByCode(itype); + if (stype == null || !stype.isAvailable()) { + _log.error("Client requested unsupported signature type " + itype); + _runner.disconnectClient("Unsupported signature type " + itype); + } else { + _log.error("Signature verification failed on a create session message"); + _runner.disconnectClient("Invalid signature on CreateSessionMessage"); + } return; } From fe4d98f0dfe4cd923a48ff114e88ee572c0e7845 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Fri, 8 Aug 2014 16:40:56 +0000 Subject: [PATCH 21/40] javadoc --- core/java/src/net/i2p/data/Base32.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/java/src/net/i2p/data/Base32.java b/core/java/src/net/i2p/data/Base32.java index 75671c31d4..4ca506b883 100644 --- a/core/java/src/net/i2p/data/Base32.java +++ b/core/java/src/net/i2p/data/Base32.java @@ -56,6 +56,7 @@ public class Base32 { }; private final static byte BAD_ENCODING = -9; // Indicates error in encoding + /** Defeats instantiation. */ private Base32() { // nop } @@ -136,6 +137,9 @@ public class Base32 { } /** + * Returns lower case. + * Does not add trailing '='. + * * @param source if null will return "" */ public static String encode(String source) { @@ -143,6 +147,9 @@ public class Base32 { } /** + * Returns lower case. + * Does not add trailing '='. + * * @param source The data to convert non-null */ public static String encode(byte[] source) { @@ -182,6 +189,8 @@ public class Base32 { /** * Decodes data from Base32 notation and * returns it as a string. + * Case-insensitive. + * Does not allow trailing '='. * * @param s the string to decode, if null returns null * @return The data as a string or null on failure @@ -194,6 +203,9 @@ public class Base32 { } /** + * Case-insensitive. + * Does not allow trailing '='. + * * @param s non-null * @return decoded data, null on error */ From 03d8314842520b234bc000a902c0cd2a831e8bbe Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Fri, 8 Aug 2014 16:41:27 +0000 Subject: [PATCH 22/40] dir for plugin certs From 0bacbbc553a12b094042d4cd216a77f392905a5f Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sat, 9 Aug 2014 17:55:17 +0000 Subject: [PATCH 23/40] SigType: Add static isAvailable() methods SU3File: - Add -x option to bypass signature verification - Add -k option to use specified private key cert for verification - Don't verify signature in showversion --- core/java/src/net/i2p/crypto/SU3File.java | 143 +++++++++++++++++----- core/java/src/net/i2p/crypto/SigType.java | 23 ++++ 2 files changed, 138 insertions(+), 28 deletions(-) diff --git a/core/java/src/net/i2p/crypto/SU3File.java b/core/java/src/net/i2p/crypto/SU3File.java index 8b09338a76..9c158a48a1 100644 --- a/core/java/src/net/i2p/crypto/SU3File.java +++ b/core/java/src/net/i2p/crypto/SU3File.java @@ -15,6 +15,8 @@ import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; @@ -55,6 +57,8 @@ public class SU3File { private PublicKey _signerPubkey; private boolean _headerVerified; private SigType _sigType; + private boolean _verifySignature = true; + private File _certFile; public static final String MAGIC = "I2Psu3"; private static final byte[] MAGIC_BYTES = DataHelper.getASCII(MAGIC); @@ -130,17 +134,44 @@ public class SU3File { _file = file; } + /** + * Should the signature be verified? Default true + * @since 0.9.15 + */ + public void setVerifySignature(boolean shouldVerify) { + _verifySignature = shouldVerify; + } + + /** + * Use this X.509 cert file for verification instead of $I2P/certificates/content_type/foo_at_mail.i2p + * @since 0.9.15 + */ + private void setPublicKeyCertificate(File certFile) { + _certFile = certFile; + } + + /** + * This does not check the signature, but it will fail if the signer is unknown, + * unless setVerifySignature(false) has been called. + */ public String getVersionString() throws IOException { verifyHeader(); return _version; } + /** + * This does not check the signature, but it will fail if the signer is unknown, + * unless setVerifySignature(false) has been called. + */ public String getSignerString() throws IOException { verifyHeader(); return _signer; } /** + * This does not check the signature, but it will fail if the signer is unknown, + * unless setVerifySignature(false) has been called. + * * @return null if unknown * @since 0.9.9 */ @@ -150,6 +181,9 @@ public class SU3File { } /** + * This does not check the signature, but it will fail if the signer is unknown, + * unless setVerifySignature(false) has been called. + * * @return -1 if unknown * @since 0.9.9 */ @@ -159,6 +193,9 @@ public class SU3File { } /** + * This does not check the signature, but it will fail if the signer is unknown, + * unless setVerifySignature(false) has been called. + * * @return -1 if unknown * @since 0.9.15 */ @@ -168,6 +205,9 @@ public class SU3File { } /** + * This does not check the signature, but it will fail if the signer is unknown, + * unless setVerifySignature(false) has been called. + * * Throws IOE if verify vails. */ public void verifyHeader() throws IOException { @@ -245,17 +285,22 @@ public class SU3File { throw new EOFException(); _signer = DataHelper.getUTF8(data); - KeyRing ring = new DirKeyRing(new File(_context.getBaseDir(), "certificates")); - try { - _signerPubkey = ring.getKey(_signer, _contentType.getName(), _sigType); - } catch (GeneralSecurityException gse) { - IOException ioe = new IOException("keystore error"); - ioe.initCause(gse); - throw ioe; + if (_verifySignature) { + if (_certFile != null) { + _signerPubkey = loadKey(_certFile); + } else { + KeyRing ring = new DirKeyRing(new File(_context.getBaseDir(), "certificates")); + try { + _signerPubkey = ring.getKey(_signer, _contentType.getName(), _sigType); + } catch (GeneralSecurityException gse) { + IOException ioe = new IOException("keystore error"); + ioe.initCause(gse); + throw ioe; + } + if (_signerPubkey == null) + throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName()); + } } - - if (_signerPubkey == null) - throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName()); _headerVerified = true; } @@ -324,8 +369,10 @@ public class SU3File { verifyHeader(in); else skip(in, getContentOffset()); - if (_signerPubkey == null) - throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName()); + if (_verifySignature) { + if (_signerPubkey == null) + throw new IOException("unknown signer: " + _signer + " for content type: " + _contentType.getName()); + } if (migrateTo != null) // else verify only out = new FileOutputStream(migrateTo); byte[] buf = new byte[16*1024]; @@ -338,15 +385,19 @@ public class SU3File { out.write(buf, 0, read); tot += read; } - byte[] sha = md.digest(); - din.on(false); - Signature signature = new Signature(_sigType); - signature.readBytes(in); - SimpleDataStructure hash = _sigType.getHashInstance(); - hash.setData(sha); - //System.out.println("hash\n" + HexDump.dump(sha)); - //System.out.println("sig\n" + HexDump.dump(signature.getData())); - rv = _context.dsa().verifySignature(signature, hash, _signerPubkey); + if (_verifySignature) { + byte[] sha = md.digest(); + din.on(false); + Signature signature = new Signature(_sigType); + signature.readBytes(in); + SimpleDataStructure hash = _sigType.getHashInstance(); + hash.setData(sha); + //System.out.println("hash\n" + HexDump.dump(sha)); + //System.out.println("sig\n" + HexDump.dump(signature.getData())); + rv = _context.dsa().verifySignature(signature, hash, _signerPubkey); + } else { + rv = true; + } } catch (DataFormatException dfe) { IOException ioe = new IOException("foo"); ioe.initCause(dfe); @@ -461,8 +512,10 @@ public class SU3File { String stype = null; String ctype = null; String ftype = null; + String kfile = null; boolean error = false; - Getopt g = new Getopt("SU3File", args, "t:c:f:"); + boolean shouldVerify = true; + Getopt g = new Getopt("SU3File", args, "t:c:f:k:x"); int c; while ((c = g.getopt()) != -1) { switch (c) { @@ -478,6 +531,14 @@ public class SU3File { ftype = g.getOptarg(); break; + case 'k': + kfile = g.getOptarg(); + break; + + case 'x': + shouldVerify = false; + break; + case '?': case ':': default: @@ -505,11 +566,11 @@ public class SU3File { new I2PAppContext(props); ok = bulkSignCLI(stype, ctype, a.get(0), a.get(1), a.get(2), a.get(3)); } else if ("verifysig".equals(cmd)) { - ok = verifySigCLI(a.get(0)); + ok = verifySigCLI(a.get(0), kfile); } else if ("keygen".equals(cmd)) { ok = genKeysCLI(stype, a.get(0), a.get(1), a.get(2)); } else if ("extract".equals(cmd)) { - ok = extractCLI(a.get(0), a.get(1)); + ok = extractCLI(a.get(0), a.get(1), shouldVerify); } else { showUsageCLI(); } @@ -527,8 +588,8 @@ public class SU3File { System.err.println(" SU3File sign [-t type|code] [-c type|code] [-f type|code] inputFile.zip signedFile.su3 keystore.ks version you@mail.i2p"); System.err.println(" SU3File bulksign [-t type|code] [-c type|code] directory keystore.ks version you@mail.i2p"); System.err.println(" SU3File showversion signedFile.su3"); - System.err.println(" SU3File verifysig signedFile.su3"); - System.err.println(" SU3File extract signedFile.su3 outFile"); + System.err.println(" SU3File verifysig [-k file.crt] signedFile.su3 ## -k use this pubkey cert for verification"); + System.err.println(" SU3File extract [-x] [-k file.crt] signedFile.su3 outFile ## -x don't check sig"); System.err.println(dumpTypes()); } @@ -579,6 +640,7 @@ public class SU3File { private static final boolean showVersionCLI(String signedFile) { try { SU3File file = new SU3File(signedFile); + file.setVerifySignature(false); String versionString = file.getVersionString(); if (versionString.equals("")) System.out.println("No version string found in file '" + signedFile + "'"); @@ -726,10 +788,12 @@ public class SU3File { } /** @return valid */ - private static final boolean verifySigCLI(String signedFile) { + private static final boolean verifySigCLI(String signedFile, String pkFile) { InputStream in = null; try { SU3File file = new SU3File(signedFile); + if (pkFile != null) + file.setPublicKeyCertificate(new File(pkFile)); boolean isValidSignature = file.verify(); if (isValidSignature) System.out.println("Signature VALID (signed by " + file.getSignerString() + ' ' + file._sigType + ')'); @@ -747,10 +811,11 @@ public class SU3File { * @return success * @since 0.9.9 */ - private static final boolean extractCLI(String signedFile, String outFile) { + private static final boolean extractCLI(String signedFile, String outFile, boolean verifySig) { InputStream in = null; try { SU3File file = new SU3File(signedFile); + file.setVerifySignature(verifySig); File out = new File(outFile); boolean ok = file.verifyAndMigrate(out); if (ok) @@ -836,4 +901,26 @@ public class SU3File { } return true; } + + /** + * For the -k CLI option + * @return non-null, throws IOE on all errors + * @since 0.9.15 + */ + private static PublicKey loadKey(File kd) throws IOException { + InputStream fis = null; + try { + fis = new FileInputStream(kd); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate)cf.generateCertificate(fis); + cert.checkValidity(); + return cert.getPublicKey(); + } catch (GeneralSecurityException gse) { + IOException ioe = new IOException("cert error"); + ioe.initCause(gse); + throw ioe; + } finally { + try { if (fis != null) fis.close(); } catch (IOException foo) {} + } + } } diff --git a/core/java/src/net/i2p/crypto/SigType.java b/core/java/src/net/i2p/crypto/SigType.java index f63eadea84..700f355c66 100644 --- a/core/java/src/net/i2p/crypto/SigType.java +++ b/core/java/src/net/i2p/crypto/SigType.java @@ -178,6 +178,29 @@ public enum SigType { return true; } + /** + * @return true if supported in this JVM + * @since 0.9.15 + */ + public static boolean isAvailable(int code) { + SigType type = getByCode(code); + if (type == null) + return false; + return type.isAvailable(); + } + + /** + * @param stype number or name + * @return true if supported in this JVM + * @since 0.9.15 + */ + public static boolean isAvailable(String stype) { + SigType type = parseSigType(stype); + if (type == null) + return false; + return type.isAvailable(); + } + private static final Map<Integer, SigType> BY_CODE = new HashMap<Integer, SigType>(); static { From 22a7757461a80566e9b1381c42ed31fda0ea6bfd Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sat, 9 Aug 2014 18:08:00 +0000 Subject: [PATCH 24/40] Console: Show share options below 30% (ticket #1329) --- .../java/src/net/i2p/router/web/ConfigNetHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java index d3450eb6f3..efe9f4f819 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java @@ -298,9 +298,9 @@ public class ConfigNetHelper extends HelperBase { StringBuilder buf = new StringBuilder(256); buf.append("<select style=\"text-align: right !important;\" name=\"sharePercentage\">\n"); boolean found = false; - for (int i = 30; i <= 110; i += 10) { + for (int i = 100; i >= -10; i -= 10) { int val = i; - if (i == 110) { + if (i == -10) { if (found) break; else From 6fa2a416be2a10493848e993c7b5050045edc86b Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 10 Aug 2014 12:18:18 +0000 Subject: [PATCH 25/40] Console: Hide client delete button too --- .../java/src/net/i2p/router/web/ConfigClientsHandler.java | 7 ++++++- .../java/src/net/i2p/router/web/ConfigClientsHelper.java | 2 +- router/java/src/net/i2p/router/RouterVersion.java | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java index 5acdf313b2..aac87fbfb9 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java @@ -104,7 +104,12 @@ public class ConfigClientsHandler extends FormHandler { appnum = Integer.parseInt(app); } catch (NumberFormatException nfe) {} if (appnum >= 0) { - deleteClient(appnum); + if (_context.getBooleanProperty(ConfigClientsHelper.PROP_ENABLE_CLIENT_CHANGE) || + isAdvanced()) { + deleteClient(appnum); + } else { + addFormError("Delete client disabled"); + } } else if (pluginsEnabled) { try { PluginStarter.stopPlugin(_context, app); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java index 843fef7373..4d0adeca68 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java @@ -141,7 +141,7 @@ public class ConfigClientsHelper extends HelperBase { // show stop button showStop, // show delete button, show start button - !isConsole, showStart); + allowEdit && !isConsole, showStart); } if (allowEdit && "new".equals(_edit)) diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index a411b00998..87e5bffca0 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 0; + public final static long BUILD = 1; /** for example "-test" */ public final static String EXTRA = ""; From 4ba40b340aaef91e52e17939799d6ea77da8a2bc Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 10 Aug 2014 14:08:05 +0000 Subject: [PATCH 26/40] history for prop, -2 --- history.txt | 30 +++++++++++++++++++ .../src/net/i2p/router/RouterVersion.java | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/history.txt b/history.txt index de3a674a29..7687869189 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,33 @@ +2014-08-10 zzz +Prop from i2p.i2p.zzz.test2: + * Console: Show share options below 30% (ticket #1329) + * Crypto: Move TransientSessionKeyManager from core to router. + I2PAppContext will return the dummy SessionKeyManager which + is sufficient for non-tag uses (e.g. Bote). + Client use of end-to-end encryption using SessionTags was + disabled in release 0.6, 2005-07-27. + * KeysAndCert: Change hashcode to prevent possible collisions + caused by apps with zeroed pubkey + * Plugins: Start of SU3 support (ticket #1227) + * SAM: + - Don't spawn a thread for each transmitted datagram + - Set protocol field for raw and signed datagrams + - Enforce a 60s timeout for HELLO + - Use naming service cache to reduce Destination object churn + - Get Log object from the log manager + * SigType: Add static isAvailable() methods + * SSU: Speed up introductions by responding to HolePunch (ticket #1333) + * SU3File: + - Add support for XML and NEWS types + - Fix NPE on EOF reading input + - Add -x option to bypass signature verification + - Add -k option to use specified private key cert for verification + - Don't verify signature in showversion + * UPnP: Disable external entities in XML parser + +2014-08-10 zzz + * Console: Hide client delete buttons unless advanced on /configclients + * 2014-08-09 0.9.14.1 released 2014-08-07 kytv diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 87e5bffca0..282c18b422 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 1; + public final static long BUILD = 2; /** for example "-test" */ public final static String EXTRA = ""; From 3b18cb7ecaa53689fa90b4900795cc1c2c3b1a9b Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 10 Aug 2014 14:22:16 +0000 Subject: [PATCH 27/40] history for prop, -3 --- history.txt | 17 +++++++++++++++++ .../java/src/net/i2p/router/RouterVersion.java | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/history.txt b/history.txt index 7687869189..aa11143a60 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,20 @@ +2014-08-10 zzz +Prop from i2p.i2p.zzz.snarkconfig: + * i2psnark: + - Move config file and DHT persistence file to a config dir + - Move per-torrent configuration from "zmeta" in the main config file + to a per-torrent config file (ticket #1132) + - Split timestamp and bitfield into separate configs + - Fix misspelling of autoStart config + - Remove two unused SnarkManager methods + - Refactor file deletion in prep for better file name handling (ticket #571) + - Don't use canonical files in directory listings, + for speed and to avoid file comparison problems (tickets #1079, #1148) + - Set base file/dir in Storage constructor, make final, + in prep for arbitrary locations (ticket #1028) + - Add missing nonce protection for file priority setting + - Add torrent mime type + 2014-08-10 zzz Prop from i2p.i2p.zzz.test2: * Console: Show share options below 30% (ticket #1329) diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 282c18b422..0725033fa6 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 2; + public final static long BUILD = 3; /** for example "-test" */ public final static String EXTRA = ""; From 41672dde645d1cbf8d1404a0c62055af49248ded Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 10 Aug 2014 14:57:28 +0000 Subject: [PATCH 28/40] include geoip.txt in updater for next release --- build.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build.xml b/build.xml index 14aad90728..11a1e74ea4 100644 --- a/build.xml +++ b/build.xml @@ -1094,6 +1094,7 @@ <target name="updater200" depends="prepupdate, preplicenses, pack200, zipit200" /> <target name="updater200WithJetty" depends="prepjupdate, preplicenses, pack200, zipit200" /> + <target name="updater200WithJettyAndGeoIP" depends="prepjupdate, prepgeoupdate, preplicenses, pack200, zipit200" /> <target name="updater200WithJettyFixes" depends="prepjupdatefixes, preplicenses, pack200, zipit200" /> <target name="updater200WithJettyFixesAndJbigi" depends="prepjupdatefixes, prepjbigiupdate, preplicenses, pack200, zipit200" /> <target name="updater" depends="prepupdate, preplicenses, zipit" /> @@ -1105,6 +1106,7 @@ <target name="updaterWithGeoIP" depends="prepupdate, prepgeoupdate, preplicenses, zipit" /> <target name="updaterWithJetty" depends="prepjupdate, preplicenses, zipit" /> <target name="updaterWithJettyRepack" depends="prepjupdate, preplicenses, repack200, zipit" /> + <target name="updaterWithJettyAndGeoIPRepack" depends="prepjupdate, prepgeoupdate, preplicenses, repack200, zipit" /> <target name="updaterWithJettyFixes" depends="prepjupdatefixes, preplicenses, zipit" /> <target name="updaterWithJettyFixesAndJbigi" depends="prepjupdatefixes, prepjbigiupdate, preplicenses, zipit" /> <target name="updaterWithJettyFixesAndGeoIP" depends="prepjupdatefixes, prepgeoupdate, preplicenses, zipit" /> @@ -1235,9 +1237,11 @@ <copy file="installer/resources/geoip.txt" todir="pkg-temp/geoip/" /> <copy file="installer/resources/geoipv6.dat.gz" todir="pkg-temp/geoip/" /> <copy file="installer/resources/countries.txt" todir="pkg-temp/geoip/" /> + <!-- <copy todir="pkg-temp/docs/icons/flags" > <fileset dir="installer/resources/icons/flags" /> </copy> + --> </target> <!-- All jetty jars required for update. @@ -1559,8 +1563,9 @@ since preppkg puts too much stuff in pkg-temp --> <!-- <target name="release" depends="distclean, updaterWithJettyFixesAndJbigi , updater200WithJettyFixes, preppkg, installer, getReleaseNumber" > ---> <target name="release" depends="verifyReleaseBuildNumbers, -pre-release, distclean, testscripts, updaterWithJettyRepack, updater200WithJetty, delete-j6-update, installer-nowindows, delete-nonwindows, installer-windows"> +--> + <target name="release" depends="verifyReleaseBuildNumbers, -pre-release, distclean, testscripts, updaterWithJettyAndGeoIPRepack, updater200WithJettyAndGeoIP, delete-j6-update, installer-nowindows, delete-nonwindows, installer-windows"> <echo message="New version number is ${release.number}" /> <copy file="i2pupdate.zip" tofile="i2pupdate_${release.number}.zip" /> <copy file="i2pinstall_${full.version}.jar" tofile="i2pinstall_${release.number}.jar" /> From a63bfeaeecc22485ca9f67e0304d88b22ee04d6b Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 10 Aug 2014 15:48:18 +0000 Subject: [PATCH 29/40] fix SKM test broken by TSKM move --- .../junit/net/i2p/crypto/CryptoTestSuite.java | 1 - .../router}/crypto/SessionEncryptionTest.java | 112 ++++++++++-------- 2 files changed, 60 insertions(+), 53 deletions(-) rename {core/java/test/junit/net/i2p => router/java/test/junit/net/i2p/router}/crypto/SessionEncryptionTest.java (72%) diff --git a/core/java/test/junit/net/i2p/crypto/CryptoTestSuite.java b/core/java/test/junit/net/i2p/crypto/CryptoTestSuite.java index 4300802659..19f9abad96 100644 --- a/core/java/test/junit/net/i2p/crypto/CryptoTestSuite.java +++ b/core/java/test/junit/net/i2p/crypto/CryptoTestSuite.java @@ -28,7 +28,6 @@ public class CryptoTestSuite { suite.addTestSuite(ElGamalTest.class); suite.addTestSuite(HMACSHA256Test.class); suite.addTestSuite(KeyGeneratorTest.class); - suite.addTestSuite(SessionEncryptionTest.class); suite.addTestSuite(SHA1HashTest.class); suite.addTestSuite(SHA256Test.class); diff --git a/core/java/test/junit/net/i2p/crypto/SessionEncryptionTest.java b/router/java/test/junit/net/i2p/router/crypto/SessionEncryptionTest.java similarity index 72% rename from core/java/test/junit/net/i2p/crypto/SessionEncryptionTest.java rename to router/java/test/junit/net/i2p/router/crypto/SessionEncryptionTest.java index ace051aa78..fe2b1d9efe 100644 --- a/core/java/test/junit/net/i2p/crypto/SessionEncryptionTest.java +++ b/router/java/test/junit/net/i2p/router/crypto/SessionEncryptionTest.java @@ -1,4 +1,4 @@ -package net.i2p.crypto; +package net.i2p.router.crypto; /* * free (adj.): unencumbered; not under the control of others * Written by jrandom in 2003 and released into the public domain @@ -13,6 +13,9 @@ import java.util.Set; import junit.framework.TestCase; import net.i2p.I2PAppContext; +import net.i2p.crypto.KeyGenerator; +import net.i2p.crypto.SessionKeyManager; +import net.i2p.crypto.TagSetHandle; import net.i2p.data.DataHelper; import net.i2p.data.PrivateKey; import net.i2p.data.PublicKey; @@ -25,10 +28,10 @@ import net.i2p.data.SessionTag; * */ public class SessionEncryptionTest extends TestCase{ - private static I2PAppContext _context = I2PAppContext.getGlobalContext(); + private I2PAppContext _context; protected void setUp(){ - _context = new I2PAppContext(); + _context = I2PAppContext.getGlobalContext(); } protected void tearDown() { @@ -40,12 +43,13 @@ public class SessionEncryptionTest extends TestCase{ Object keys[] = KeyGenerator.getInstance().generatePKIKeypair(); PublicKey pubKey = (PublicKey)keys[0]; PrivateKey privKey = (PrivateKey)keys[1]; - SessionKey curKey = _context.sessionKeyManager().createSession(pubKey); + SessionKeyManager skm = new TransientSessionKeyManager(_context); + SessionKey curKey = skm.createSession(pubKey); byte[] msg = "msg 1".getBytes(); byte emsg[] = _context.elGamalAESEngine().encrypt(msg, pubKey, curKey, 64); - byte dmsg[] = _context.elGamalAESEngine().decrypt(emsg, privKey); + byte dmsg[] = _context.elGamalAESEngine().decrypt(emsg, privKey, skm); assertTrue(DataHelper.eq(dmsg, msg)); } @@ -53,12 +57,13 @@ public class SessionEncryptionTest extends TestCase{ Object keys[] = KeyGenerator.getInstance().generatePKIKeypair(); PublicKey pubKey = (PublicKey)keys[0]; PrivateKey privKey = (PrivateKey)keys[1]; - SessionKey curKey = _context.sessionKeyManager().createSession(pubKey); + SessionKeyManager skm = new TransientSessionKeyManager(_context); + SessionKey curKey = skm.createSession(pubKey); byte[] msg = "msg 2".getBytes(); byte emsg[] = _context.elGamalAESEngine().encrypt(msg, pubKey, curKey, 64); - byte dmsg[] = _context.elGamalAESEngine().decrypt(emsg, privKey); + byte dmsg[] = _context.elGamalAESEngine().decrypt(emsg, privKey, skm); assertTrue(DataHelper.eq(dmsg, msg)); } @@ -74,7 +79,8 @@ public class SessionEncryptionTest extends TestCase{ Object keys[] = KeyGenerator.getInstance().generatePKIKeypair(); PublicKey pubKey = (PublicKey)keys[0]; PrivateKey privKey = (PrivateKey)keys[1]; - SessionKey curKey = _context.sessionKeyManager().createSession(pubKey); + SessionKeyManager skm = new TransientSessionKeyManager(_context); + SessionKey curKey = skm.createSession(pubKey); SessionTag tag1 = new SessionTag(true); SessionTag tag2 = new SessionTag(true); @@ -97,64 +103,64 @@ public class SessionEncryptionTest extends TestCase{ byte emsg1[] = _context.elGamalAESEngine().encrypt(msg1, pubKey, curKey, firstTags, 64); - byte dmsg1[] = _context.elGamalAESEngine().decrypt(emsg1, privKey); + byte dmsg1[] = _context.elGamalAESEngine().decrypt(emsg1, privKey, skm); assertTrue(DataHelper.eq(dmsg1, msg1)); - TagSetHandle tsh = _context.sessionKeyManager().tagsDelivered(pubKey, curKey, firstTags); - _context.sessionKeyManager().tagsAcked(pubKey, curKey, tsh); + TagSetHandle tsh = skm.tagsDelivered(pubKey, curKey, firstTags); + skm.tagsAcked(pubKey, curKey, tsh); - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - SessionTag curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + SessionTag curTag = skm.consumeNextAvailableTag(pubKey, curKey); assertNotNull(curTag); byte emsg2[] = _context.elGamalAESEngine().encrypt(msg2, pubKey, curKey, null, curTag, 64); - byte dmsg2[] = _context.elGamalAESEngine().decrypt(emsg2, privKey); + byte dmsg2[] = _context.elGamalAESEngine().decrypt(emsg2, privKey, skm); assertTrue(DataHelper.eq(dmsg2, msg2)); - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + curTag = skm.consumeNextAvailableTag(pubKey, curKey); assertNotNull(curTag); assertNotNull(curKey); byte emsg3[] = _context.elGamalAESEngine().encrypt(msg3, pubKey, curKey, secondTags, curTag, 64); - byte dmsg3[] = _context.elGamalAESEngine().decrypt(emsg3, privKey); + byte dmsg3[] = _context.elGamalAESEngine().decrypt(emsg3, privKey, skm); assertTrue(DataHelper.eq(dmsg3, msg3)); - tsh = _context.sessionKeyManager().tagsDelivered(pubKey, curKey, secondTags); - _context.sessionKeyManager().tagsAcked(pubKey, curKey, tsh); + tsh = skm.tagsDelivered(pubKey, curKey, secondTags); + skm.tagsAcked(pubKey, curKey, tsh); - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + curTag = skm.consumeNextAvailableTag(pubKey, curKey); assertNotNull(curTag); assertNotNull(curKey); byte emsg4[] = _context.elGamalAESEngine().encrypt(msg4, pubKey, curKey, null, curTag, 64); - byte dmsg4[] = _context.elGamalAESEngine().decrypt(emsg4, privKey); + byte dmsg4[] = _context.elGamalAESEngine().decrypt(emsg4, privKey, skm); assertTrue(DataHelper.eq(dmsg4, msg4)); - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + curTag = skm.consumeNextAvailableTag(pubKey, curKey); assertNotNull(curTag); assertNotNull(curKey); byte emsg5[] = _context.elGamalAESEngine().encrypt(msg5, pubKey, curKey, null, curTag, 64); - byte dmsg5[] = _context.elGamalAESEngine().decrypt(emsg5, privKey); + byte dmsg5[] = _context.elGamalAESEngine().decrypt(emsg5, privKey, skm); assertTrue(DataHelper.eq(dmsg5, msg5)); @@ -172,7 +178,8 @@ public class SessionEncryptionTest extends TestCase{ Object keys[] = KeyGenerator.getInstance().generatePKIKeypair(); PublicKey pubKey = (PublicKey)keys[0]; PrivateKey privKey = (PrivateKey)keys[1]; - SessionKey curKey = _context.sessionKeyManager().createSession(pubKey); + SessionKeyManager skm = new TransientSessionKeyManager(_context); + SessionKey curKey = skm.createSession(pubKey); SessionKey nextKey = KeyGenerator.getInstance().generateSessionKey(); SessionTag tag1 = new SessionTag(true); @@ -196,64 +203,64 @@ public class SessionEncryptionTest extends TestCase{ byte emsg1[] = _context.elGamalAESEngine().encrypt(msg1, pubKey, curKey, firstTags, 64); - byte dmsg1[] = _context.elGamalAESEngine().decrypt(emsg1, privKey); + byte dmsg1[] = _context.elGamalAESEngine().decrypt(emsg1, privKey, skm); assertTrue(DataHelper.eq(dmsg1, msg1)); - TagSetHandle tsh = _context.sessionKeyManager().tagsDelivered(pubKey, curKey, firstTags); - _context.sessionKeyManager().tagsAcked(pubKey, curKey, tsh); + TagSetHandle tsh = skm.tagsDelivered(pubKey, curKey, firstTags); + skm.tagsAcked(pubKey, curKey, tsh); - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - SessionTag curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + SessionTag curTag = skm.consumeNextAvailableTag(pubKey, curKey); assertNotNull(curTag); byte emsg2[] = _context.elGamalAESEngine().encrypt(msg2, pubKey, curKey, null, curTag, 64); - byte dmsg2[] = _context.elGamalAESEngine().decrypt(emsg2, privKey); + byte dmsg2[] = _context.elGamalAESEngine().decrypt(emsg2, privKey, skm); assertTrue(DataHelper.eq(dmsg2, msg2)); - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + curTag = skm.consumeNextAvailableTag(pubKey, curKey); assertNotNull(curTag); assertNotNull(curKey); byte emsg3[] = _context.elGamalAESEngine().encrypt(msg3, pubKey, curKey, secondTags, curTag, nextKey, 64); - byte dmsg3[] = _context.elGamalAESEngine().decrypt(emsg3, privKey); + byte dmsg3[] = _context.elGamalAESEngine().decrypt(emsg3, privKey, skm); assertTrue(DataHelper.eq(dmsg3, msg3)); - tsh = _context.sessionKeyManager().tagsDelivered(pubKey, nextKey, secondTags); // note nextKey not curKey - _context.sessionKeyManager().tagsAcked(pubKey, nextKey, tsh); + tsh = skm.tagsDelivered(pubKey, nextKey, secondTags); // note nextKey not curKey + skm.tagsAcked(pubKey, nextKey, tsh); - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + curTag = skm.consumeNextAvailableTag(pubKey, curKey); assertNotNull(curTag); assertNotNull(curKey); byte emsg4[] = _context.elGamalAESEngine().encrypt(msg4, pubKey, curKey, null, curTag, 64); - byte dmsg4[] = _context.elGamalAESEngine().decrypt(emsg4, privKey); + byte dmsg4[] = _context.elGamalAESEngine().decrypt(emsg4, privKey, skm); assertTrue(DataHelper.eq(dmsg4, msg4)); - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + curTag = skm.consumeNextAvailableTag(pubKey, curKey); assertNotNull(curTag); assertNotNull(curKey); byte emsg5[] = _context.elGamalAESEngine().encrypt(msg5, pubKey, curKey, null, curTag, 64); - byte dmsg5[] = _context.elGamalAESEngine().decrypt(emsg5, privKey); + byte dmsg5[] = _context.elGamalAESEngine().decrypt(emsg5, privKey, skm); assertTrue(DataHelper.eq(dmsg5, msg5)); @@ -268,15 +275,16 @@ public class SessionEncryptionTest extends TestCase{ Object keys[] = KeyGenerator.getInstance().generatePKIKeypair(); PublicKey pubKey = (PublicKey)keys[0]; PrivateKey privKey = (PrivateKey)keys[1]; - SessionKey curKey = _context.sessionKeyManager().createSession(pubKey); + SessionKeyManager skm = new TransientSessionKeyManager(_context); + SessionKey curKey = skm.createSession(pubKey); for (int i = 0; i < 1000; i++) { Set<SessionTag> tags = null; SessionKey nextKey = null; - curKey = _context.sessionKeyManager().getCurrentKey(pubKey); - SessionTag curTag = _context.sessionKeyManager().consumeNextAvailableTag(pubKey, curKey); + curKey = skm.getCurrentKey(pubKey); + SessionTag curTag = skm.consumeNextAvailableTag(pubKey, curKey); - int availTags = _context.sessionKeyManager().getAvailableTags(pubKey, curKey); + int availTags = skm.getAvailableTags(pubKey, curKey); if ((availTags < 1)) { tags = generateNewTags(50); } @@ -287,16 +295,16 @@ public class SessionEncryptionTest extends TestCase{ byte emsg[] = _context.elGamalAESEngine().encrypt(msg, pubKey, curKey, tags, curTag, nextKey, 64); - byte dmsg[] = _context.elGamalAESEngine().decrypt(emsg, privKey); + byte dmsg[] = _context.elGamalAESEngine().decrypt(emsg, privKey, skm); assertTrue(DataHelper.eq(dmsg, msg)); if ( (tags != null) && (tags.size() > 0) ) { if (nextKey == null) { - TagSetHandle tsh = _context.sessionKeyManager().tagsDelivered(pubKey, curKey, tags); - _context.sessionKeyManager().tagsAcked(pubKey, curKey, tsh); + TagSetHandle tsh = skm.tagsDelivered(pubKey, curKey, tags); + skm.tagsAcked(pubKey, curKey, tsh); } else { - TagSetHandle tsh = _context.sessionKeyManager().tagsDelivered(pubKey, nextKey, tags); - _context.sessionKeyManager().tagsAcked(pubKey, nextKey, tsh); + TagSetHandle tsh = skm.tagsDelivered(pubKey, nextKey, tags); + skm.tagsAcked(pubKey, nextKey, tsh); } } } From 367cea4b1f7d089b7e6eceb4a941ace22246fbf8 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 10 Aug 2014 19:32:11 +0000 Subject: [PATCH 30/40] new translation files --- .tx/config | 23 +- apps/i2psnark/locale/messages_pt_bR.po | 1244 +++++++++++++++++ apps/i2ptunnel/locale-proxy/messages_sk.po | 455 ++++++ apps/i2ptunnel/locale/messages_es | 0 apps/i2ptunnel/locale/messages_nn.po | 1180 ++++++++++++++++ apps/i2ptunnel/locale/messages_ro.po | 1180 ++++++++++++++++ apps/ministreaming/locale/messages_de.po | 91 ++ apps/ministreaming/locale/messages_es.po | 90 ++ apps/ministreaming/locale/messages_fr.po | 90 ++ apps/ministreaming/locale/messages_it.po | 90 ++ apps/ministreaming/locale/messages_nb.po | 90 ++ apps/ministreaming/locale/messages_ru.po | 91 ++ apps/ministreaming/locale/messages_uk.po | 90 ++ apps/ministreaming/locale/messages_zh.po | 90 ++ .../locale-countries/messages_ca.po | 763 ++++++++++ .../locale-countries/messages_sq.po | 764 ++++++++++ .../locale-countries/messages_uk.po | 764 ++++++++++ apps/routerconsole/locale-news/messages_he.po | 66 + apps/routerconsole/locale-news/messages_ko.po | 65 + apps/routerconsole/locale-news/messages_nb.po | 65 + apps/routerconsole/locale-news/messages_uk.po | 67 + apps/susidns/locale/messages_tr.po | 703 ++++++++++ apps/susimail/locale/messages_da.po | 520 +++++++ 23 files changed, 8580 insertions(+), 1 deletion(-) create mode 100644 apps/i2psnark/locale/messages_pt_bR.po create mode 100644 apps/i2ptunnel/locale-proxy/messages_sk.po create mode 100644 apps/i2ptunnel/locale/messages_es create mode 100644 apps/i2ptunnel/locale/messages_nn.po create mode 100644 apps/i2ptunnel/locale/messages_ro.po create mode 100644 apps/ministreaming/locale/messages_de.po create mode 100644 apps/ministreaming/locale/messages_es.po create mode 100644 apps/ministreaming/locale/messages_fr.po create mode 100644 apps/ministreaming/locale/messages_it.po create mode 100644 apps/ministreaming/locale/messages_nb.po create mode 100644 apps/ministreaming/locale/messages_ru.po create mode 100644 apps/ministreaming/locale/messages_uk.po create mode 100644 apps/ministreaming/locale/messages_zh.po create mode 100644 apps/routerconsole/locale-countries/messages_ca.po create mode 100644 apps/routerconsole/locale-countries/messages_sq.po create mode 100644 apps/routerconsole/locale-countries/messages_uk.po create mode 100644 apps/routerconsole/locale-news/messages_he.po create mode 100644 apps/routerconsole/locale-news/messages_ko.po create mode 100644 apps/routerconsole/locale-news/messages_nb.po create mode 100644 apps/routerconsole/locale-news/messages_uk.po create mode 100644 apps/susidns/locale/messages_tr.po create mode 100644 apps/susimail/locale/messages_da.po diff --git a/.tx/config b/.tx/config index 1374640b06..dad1629754 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 @@ -39,6 +41,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 @@ -80,8 +83,10 @@ trans.de = apps/routerconsole/locale-news/messages_de.po trans.es = apps/routerconsole/locale-news/messages_es.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 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.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 @@ -91,12 +96,14 @@ trans.ru_RU = apps/routerconsole/locale-news/messages_ru.po trans.sk = apps/routerconsole/locale-news/messages_sk.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 @@ -115,7 +122,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 +143,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 +171,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,6 +205,7 @@ 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.fr = apps/susimail/locale/messages_fr.po @@ -242,6 +254,7 @@ trans.fr = installer/resources/locale/po/messages_fr.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 +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 @@ -274,6 +287,14 @@ 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.de = apps/ministreaming/locale/messages_de.po +trans.es = apps/ministreaming/locale/messages_es.po +trans.fr = apps/ministreaming/locale/messages_fr.po +trans.it = apps/ministreaming/locale/messages_it.po +trans.nb = apps/ministreaming/locale/messages_nb.po +trans.ru_RU = apps/ministreaming/locale/messages_ru.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/apps/i2psnark/locale/messages_pt_bR.po b/apps/i2psnark/locale/messages_pt_bR.po new file mode 100644 index 0000000000..0e26aea0e6 --- /dev/null +++ b/apps/i2psnark/locale/messages_pt_bR.po @@ -0,0 +1,1244 @@ +# 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 <deborinha97@hotmail.com>, 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-07-05 19:07+0000\n" +"Last-Translator: testsubject67 <deborinha97@hotmail.com>\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" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\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 +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 +msgid "Magnet" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:515 +#, java-format +msgid "Total uploaders limit changed to {0}" +msgstr "Limite de uploaders totais alterada para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:517 +#, 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:529 +#, 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:531 +#, 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:543 +#, java-format +msgid "Startup delay changed to {0}" +msgstr "Atraso de inicialização alterada para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:554 +#, java-format +msgid "Refresh time changed to {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:556 +msgid "Refresh disabled" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:572 +#, java-format +msgid "Page size changed to {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:581 +msgid "Data directory must be an absolute path" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:583 +msgid "Data directory does not exist" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:585 +msgid "Not a directory" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:587 +msgid "Unreadable" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:592 +#, java-format +msgid "Data directory changed to {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:647 +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:651 +#, java-format +msgid "I2CP options changed to {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:657 +msgid "Disconnecting old I2CP destination" +msgstr "Desconectando destinação do velho I2CP" + +#: ../java/src/org/klomp/snark/SnarkManager.java:659 +#, java-format +msgid "I2CP settings changed to {0}" +msgstr "Configurações de I2CP alteradas para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:664 +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:668 +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:670 +msgid "Reconnected on the new I2CP destination" +msgstr "Reconectado à nova destinação de I2CP" + +#: ../java/src/org/klomp/snark/SnarkManager.java:677 +#, java-format +msgid "I2CP listener restarted for \"{0}\"" +msgstr "Auditor I2CP recomeçadas a \"{0}\"" + +#: ../java/src/org/klomp/snark/SnarkManager.java:691 +msgid "New files will be publicly readable" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:693 +msgid "New files will not be publicly readable" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:700 +msgid "Enabled autostart" +msgstr "Autocomeço permitido" + +#: ../java/src/org/klomp/snark/SnarkManager.java:702 +msgid "Disabled autostart" +msgstr "Autocomeço não permitido" + +#: ../java/src/org/klomp/snark/SnarkManager.java:708 +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:710 +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:717 +msgid "Enabled DHT." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:719 +msgid "Disabled DHT." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:721 +msgid "DHT change requires tunnel shutdown and reopen" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:728 +#, 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:738 +msgid "Configuration unchanged." +msgstr "Configuração sem alteração" + +#: ../java/src/org/klomp/snark/SnarkManager.java:770 +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:780 +msgid "Private tracker list changed - affects newly created torrents only." +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:826 +#, 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:904 +msgid "Connecting to I2P" +msgstr "Conectando a I2P" + +#: ../java/src/org/klomp/snark/SnarkManager.java:907 +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:916 +#: ../java/src/org/klomp/snark/SnarkManager.java:1692 +#, 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:938 +#, 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: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-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:963 +#, java-format +msgid "ERROR - No I2P trackers in private torrent \"{0}\"" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:965 +#, 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-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-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-format +msgid "Torrent in \"{0}\" is invalid" +msgstr "O torrent em \"{0}\" é inválido" + +#: ../java/src/org/klomp/snark/SnarkManager.java:999 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:186 +#, java-format +msgid "ERROR - Out of memory, cannot create torrent from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1011 +#, java-format +msgid "Torrent added and started: \"{0}\"" +msgstr "Torrent adicionado e começado: \"{0}\"" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1013 +#, java-format +msgid "Torrent added: \"{0}\"" +msgstr "Torrent adicionado: \"{0}\"" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1069 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:89 +#, java-format +msgid "Fetching {0}" +msgstr "Buscando {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1075 +#, 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-format +msgid "Adding {0}" +msgstr "Adicionando {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1111 +#, 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-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:1400 +#, java-format +msgid "Too many files in \"{0}\" ({1}), deleting it!" +msgstr "Arquivos em excesso em \"{0}\" ({1}), deletando!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1402 +#, java-format +msgid "Torrent file \"{0}\" cannot end in \".torrent\", deleting it!" +msgstr "Arquivo de torrent \"{0}\" não pode terminar em \".torrent\", deletando!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1404 +#, java-format +msgid "No pieces in \"{0}\", deleting it!" +msgstr "Sem peças em \"{0}\", deletando!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1406 +#, java-format +msgid "Too many pieces in \"{0}\", limit is {1}, deleting it!" +msgstr "Peças em excesso em \"{0}\". O limite é {1}, deletando!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1408 +#, java-format +msgid "Pieces are too large in \"{0}\" ({1}B), deleting it." +msgstr "Peças são muito grande em \"{0}\" ({1}B), deletando." + +#: ../java/src/org/klomp/snark/SnarkManager.java:1409 +#, java-format +msgid "Limit is {0}B" +msgstr "O limite é {0}B" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1411 +#, java-format +msgid "Torrent \"{0}\" has no data, deleting it!" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1419 +#, java-format +msgid "Torrents larger than {0}B are not supported yet, deleting \"{1}\"" +msgstr "Torrents maiores do que {0}B não são suportados ainda, deletando \"{1}\"" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1435 +#, 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:1456 +#: ../java/src/org/klomp/snark/SnarkManager.java:1474 +#, java-format +msgid "Torrent stopped: \"{0}\"" +msgstr "Torrent parado: \"{0}\"" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1495 +#, java-format +msgid "Torrent removed: \"{0}\"" +msgstr "Torrent removido: \"{0}\"" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1503 +#, java-format +msgid "Adding torrents in {0}" +msgstr "Adicionando torrents em {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1534 +#, java-format +msgid "Up bandwidth limit is {0} KBps" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1556 +#, java-format +msgid "Download finished: {0}" +msgstr "Download terminado: {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1607 +#, java-format +msgid "Metainfo received for {0}" +msgstr "Metainfo recebido para {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1608 +#: ../java/src/org/klomp/snark/SnarkManager.java:1837 +#, java-format +msgid "Starting up torrent {0}" +msgstr "Iniciando torrent {0}" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1623 +#, java-format +msgid "Error on torrent {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1686 +msgid "Unable to connect to I2P!" +msgstr "Incapaz de conectar ao I2P!" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1836 +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:126 +msgid "Opening the I2P tunnel" +msgstr "" + +#: ../java/src/org/klomp/snark/SnarkManager.java:1860 +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:1923 +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:1942 +msgid "Closing I2P tunnel after notifying trackers." +msgstr "" + +#: ../java/src/org/klomp/snark/TrackerClient.java:234 +#, 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 +msgid "Updating" +msgstr "" + +#: ../java/src/org/klomp/snark/UpdateRunner.java:114 +#, java-format +msgid "Updating from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:77 +#, java-format +msgid "Download torrent file from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:99 +#, java-format +msgid "Torrent was not retrieved from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:153 +#, java-format +msgid "Torrent fetched from {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:174 +#, java-format +msgid "Torrent already running: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:176 +#, java-format +msgid "Torrent already in the queue: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/FetchAndAdd.java:184 +#, 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 "I2PSnark - BitTorrent Client Anônimo" + +#: ../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 "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 +msgid "I2PSnark" +msgstr "I2PSnar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:287 +msgid "Refresh page" +msgstr "Recarregar página" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:295 +msgid "Forum" +msgstr "Fórum" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:308 +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 +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 +msgid "Status" +msgstr "Status" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:411 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:413 +msgid "Hide Peers" +msgstr "Ocultar Peers" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:423 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:425 +msgid "Show Peers" +msgstr "Mostrar Peers" + +#: ../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 +msgid "Torrent" +msgstr "Torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:442 +msgid "Estimated time remaining" +msgstr "Tempo restante estimado" + +#. 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 "Baixado" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:453 +msgid "RX" +msgstr "RX" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:458 +msgid "Uploaded" +msgstr "Uploaded" + +#. 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:467 +msgid "Down Rate" +msgstr "Taxa de down" + +#. 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 "Taxad de up" + +#. Translators: Please keep short or translate as " " +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:479 +msgid "TX Rate" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:494 +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:496 +msgid "Stop All" +msgstr "Parar todos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:508 +msgid "Start all stopped torrents" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:510 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:524 +msgid "Start All" +msgstr "Começar todos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:522 +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:548 +msgid "No torrents loaded." +msgstr "Nenhum torrent carregado." + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:554 +msgid "Totals" +msgstr "Totais" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:556 +#, 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-format +msgid "1 connected peer" +msgid_plural "{0} connected peers" +msgstr[0] "1 peer conectado" +msgstr[1] "{0} peers conectados" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:568 +#, java-format +msgid "1 DHT peer" +msgid_plural "{0} DHT peers" +msgstr[0] "" +msgstr[1] "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +msgid "First" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:604 +msgid "First page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +msgid "Prev" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:615 +msgid "Previous page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +msgid "Next" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:650 +msgid "Next page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +msgid "Last" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:660 +msgid "Last page" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:744 +#, 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:785 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:814 +#, java-format +msgid "Magnet deleted: {0}" +msgstr "Magnet deletado: {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 "Arquivo de torrent deletado: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:812 +#, java-format +msgid "Download deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:826 +#, java-format +msgid "Data file deleted: {0}" +msgstr "Arquivo de data deletado: {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:828 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:839 +#, 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:854 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:863 +#, java-format +msgid "Directory could not be deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:861 +#, java-format +msgid "Directory deleted: {0}" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:933 +msgid "Error - Cannot include alternate trackers without a primary tracker" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:946 +msgid "Error - Cannot mix private and public trackers in a torrent" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:966 +#, java-format +msgid "Torrent created for \"{0}\"" +msgstr "Torrent criado para \"{0}\"" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:968 +#, 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:970 +#, java-format +msgid "Error creating a torrent for \"{0}\"" +msgstr "Erro ao criar torrent para \"{0}\"" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:974 +#, 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:977 +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:1008 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2018 +msgid "Delete selected" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1008 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2019 +msgid "Save tracker configuration" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1025 +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 +msgid "Add tracker" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1077 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1080 +msgid "Enter valid tracker name and URLs" +msgstr "" + +#. "<input type=\"reset\" class=\"cancel\" +#. value=\"").append(_("Cancel")).append("\">\n" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1082 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2021 +msgid "Restore defaults" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1085 +msgid "Restored default trackers" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1206 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1207 +msgid "Checking" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1209 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1210 +msgid "Allocating" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1224 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1231 +msgid "Tracker Error" +msgstr "Erro de 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-format +msgid "1 peer" +msgid_plural "{0} peers" +msgstr[0] "1 peer" +msgstr[1] "{0} peers" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1234 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1235 +msgid "Starting" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1243 +msgid "Seeding" +msgstr "Seeding" + +#: ../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 +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 +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 +msgid "Stalled" +msgstr "Estagnado" + +#: ../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 +msgid "No Peers" +msgstr "Sem peers" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1295 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1296 +msgid "Stopped" +msgstr "Parad" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1329 +msgid "Torrent details" +msgstr "Detalhes do torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1358 +msgid "View files" +msgstr "Ver arquivos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1360 +msgid "Open file" +msgstr "Abrir arquivos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1402 +msgid "Stop the torrent" +msgstr "Parar o torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1404 +msgid "Stop" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1416 +msgid "Start the torrent" +msgstr "Começar o torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1418 +msgid "Start" +msgstr "Começar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1430 +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:1435 +#, 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 +msgid "Remove" +msgstr "Remover" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1450 +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:1455 +#, 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:1458 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1988 +msgid "Delete" +msgstr "Deletar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1493 +msgid "Unknown" +msgstr "desconhecido" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1505 +msgid "Seed" +msgstr "Seed" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1528 +msgid "Uninteresting (The peer has no pieces we need)" +msgstr "Desinteressante (O peer não tem as peças de interesse)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1530 +msgid "Choked (The peer is not allowing us to request pieces)" +msgstr "Engasgado (O peer não deixa solicitar as peças)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1550 +msgid "Uninterested (We have no pieces the peer needs)" +msgstr "Desinteressado (Peer não precisa das peças)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1552 +msgid "Choking (We are not allowing the peer to request pieces)" +msgstr "Engasgando (Peer está impossibilitado de solicitar peças)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1607 +#, java-format +msgid "Details at {0} tracker" +msgstr "Detalhes em tracker {0}" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1624 +msgid "Info" +msgstr "Info" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1675 +msgid "Add Torrent" +msgstr "Adicionar Torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1677 +msgid "From URL" +msgstr "Do URL" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1680 +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 +msgid "Add torrent" +msgstr "Acidionar torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1688 +#, 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:1690 +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:1713 +msgid "Create Torrent" +msgstr "Criar Torrent" + +#. out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" +#. value=\"" + newFile + "\" /><br>\n"); +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1716 +msgid "Data to seed" +msgstr "Arquivo para seed" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1720 +msgid "File or directory to seed (must be within the specified path)" +msgstr "Arquivo ou diretório para seed (deve ser dentro do caminho especificado)" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1722 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1966 +msgid "Trackers" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1724 +msgid "Primary" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1726 +msgid "Alternates" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1729 +msgid "Create torrent" +msgstr "Criar torrent" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1747 +msgid "none" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1780 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2033 +msgid "Configuration" +msgstr "Configuração" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1784 +msgid "Data directory" +msgstr "Diretório de arquivo" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1788 +msgid "Files readable by all" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1792 +msgid "If checked, other users may access the downloaded files" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1796 +msgid "Auto start" +msgstr "Autocomeçar" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1800 +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:1804 +msgid "Theme" +msgstr "Tema" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1817 +msgid "Refresh time" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1830 +msgid "Never" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1836 +msgid "Startup delay" +msgstr "Atraso de inicialização" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1838 +msgid "minutes" +msgstr "minutos" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1842 +msgid "Page size" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1844 +msgid "torrents" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1868 +msgid "Total uploader limit" +msgstr "Limite total do uploader" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1871 +msgid "peers" +msgstr "peers" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1875 +msgid "Up bandwidth limit" +msgstr "Up limite de banda larga" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1878 +msgid "Half available bandwidth recommended." +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1880 +msgid "View or change router bandwidth" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1884 +msgid "Use open trackers also" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1888 +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 +msgid "Enable DHT" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1896 +msgid "If checked, use DHT" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1912 +msgid "Inbound Settings" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1918 +msgid "Outbound Settings" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1926 +msgid "I2CP host" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1931 +msgid "I2CP port" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1946 +msgid "I2CP options" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1951 +msgid "Save configuration" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1971 +msgid "Name" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1973 +msgid "Website URL" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1975 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2517 +msgid "Open" +msgstr "Abrir" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1977 +msgid "Private" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:1979 +msgid "Announce URL" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2009 +msgid "Add" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2049 +#, java-format +msgid "Invalid magnet URL {0}" +msgstr "" + +#. * dummies for translation +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2057 +#, java-format +msgid "1 hop" +msgid_plural "{0} hops" +msgstr[0] "" +msgstr[1] "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2058 +#, java-format +msgid "1 tunnel" +msgid_plural "{0} tunnels" +msgstr[0] "" +msgstr[1] "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2265 +msgid "Torrent file" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2278 +msgid "Primary Tracker" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2287 +msgid "Tracker List" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2311 +msgid "Comment" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2320 +msgid "Created" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2330 +msgid "Created By" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2340 +msgid "Magnet link" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2347 +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 +msgid "Completion" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2374 +msgid "Remaining" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2381 +msgid "Files" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2386 +msgid "Pieces" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2390 +msgid "Piece size" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2413 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2417 +msgid "Directory" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2434 +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2436 +msgid "Priority" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2442 +msgid "Up to higher level directory" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2472 +msgid "Torrent not found?" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2480 +msgid "File not found in torrent?" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2493 +msgid "complete" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2494 +msgid "remaining" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2543 +msgid "High" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2548 +msgid "Normal" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2553 +msgid "Skip" +msgstr "" + +#: ../java/src/org/klomp/snark/web/I2PSnarkServlet.java:2562 +msgid "Save priorities" +msgstr "" diff --git a/apps/i2ptunnel/locale-proxy/messages_sk.po b/apps/i2ptunnel/locale-proxy/messages_sk.po new file mode 100644 index 0000000000..f3c8d651e1 --- /dev/null +++ b/apps/i2ptunnel/locale-proxy/messages_sk.po @@ -0,0 +1,455 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the i2ptunnel package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Roman 'Kaktuxista' Benji <romanbeno273@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-06 18:27+0000\n" +"PO-Revision-Date: 2014-05-19 19:29+0000\n" +"Last-Translator: Roman 'Kaktuxista' Benji <romanbeno273@gmail.com>\n" +"Language-Team: Slovak (http://www.transifex.com/projects/p/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/build/Proxy.java:5 ../java/build/Proxy.java:11 +msgid "Warning: Outproxy Not Found" +msgstr "" + +#: ../java/build/Proxy.java:6 ../java/build/Proxy.java:18 +#: ../java/build/Proxy.java:27 ../java/build/Proxy.java:40 +#: ../java/build/Proxy.java:49 ../java/build/Proxy.java:61 +#: ../java/build/Proxy.java:69 ../java/build/Proxy.java:78 +#: ../java/build/Proxy.java:93 ../java/build/Proxy.java:104 +#: ../java/build/Proxy.java:116 ../java/build/Proxy.java:126 +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:204 +msgid "Router Console" +msgstr "Konzola routra" + +#: ../java/build/Proxy.java:7 ../java/build/Proxy.java:19 +#: ../java/build/Proxy.java:28 ../java/build/Proxy.java:41 +#: ../java/build/Proxy.java:50 ../java/build/Proxy.java:62 +#: ../java/build/Proxy.java:70 ../java/build/Proxy.java:79 +#: ../java/build/Proxy.java:94 ../java/build/Proxy.java:105 +#: ../java/build/Proxy.java:117 ../java/build/Proxy.java:127 +msgid "I2P Router Console" +msgstr "Konzola I2P routra" + +#: ../java/build/Proxy.java:8 ../java/build/Proxy.java:20 +#: ../java/build/Proxy.java:29 ../java/build/Proxy.java:42 +#: ../java/build/Proxy.java:51 ../java/build/Proxy.java:63 +#: ../java/build/Proxy.java:71 ../java/build/Proxy.java:80 +#: ../java/build/Proxy.java:95 ../java/build/Proxy.java:106 +#: ../java/build/Proxy.java:118 ../java/build/Proxy.java:128 +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:205 +msgid "Configuration" +msgstr "Konfigurácia" + +#: ../java/build/Proxy.java:9 ../java/build/Proxy.java:21 +#: ../java/build/Proxy.java:30 ../java/build/Proxy.java:43 +#: ../java/build/Proxy.java:52 ../java/build/Proxy.java:64 +#: ../java/build/Proxy.java:72 ../java/build/Proxy.java:81 +#: ../java/build/Proxy.java:96 ../java/build/Proxy.java:107 +#: ../java/build/Proxy.java:119 ../java/build/Proxy.java:129 +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:205 +msgid "Help" +msgstr "Pomoc" + +#: ../java/build/Proxy.java:10 ../java/build/Proxy.java:22 +#: ../java/build/Proxy.java:31 ../java/build/Proxy.java:44 +#: ../java/build/Proxy.java:53 ../java/build/Proxy.java:65 +#: ../java/build/Proxy.java:73 ../java/build/Proxy.java:82 +#: ../java/build/Proxy.java:97 ../java/build/Proxy.java:108 +#: ../java/build/Proxy.java:120 ../java/build/Proxy.java:130 +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:205 +msgid "Addressbook" +msgstr "Adresár" + +#: ../java/build/Proxy.java:12 +msgid "The HTTP Outproxy was not found." +msgstr "" + +#: ../java/build/Proxy.java:13 +msgid "" +"It is offline, there is network congestion, or your router is not yet well-" +"integrated with peers." +msgstr "" + +#: ../java/build/Proxy.java:14 +#, java-format +msgid "" +"You may want to {0}retry{1} as this will randomly reselect an outproxy from " +"the pool you have defined {2}here{3} (if you have more than one configured)." +msgstr "" + +#: ../java/build/Proxy.java:15 +#, java-format +msgid "" +"If you continue to have trouble you may want to edit your outproxy list " +"{0}here{1}." +msgstr "" + +#: ../java/build/Proxy.java:16 ../java/build/Proxy.java:38 +#: ../java/build/Proxy.java:59 ../java/build/Proxy.java:102 +msgid "Could not find the following destination:" +msgstr "Nebolo možné nájsť nasledovnú destináciu:" + +#: ../java/build/Proxy.java:17 +msgid "Error: Request Denied" +msgstr "" + +#: ../java/build/Proxy.java:23 +msgid "Error: Local Access" +msgstr "" + +#: ../java/build/Proxy.java:24 +msgid "Your browser is misconfigured." +msgstr "" + +#: ../java/build/Proxy.java:25 +msgid "" +"Do not use the proxy to access the router console, localhost, or local LAN " +"destinations." +msgstr "" + +#: ../java/build/Proxy.java:26 +msgid "Warning: Eepsite Unknown" +msgstr "Varovanie: Neznáma eepsite" + +#: ../java/build/Proxy.java:32 +msgid "Warning: Eepsite Not Found in Addressbook" +msgstr "Varovanie: Eepsite nebola v adresári nájdená" + +#: ../java/build/Proxy.java:33 +msgid "The eepsite was not found in your router's addressbook." +msgstr "Daná eepsite nebola nájdená v adresári vášho routra." + +#: ../java/build/Proxy.java:34 +msgid "Check the link or find a Base 32 or Base 64 address." +msgstr "Skontrolujte daný odkaz, prípadne nájdite Base 32 alebo Base 64 adresu." + +#: ../java/build/Proxy.java:35 +#, java-format +msgid "If you have the Base 64 address, {0}add it to your addressbook{1}." +msgstr "Ak máte Base 64 adresu, {0}pridajte si ju do svojho adresára{1}." + +#: ../java/build/Proxy.java:36 +msgid "" +"Otherwise, find a Base 32 or address helper link, or use a jump service link" +" below." +msgstr "" + +#: ../java/build/Proxy.java:37 +#, java-format +msgid "" +"Seeing this page often? See {0}the FAQ{1} for help in {2}adding some " +"subscriptions{3} to your addressbook." +msgstr "" + +#: ../java/build/Proxy.java:39 ../java/build/Proxy.java:45 +msgid "Warning: Invalid Request URI" +msgstr "Varovanie: Neplatná URI požiadavku" + +#: ../java/build/Proxy.java:46 +msgid "The request URI is invalid, and probably contains illegal characters." +msgstr "URI požiadavku je neplatná a zrejme obsahuje nepovolené znaky." + +#: ../java/build/Proxy.java:47 +msgid "" +"If you clicked a link, check the end of the URI for any characters the " +"browser has mistakenly added on." +msgstr "Ak ste klikli na odkaz, skontrolujte koniec URI, či sa v ňom nenachádzajú nejaké znaky omylom pridané prehliadačom." + +#: ../java/build/Proxy.java:48 ../java/build/Proxy.java:54 +msgid "Warning: Invalid Destination" +msgstr "Varovanie: Neplatná destinácia" + +#: ../java/build/Proxy.java:55 +msgid "" +"The eepsite destination specified was not valid, or was otherwise " +"unreachable." +msgstr "Zadaná eepsite destinácia nebola platná, alebo sa ju iným spôsobom nepodarilo dosiahnuť." + +#: ../java/build/Proxy.java:56 +msgid "" +"Perhaps you pasted in the wrong Base 64 string or the link you are following" +" is bad." +msgstr "Možno ste vložili nesprávny Base 64 reťazec, prípadne odkaz, ktorý práve nasledujete, je zlý." + +#: ../java/build/Proxy.java:57 +msgid "The I2P host could also be offline." +msgstr "Takisto I2P hostiteľ mohol byť offline." + +#: ../java/build/Proxy.java:58 ../java/build/Proxy.java:101 +#, java-format +msgid "You may want to {0}retry{1}." +msgstr "Môžete to chcieť {0}skúsiť znova{1}." + +#: ../java/build/Proxy.java:60 ../java/build/Proxy.java:66 +msgid "Warning: Request Denied" +msgstr "Varovanie: Požiadavok bol odmietnutý" + +#: ../java/build/Proxy.java:67 +msgid "You attempted to connect to a non-I2P website or location." +msgstr "Pokúsili ste sa pripojiť k webovej stránke alebo lokácii mimo I2P." + +#: ../java/build/Proxy.java:68 ../java/build/Proxy.java:74 +msgid "Warning: No Outproxy Configured" +msgstr "Varovanie: Nie je nakonfigurovaný žiadny východzí proxy" + +#: ../java/build/Proxy.java:75 +msgid "" +"Your request was for a site outside of I2P, but you have no HTTP outproxy " +"configured." +msgstr "Váš požiadavok bol určený pre stránku mimo I2P, avšak nemáte nakonfigurovaný žiadny východzí proxy." + +#: ../java/build/Proxy.java:76 +msgid "Please configure an outproxy in I2PTunnel." +msgstr "Prosím nakonfigurujte si v I2PTunneli východzí proxy." + +#: ../java/build/Proxy.java:77 ../java/build/Proxy.java:83 +msgid "Warning: Destination Key Conflict" +msgstr "" + +#: ../java/build/Proxy.java:84 +msgid "" +"The addresshelper link you followed specifies a different destination key " +"than a host entry in your host database." +msgstr "" + +#: ../java/build/Proxy.java:85 +msgid "" +"Someone could be trying to impersonate another eepsite, or people have given" +" two eepsites identical names." +msgstr "" + +#: ../java/build/Proxy.java:86 +msgid "" +"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." +msgstr "" + +#: ../java/build/Proxy.java:87 +msgid "Proxy Authorization Required" +msgstr "Je vyžadovaná autorizácia proxy" + +#: ../java/build/Proxy.java:88 +msgid "I2P HTTP Proxy Authorization Required" +msgstr "Je vyžadovaná autorizácia I2P HTTP proxy" + +#: ../java/build/Proxy.java:89 +msgid "" +"This proxy is configured to require a username and password for access." +msgstr "Tento proxy je nakonfigurovaný tak, aby pre prístup vyžadoval uživateľské meno a heslo." + +#: ../java/build/Proxy.java:90 +#, java-format +msgid "" +"Please enter your username and password, or check your {0}router " +"configuration{1} or {2}I2PTunnel configuration{3}." +msgstr "Prosím zadajte vaše užívateľské meno a heslo, prípadne skontrolujte vašu {0}konfiguráciu routra{1} alebo {2}I2PTunnel konfiguráciu{3}." + +#: ../java/build/Proxy.java:91 +#, java-format +msgid "" +"To disable authorization, remove the configuration " +"{0}i2ptunnel.proxy.auth=basic{1}, then stop and restart the HTTP Proxy " +"tunnel." +msgstr "Ak chcete zakázať autorizáciu, odstráňte nastavenie {0}i2ptunnel.proxy.auth=basic{1} a následne zastavte a reštartujte HTTP Proxy tunel." + +#: ../java/build/Proxy.java:92 ../java/build/Proxy.java:98 +msgid "Warning: Eepsite Unreachable" +msgstr "" + +#: ../java/build/Proxy.java:99 +msgid "The eepsite was not reachable." +msgstr "" + +#: ../java/build/Proxy.java:100 +msgid "" +"The eepsite is offline, there is network congestion, or your router is not " +"yet well-integrated with peers." +msgstr "" + +#: ../java/build/Proxy.java:103 +msgid "Information: New Host Name" +msgstr "Informácia: Nový názov hostiteľa" + +#: ../java/build/Proxy.java:109 +msgid "Information: New Host Name with Address Helper" +msgstr "Informácia: Nový názov hostiteľa s adresným pomocníkom" + +#: ../java/build/Proxy.java:110 +msgid "" +"The address helper link you followed is for a new host name that is not in " +"your address book." +msgstr "Odkaz adresného pomocníka, ktorý ste nasledovali, je určený pre nový názov hostiteľa nenachádzajúceho sa vo vašom adresári." + +#: ../java/build/Proxy.java:111 +msgid "You may save this host name to your local address book." +msgstr "Môžete uložiť tento názov hostiteľa do lokálneho adresára." + +#: ../java/build/Proxy.java:112 +msgid "" +"If you save it to your address book, you will not see this message again." +msgstr "Ak ho uložíte do svojho adresára, už túto správu znova neuvidíte." + +#: ../java/build/Proxy.java:113 +msgid "" +"If you do not save it, the host name will be forgotten after the next router" +" restart." +msgstr "Ak ho neuložíte, názov hostiteľa bude po ďalšom reštarte routra zabudnutý." + +#: ../java/build/Proxy.java:114 +msgid "" +"If you do not wish to visit this host, click the \"back\" button on your " +"browser." +msgstr "Ak si neželáte navštíviť tohto hostiteľa, kliknite na tlačítko \"Späť\" vo vašom prehliadači." + +#: ../java/build/Proxy.java:115 ../java/build/Proxy.java:121 +msgid "Warning: Bad Address Helper" +msgstr "" + +#: ../java/build/Proxy.java:122 +#, java-format +msgid "The helper key in the URL ({0}i2paddresshelper={1}) is not resolvable." +msgstr "" + +#: ../java/build/Proxy.java:123 +msgid "It seems to be garbage data, or a mistyped Base 32 address." +msgstr "" + +#: ../java/build/Proxy.java:124 +msgid "" +"Check your URL to try and fix the helper key to be a valid Base 32 hostname " +"or Base 64 key." +msgstr "" + +#: ../java/build/Proxy.java:125 ../java/build/Proxy.java:131 +msgid "Warning: Non-HTTP Protocol" +msgstr "" + +#: ../java/build/Proxy.java:132 +msgid "The request uses a bad protocol." +msgstr "" + +#: ../java/build/Proxy.java:133 +msgid "The I2P HTTP Proxy supports HTTP and HTTPS requests only." +msgstr "" + +#: ../java/build/Proxy.java:134 +msgid "Other protocols such as FTP are not allowed." +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:595 +msgid "This seems to be a bad destination:" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:595 +msgid "i2paddresshelper cannot help you with a destination like that!" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:662 +#, java-format +msgid "" +"To visit the destination in your host database, click <a " +"href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, " +"click <a href=\"{1}\">here</a>." +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1151 +msgid "Host" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1155 +msgid "Base 32" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1159 +msgid "Destination" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1165 +#, java-format +msgid "Continue to {0} without saving" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1170 +#, java-format +msgid "Save {0} to router address book and continue to eepsite" +msgstr "" + +#. only blockfile supports multiple books +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1173 +#, java-format +msgid "Save {0} to master address book and continue to eepsite" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1174 +#, java-format +msgid "Save {0} to private address book and continue to eepsite" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1290 +msgid "HTTP Outproxy" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1326 +msgid "" +"Click a link below to look for an address helper by using a \"jump\" " +"service:" +msgstr "" + +#. Translators: parameter is a host name +#: ../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java:1334 +#, java-format +msgid "{0} jump service" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:162 +#, java-format +msgid "Added via address helper from {0}" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:164 +msgid "Added via address helper" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:187 +msgid "router" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:189 +msgid "master" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:191 +msgid "private" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:198 +#, java-format +msgid "Redirecting to {0}" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:210 +#, java-format +msgid "Saved {0} to the {1} addressbook, redirecting now." +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:211 +#, java-format +msgid "Failed to save {0} to the {1} addressbook, redirecting now." +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/localServer/LocalHTTPServer.java:213 +msgid "Click here if you are not redirected automatically." +msgstr "" diff --git a/apps/i2ptunnel/locale/messages_es b/apps/i2ptunnel/locale/messages_es new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/i2ptunnel/locale/messages_nn.po b/apps/i2ptunnel/locale/messages_nn.po new file mode 100644 index 0000000000..8f3d9aefe2 --- /dev/null +++ b/apps/i2ptunnel/locale/messages_nn.po @@ -0,0 +1,1180 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the i2ptunnel package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# <n414210@rtrtr.com>, 2012 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-06 18:27+0000\n" +"PO-Revision-Date: 2014-02-06 18:45+0000\n" +"Last-Translator: kytv <killyourtv@i2pmail.org>\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/projects/p/I2P/language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:363 +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:373 +msgid "internal" +msgstr "intern" + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:449 +#, java-format +msgid "{0} inbound, {0} outbound tunnel" +msgid_plural "{0} inbound, {0} outbound tunnels" +msgstr[0] "" +msgstr[1] "" + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:453 +msgid "lower bandwidth and reliability" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:455 +msgid "standard bandwidth and reliability" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:457 +msgid "higher bandwidth and reliability" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:123 +msgid "Tunnels are not initialized yet, please reload in two minutes." +msgstr "Tunellane har ikkje opna enno, ver venleg og last om att om to minutt." + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:196 +msgid "" +"Invalid form submission, probably because you used the 'back' or 'reload' " +"button on your browser. Please resubmit." +msgstr "Ugyldig skjemainnsending, sannsynlegvis fordi du brukte «tilbake»- eller «oppfrisk»-knappen på nettlesaren din. Ver venleg og send om att." + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:198 +msgid "" +"If the problem persists, verify that you have cookies enabled in your " +"browser." +msgstr "Sjekk at nettlesaren din har støtte for informasjonskapslar viss du enno har problem." + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:244 +msgid "Configuration reloaded for all tunnels" +msgstr "Konfigurasjon lasta om att for alle tunellar" + +#. and give them something to look at in any case +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:257 +msgid "Starting tunnel" +msgstr "Startar tunell" + +#. and give them something to look at in any case +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:270 +msgid "Stopping tunnel" +msgstr "Stoppar tunell" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:336 +msgid "Configuration changes saved" +msgstr "Konfigurasjonsendringar lagra" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:339 +msgid "Failed to save configuration" +msgstr "Klarte ikkje å lagra konfigurasjonen" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:461 +msgid "New Tunnel" +msgstr "Ny tunell" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:484 +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:494 +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:611 +msgid "Port not set" +msgstr "Port ikkje stilt inn" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:487 +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:613 +msgid "Invalid port" +msgstr "Ugyldig port" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:490 +msgid "Warning - ports less than 1024 are not recommended" +msgstr "Åtvaring – portar under 1024 er ikkje tilrådd" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:506 +msgid "Standard client" +msgstr "Standardklient" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:507 +msgid "HTTP/HTTPS client" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:508 +msgid "IRC client" +msgstr "IRC-klient" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:509 +msgid "Standard server" +msgstr "Standardtenar" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:510 +msgid "HTTP server" +msgstr "HTTP-tenar" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:511 +msgid "SOCKS 4/4a/5 proxy" +msgstr "SOCKS 4/4a/5-mellomtenar" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:512 +msgid "SOCKS IRC proxy" +msgstr "SOCKS IRC-mellomtenar" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:513 +msgid "CONNECT/SSL/HTTPS proxy" +msgstr "CONNECT/SSL/HTTPS-mellomtenar" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:514 +msgid "IRC server" +msgstr "IRC-tenar" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:515 +msgid "Streamr client" +msgstr "Streamr-klient" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:516 +msgid "Streamr server" +msgstr "Streamr-tenar" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:517 +msgid "HTTP bidir" +msgstr "HTTP tovegs" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:605 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:313 +msgid "Host not set" +msgstr "Tenar ikkje stilt inn" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:607 +msgid "Invalid address" +msgstr "Ugyldig adresse" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:82 +msgid "I2P Tunnel Manager - Edit Client Tunnel" +msgstr "I2p tunellhandterar – rediger klienttunell" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:110 +msgid "Edit proxy settings" +msgstr "Rediger mellomtenarinnstillingar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:118 +msgid "New proxy settings" +msgstr "Nye mellomtenarinnstillingar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:129 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:129 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:126 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:140 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:271 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:286 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:326 +msgid "Name" +msgstr "Namn" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:133 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:133 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:275 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:302 +msgid "Type" +msgstr "Type" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:137 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:137 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:255 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:422 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:330 +msgid "Description" +msgstr "Skildring" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:143 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:153 +msgid "Target" +msgstr "Mål" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:147 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:149 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:186 +msgid "Access Point" +msgstr "Tilgangspunkt" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:154 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:167 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:223 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:170 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:191 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:236 +msgid "required" +msgstr "kravd" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:175 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:201 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:482 +msgid "Reachable by" +msgstr "Kan nåast frå" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:196 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:358 +msgid "Outproxies" +msgstr "Ut-mellomtenarar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:203 +msgid "SSL Outproxies" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:209 +msgid "Use Outproxy Plugin" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:213 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:251 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:259 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:145 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:526 +msgid "(Check the Box for 'YES')" +msgstr "(Huk av for «JA»)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:218 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:378 +msgid "Tunnel Destination" +msgstr "Tunellmålside" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:230 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:382 +msgid "name, name:port, or destination" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:233 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:386 +msgid "b32 not recommended" +msgstr "b32 ikkje tilrådd" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239 +msgid "Shared Client" +msgstr "Delt klient" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:243 +msgid "" +"(Share tunnels with other clients and irc/httpclients? Change requires " +"restart of client proxy)" +msgstr "(Del tunellar med andre klientar og irc-/http-klientar? Endringa krev omstart av klientmellomtenaren.)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:247 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:141 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:522 +msgid "Auto Start" +msgstr "Autostart" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:255 +msgid "Enable DCC" +msgstr "Skru på DCC" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:263 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:266 +msgid "Advanced networking options" +msgstr "Avanserte nettverksval" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:265 +msgid "" +"(NOTE: when this client proxy is configured to share tunnels, then these " +"options are for all the shared proxy clients!)" +msgstr "(MERK: Når denne klientmellomtenaren er konfigurert for å dela tunellar, gjeld vala for alle dei delte mellomtenarklientane!)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:267 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:268 +msgid "Tunnel Options" +msgstr "Tunellval" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:269 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:270 +msgid "Length" +msgstr "Lengd" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:276 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:277 +msgid "0 hop tunnel (no anonymity)" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:280 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281 +msgid "1 hop tunnel (low anonymity)" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:284 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:285 +msgid "2 hop tunnel (medium anonymity)" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:288 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:289 +msgid "3 hop tunnel (high anonymity)" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:296 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:297 +msgid "hop tunnel (very poor performance)" +msgstr "hoppstunell (veldig dårleg yting)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:301 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:302 +msgid "Variance" +msgstr "Varians" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:308 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:309 +msgid "0 hop variance (no randomisation, consistant performance)" +msgstr "Varians på 0 hopp (ingen randomisering, konstant yting)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:312 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:313 +msgid "" +"+ 0-1 hop variance (medium additive randomisation, subtractive performance)" +msgstr "+ Varians på 0-1 hopp (middels aukande randomisering, minkande yting)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:316 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:317 +msgid "" +"+ 0-2 hop variance (high additive randomisation, subtractive performance)" +msgstr "+ Varians på 0-2 hopp (høg aukande randomisering, minkande yting)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:320 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:321 +msgid "+/- 0-1 hop variance (standard randomisation, standard performance)" +msgstr "+/- Varians på 0-1 hopp (vanleg randomisering, vanleg yting)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:324 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:325 +msgid "+/- 0-2 hop variance (not recommended)" +msgstr "+/- Varians på 0-2 hopp (ikkje tilrådd)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:335 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:336 +msgid "hop variance" +msgstr "hoppsvarians" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:340 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:341 +msgid "Count" +msgstr "Tal" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:344 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:345 +msgid "Backup Count" +msgstr "Ekstra" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:351 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:352 +msgid "0 backup tunnels (0 redundancy, no added resource usage)" +msgstr "0 ekstratunellar (0 redundans, ikkje meir ressursbruk)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:355 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:356 +msgid "1 backup tunnel each direction (low redundancy, low resource usage)" +msgstr "1 ekstratunell kvar veg (låg redundans, låg ressursbruk)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:359 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:360 +msgid "" +"2 backup tunnels each direction (medium redundancy, medium resource usage)" +msgstr "2 ekstratunellar kvar veg (middels redundans, middels ressursbruk)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:363 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:364 +msgid "3 backup tunnels each direction (high redundancy, high resource usage)" +msgstr "3 ekstratunellar kvar veg (høg redundans, høg ressursbruk)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:371 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:372 +msgid "backup tunnels" +msgstr "ekstratunellar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:378 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:379 +msgid "Profile" +msgstr "Profil" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:385 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:386 +msgid "interactive connection" +msgstr "interaktiv tilkopling" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:389 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:390 +msgid "bulk connection (downloads/websites/BT)" +msgstr "massetilkopling (nedlastingar/nettsider/BT)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:391 +msgid "Delay Connect" +msgstr "Forseink tilkopling" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:395 +msgid "for request/response connections" +msgstr "for førespurnad-/respons-tilkoplingar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:399 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:394 +msgid "Router I2CP Address" +msgstr "I2CP-adresse til ruteren" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:401 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:159 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:396 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:413 +msgid "Host" +msgstr "Tenar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:409 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:165 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:404 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:273 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:295 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:434 +msgid "Port" +msgstr "Port" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:419 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:502 +msgid "Reduce tunnel quantity when idle" +msgstr "Reduser tunellkvantitet når inaktiv" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:421 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:435 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:443 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:455 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:465 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:493 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:503 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:414 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:504 +msgid "Enable" +msgstr "Skru på" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:425 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:508 +msgid "Reduced tunnel count" +msgstr "Reduser tunnelmengd" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:429 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:449 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:512 +msgid "Idle minutes" +msgstr "Minutt inaktiv" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:433 +msgid "Close tunnels when idle" +msgstr "Lukk tunellar når inaktiv" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:439 +msgid "New Keys on Reopen" +msgstr "Nye nøklar ved gjenopning" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:447 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:430 +msgid "Disable" +msgstr "Skru av" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:453 +msgid "Delay tunnel open until required" +msgstr "Vent med tunellopning til det trengst" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:463 +msgid "Persistent private key" +msgstr "Varig privat nøkkel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:469 +msgid "File" +msgstr "Fil" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:478 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:243 +msgid "Local destination" +msgstr "Lokal målside" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:482 +msgid "Local Base 32" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:491 +msgid "Local Authorization" +msgstr "Lokal autorisering" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:497 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:507 +msgid "Username" +msgstr "Brukarnamn" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:499 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:511 +msgid "Password" +msgstr "Passord" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:501 +msgid "Outproxy Authorization" +msgstr "Autorisering av ut-mellomtenar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:518 +msgid "Jump URL List" +msgstr "URL-liste over vidaresendingstenester" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:524 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:548 +msgid "Custom options" +msgstr "Eigne val" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:528 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:552 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:702 +msgid "Cancel" +msgstr "Avbryt" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:532 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:556 +msgid "Delete" +msgstr "Slett" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:534 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:558 +msgid "Save" +msgstr "Lagra" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:82 +msgid "I2P Tunnel Manager - Edit Server Tunnel" +msgstr "I2P tunellhandterar – rediger tenartunell" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:110 +msgid "Edit server settings" +msgstr "Rediger tenarinnstillingar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:118 +msgid "New server settings" +msgstr "Nye tenarinnstillingar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:179 +msgid "Use SSL?" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:222 +msgid "Website name" +msgstr "Namn på nettstad" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:226 +msgid "(leave blank for outproxies)" +msgstr "(blank for ut-mellomtenarar)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:231 +msgid "Private key file" +msgstr "Privat nøkkelfil" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:253 +msgid "Add to local addressbook" +msgstr "Legg til i lokal adressebok" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:260 +msgid "Hostname Signature" +msgstr "Signatur på tenarnamn" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:412 +msgid "Encrypt Leaseset" +msgstr "Krypter «leaseset» (tunellinngangar)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:418 +msgid "Encryption Key" +msgstr "Krypteringsnøkkel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:422 +msgid "Generate New Key" +msgstr "Opprett ny nøkkel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:424 +msgid "Generate" +msgstr "Opprett" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:426 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:546 +msgid "(Tunnel must be stopped first)" +msgstr "(Tunellen må stoppast først)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:428 +msgid "Restricted Access List" +msgstr "Avgrensa tilgangsliste" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:434 +msgid "Whitelist" +msgstr "Kviteliste" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:438 +msgid "Blacklist" +msgstr "Svarteliste" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:442 +msgid "Access List" +msgstr "Tilgangsliste" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:446 +msgid "Inbound connection limits (0=unlimited)" +msgstr "Inn-tilkoplingsgrense (0=inga grense)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:448 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:479 +msgid "Per client" +msgstr "Per klient" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:450 +msgid "Per minute" +msgstr "Per minutt" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:454 +msgid "Per hour" +msgstr "Per time" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:458 +msgid "Per day" +msgstr "Per dag" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:462 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:489 +msgid "Total" +msgstr "I alt" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:470 +msgid "Max concurrent connections (0=unlimited)" +msgstr "Maks samtidige tilkoplingar (0=inga grense)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:477 +msgid "POST limits (0=unlimited)" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:481 +msgid "Per period" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:485 +msgid "Ban minutes" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:495 +msgid "POST limit period (minutes)" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:516 +msgid "New Certificate type" +msgstr "Ny sertifikattype" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:518 +msgid "None" +msgstr "Ingen" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:522 +msgid "Hashcash (effort)" +msgstr "Hashcash (arbeidsmengd)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:528 +msgid "Hashcash Calc Time" +msgstr "Hashcash kalkuleringstid" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:530 +msgid "Estimate" +msgstr "Estimat" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:532 +msgid "Hidden" +msgstr "Skjult" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:536 +msgid "Signed (signed by)" +msgstr "Signert (signert av)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:542 +msgid "Modify Certificate" +msgstr "Endra sertifikat" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:544 +msgid "Modify" +msgstr "Endra" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:83 +msgid "I2P Tunnel Manager - List" +msgstr "I2P tunellhandterar – liste" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:97 +msgid "Status Messages" +msgstr "Statusmeldingar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:101 +msgid "Refresh" +msgstr "Oppfrisk" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:109 +msgid "Tunnel Wizard" +msgstr "Tunellvegvisar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:113 +msgid "Stop All" +msgstr "Stopp alle" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:117 +msgid "Start All" +msgstr "Start alle" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:121 +msgid "Restart All" +msgstr "Omstart alle" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:124 +msgid "I2P Server Tunnels" +msgstr "I2P tenartunellar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:128 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:149 +msgid "Points at" +msgstr "Peker på" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:130 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:182 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:186 +msgid "Preview" +msgstr "Førehandsvis" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:132 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:206 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:279 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:320 +msgid "Status" +msgstr "Status" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:192 +msgid "Base32 Address" +msgstr "Base32-adresse" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:200 +msgid "No Preview" +msgstr "Inga førehandsvising" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:213 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:327 +msgid "Starting..." +msgstr "Startar …" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:220 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:234 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:334 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:348 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:362 +msgid "Stop" +msgstr "Stopp" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:227 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:355 +msgid "Running" +msgstr "Køyrer" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:241 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:369 +msgid "Stopped" +msgstr "Stoppa" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:248 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:376 +msgid "Start" +msgstr "Start" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:263 +msgid "New server tunnel" +msgstr "Ny tenartunell" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:265 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:432 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:223 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:265 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:295 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:301 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:576 +msgid "Standard" +msgstr "Standard" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:267 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:434 +msgid "Create" +msgstr "Opprett" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:269 +msgid "I2P Client Tunnels" +msgstr "I2P klienttunellar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:277 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:306 +msgid "Interface" +msgstr "Grensesnitt" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:341 +msgid "Standby" +msgstr "Ventemodus" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:385 +msgid "Outproxy" +msgstr "Ut-mellomtenar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:388 +msgid "Destination" +msgstr "Målside" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:395 +msgid "internal plugin" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:414 +msgid "none" +msgstr "ingen" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:430 +msgid "New client tunnel" +msgstr "Ny klienttunell" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:119 +msgid "I2P Tunnel Manager - Tunnel Creation Wizard" +msgstr "I2P tunellhandterar – vegvisar for tunelloppretting" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:139 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:567 +msgid "Server or client tunnel?" +msgstr "Tenar- eller klienttunell?" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:145 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:571 +msgid "Tunnel type" +msgstr "Tunelltype" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:151 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:601 +msgid "Tunnel name and description" +msgstr "Tunellnamn og -skildring" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:157 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:610 +msgid "Tunnel destination" +msgstr "Tunellmålside" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:163 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:626 +msgid "Binding address and port" +msgstr "Bindingsadresse og -port" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:169 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:652 +msgid "Tunnel auto-start" +msgstr "Auto-start tunell" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:175 +msgid "Wizard completed" +msgstr "Vegvisar fullført" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:189 +msgid "" +"This wizard will take you through the various options available for creating" +" tunnels in I2P." +msgstr "Denne vegvisaren tek deg gjennom dei ulike tilgjengelege vala for å oppretta tunellar i I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:191 +msgid "" +"The first thing to decide is whether you want to create a server or a client" +" tunnel." +msgstr "Det første du må avgjera er om du ønskjer ein tenar- eller klienttunell." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:193 +msgid "" +"If you need to connect to a remote service, such as an IRC server inside I2P" +" or a code repository, then you will require a CLIENT tunnel." +msgstr "Viss du må kopla til ei ekstern teneste, t.d. ein IRC-tenar i I2P eller eit kodelager, så treng du ein KLIENT-tunell." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:195 +msgid "" +"On the other hand, if you wish to host a service for others to connect to " +"you'll need to create a SERVER tunnel." +msgstr "Viss du derimot ønskjer å ha ei teneste som andre koplar seg opp mot, så treng du ein TENAR-tunell." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:197 +msgid "Server Tunnel" +msgstr "Tenartunell" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:199 +msgid "Client Tunnel" +msgstr "Klienttunell" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:217 +msgid "There are several types of tunnels to choose from:" +msgstr "Det finst fleire typar tunellar å velja mellom:" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:225 +msgid "Basic tunnel for connecting to a single service inside I2P." +msgstr "Standardtunell for å kopla til ei einskild teneste i I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:227 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:269 +msgid "" +"Try this if none of the tunnel types below fit your requirements, or you " +"don't know what type of tunnel you need." +msgstr "Prøv denne viss ingen av tunelltypane under passar, eller viss du ikkje veit kva for tunell du treng." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:229 +msgid "Tunnel that acts as an HTTP proxy for reaching eepsites inside I2P." +msgstr "Tunell som fungerer som ein HTTP-mellomtenar for å nå eepsider i I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:231 +msgid "" +"Set your browser to use this tunnel as an http proxy, or set your " +"\"http_proxy\" environment variable for command-line applications in " +"GNU/Linux." +msgstr "La nettlesaren din brukar denne tunellen som ein HTTP-mellomtenar, eller still inn miljøvariabelen «http_proxy» for kommandolinjeprogram i GNU/Linux." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:233 +msgid "" +"Websites outside I2P can also be reached if an HTTP proxy within I2P is " +"known." +msgstr "Du kan òg nå nettsider utanfor I2P om du har ein kjend HTTP-mellomtenar i I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:235 +msgid "Customised client tunnel specific for IRC connections." +msgstr "Klienttunell spesielt innstilt for IRC-tilkoplingar." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:237 +msgid "" +"With this tunnel type, your IRC client will be able to connect to an IRC " +"network inside I2P." +msgstr "Med denne tunelltypen vil IRC-klienten din kunna kopla til eit IRC-nettverk inni I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:239 +msgid "" +"Each IRC network in I2P that you wish to connect to will require its own " +"tunnel. (See Also, SOCKS IRC)" +msgstr "Kvart IRC-nettverk i I2P som du ønskjer å kopla til må ha sin eigen tunell. (Sjå òg SOCKS IRC.)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:241 +msgid "A tunnel that implements the SOCKS protocol." +msgstr "Ein tunell som implementerer SOCKS-protokollen." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:243 +msgid "" +"This enables both TCP and UDP connections to be made through a SOCKS " +"outproxy within I2P." +msgstr "Dette gjer det moleg å oppretta både TCP- og UDP-tilkoplingar gjennom ein SOCKS-basert ut-mellomtenar inni I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:245 +msgid "" +"A client tunnel implementing the SOCKS protocol, which is customised for " +"connecting to IRC networks." +msgstr "Ein klienttunell som implementerer SOCKS-protokollen, som i tillegg er spesielt innstilt for IRC-nettverk." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:247 +msgid "" +"With this tunnel type, IRC networks in I2P can be reached by typing the I2P " +"address into your IRC client, and configuring the IRC client to use this " +"SOCKS tunnel." +msgstr "Med denne tunelltypen kan du nå IRC-nettverk inni I2P ved å skriva I2P-adressa i IRC-klienten og konfigurera IRC-klienten til å bruka denne SOCKS-tunellen." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:249 +msgid "" +"This means that only one I2P tunnel is required rather than a separate " +"tunnel per IRC network." +msgstr "Dette vil seia at du berre treng éin I2P-tunell totalt, i staden for éin tunell per IRC-nettverk." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:251 +msgid "" +"IRC networks outside I2P can also be reached if a SOCKS outproxy within I2P " +"is known, though it depends on whether or not the outproxy has been blocked " +"by the IRC network." +msgstr "Du kan òg nå IRC-nettverk utanfor I2P viss du kjenner til ein SOCKS-basert ut-mellomtenar inni I2P, men det avheng av at ikkje ut-mellomtenaren er blokkert av IRC-nettverket." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:253 +msgid "A client tunnel that implements the HTTP CONNECT command." +msgstr "Ein klienttunell som implementerer HTTP CONNECT-kommandoen." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:255 +msgid "" +"This enables TCP connections to be made through an HTTP outproxy, assuming " +"the proxy supports the CONNECT command." +msgstr "Dette gjer det mogleg å oppretta TCP-tilkoplingar gjennom ein HTTP-basert ut-mellomtenar, dersom mellomtenaren støtter CONNECT-kommandoen." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:257 +msgid "A customised client tunnel for Streamr." +msgstr "Ein klienttunell spesielt innstilt for Streamr." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:267 +msgid "A basic server tunnel for hosting a generic service inside I2P." +msgstr "Ein enkel tenartunell for generelle tenester inni I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:271 +msgid "A server tunnel that is customised for HTTP connections." +msgstr "Ein tenartunell som er spesielt innstilt for HTTP-tilkoplingar." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:273 +msgid "Use this tunnel type if you want to host an eepsite." +msgstr "Bruk denne tunelltypen viss du vil ha ei eepside." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:275 +msgid "" +"A customised server tunnel that can both serve HTTP data and connect to " +"other server tunnels." +msgstr "Ein tenartunell som kan både servera HTTP-data og kopla til andre tenartunellar." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:277 +msgid "This tunnel type is predominantly used when running a Seedless server." +msgstr "Denne tunelltypen er hovudsakleg nytta under køyring av ein Seedless-tenar." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:279 +msgid "A customised server tunnel for hosting IRC networks inside I2P." +msgstr "Ein tenartunell for å ha IRC-nettverk inni I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:281 +msgid "" +"Usually, a separate tunnel needs to be created for each IRC server that is " +"to be accessible inside I2P." +msgstr "Vanlegvis må du oppretta éin separat tunell for kvar IRC-tenar som skal vera tilgjengeleg inni I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:283 +msgid "A customised server tunnel for Streamr." +msgstr "Ein tenartunell som er spesielt innstilt for Streamr." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:322 +msgid "Choose a name and description for your tunnel." +msgstr "Vel eit namn og ei skildring av tunnelen" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:324 +msgid "" +"These can be anything you want - they are just for ease of identifying the " +"tunnel in the routerconsole." +msgstr "Dette kan vera kva som helst – det er berre for å gjera det enkelt for deg å identifisera tunellen i ruterkonsollen." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:354 +msgid "" +"If you know of any outproxies for this type of tunnel (either HTTP or " +"SOCKS), fill them in below." +msgstr "Fyll inn nedanfor viss du kjenner til utmellomtenarar for denne tunelltypen (anten HTTP eller SOCKS)." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:356 +msgid "Separate multiple proxies with commas." +msgstr "Nytt komma til å skilja mellomtenarar frå kvarandre." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:374 +msgid "" +"Type in the I2P destination of the service that this client tunnel should " +"connect to." +msgstr "Skriv inn I2P-målet til tenesten som denne klienttunellen skal kopla til." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:376 +msgid "" +"This could be the full base 64 destination key, or an I2P URL from your " +"address book." +msgstr "Dette kan vera den fulle målnøkkelen i base 64, eller ein I2P-URL frå adresseboka di." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:409 +msgid "" +"This is the IP that your service is running on, this is usually on the same " +"machine so 127.0.0.1 is autofilled." +msgstr "Dette er IP-adressa som tenesta di køyrer på. Dette er vanlegvis den same maskinen, så 127.0.0.1 er fylt inn på førehand." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:432 +msgid "This is the port that the service is accepting connections on." +msgstr "Dette er porten som tenesta tek i mot tilkoplingar på." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:453 +msgid "This is the port that the client tunnel will be accessed from locally." +msgstr "Dette er porten som du koplar til klienttunellen lokalt med." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:455 +msgid "This is also the client port for the HTTPBidir server tunnel." +msgstr "Dette er òg klientporten for HTTPBidir-tenartunellen." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:474 +msgid "" +"How do you want this tunnel to be accessed? By just this machine, your " +"entire subnet, or external internet?" +msgstr "Kor vil du tillata at denne tunellen skal få tilgang frå? Berre denne maskinen, heile subnettet ditt, eller eksternt frå internett?" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:476 +msgid "You will most likely want to just allow 127.0.0.1" +msgstr "Du vil sannsynlegvis berre tillata 127.0.0.1" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:518 +msgid "" +"The I2P router can automatically start this tunnel for you when the router " +"is started." +msgstr "I2P-ruteren kan automatisk starta denne tunellen for deg når ruteren startar." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:520 +msgid "" +"This can be useful for frequently-used tunnels (especially server tunnels), " +"but for tunnels that are only used occassionally it would mean that the I2P " +"router is creating and maintaining unnecessary tunnels." +msgstr "Dette kan vera nyttig for tunellar du nyttar ofte (spesielt tenartunellar). For tunellar som berre blir nytta av og til vil det tyda at I2P-ruteren opprettar og vedlikehaldar tunellar du ikkje treng." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:546 +msgid "The wizard has now collected enough information to create your tunnel." +msgstr "Vegvisaren har no samla inn nok informasjon for å oppretta tunellen din." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:548 +msgid "" +"Upon clicking the Save button below, the wizard will set up the tunnel, and " +"take you back to the main I2PTunnel page." +msgstr "Når du klikkar Lagra under vil vegvisaren oppretta tunellen og senda deg tilbake til hovudsida for I2P-tunellar." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:553 +msgid "" +"Because you chose to automatically start the tunnel when the router starts, " +"you don't have to do anything further." +msgstr "Sidan du valte å starta tunellen automatisk når ruteren startar treng du ikkje gjera noko meir." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:555 +msgid "The router will start the tunnel once it has been set up." +msgstr "Ruteren vil starta tunellen ved oppstart." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:559 +msgid "" +"Because you chose not to automatically start the tunnel, you will have to " +"manually start it." +msgstr "Fordi du valte å ikkje starta tunellen automatisk må du starta han for hand." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:561 +msgid "" +"You can do this by clicking the Start button on the main page which " +"corresponds to the new tunnel." +msgstr "Du kan gjera dette ved å klikka Start-knappen på hovudsida som samsvarer med den nye tunellen." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:565 +msgid "Below is a summary of the options you chose:" +msgstr "Nedanfor er ei oppsummering av vala dine:" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:663 +msgid "" +"Alongside these basic settings, there are a number of advanced options for " +"tunnel configuration." +msgstr "I tillegg til desse grunnleggande innstillingane finst ei rekkje avanserte val for tunellkonfigurasjon." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:665 +msgid "" +"The wizard will set reasonably sensible default values for these, but you " +"can view and/or edit these by clicking on the tunnel's name in the main " +"I2PTunnel page." +msgstr "Vegvisaren vil velja fornuftige standardverdiar for desse, men du kan visa og/eller redigera desse ved å klikka på tunellnamnet i hovudsida for I2P-tunnellar." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:707 +msgid "Previous" +msgstr "Førre" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:715 +msgid "Save Tunnel" +msgstr "Lagra tunell" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:721 +msgid "Finish" +msgstr "Avslutt" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:727 +msgid "Next" +msgstr "Neste" diff --git a/apps/i2ptunnel/locale/messages_ro.po b/apps/i2ptunnel/locale/messages_ro.po new file mode 100644 index 0000000000..32dad11e81 --- /dev/null +++ b/apps/i2ptunnel/locale/messages_ro.po @@ -0,0 +1,1180 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the i2ptunnel package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-06 18:27+0000\n" +"PO-Revision-Date: 2014-02-06 18:45+0000\n" +"Last-Translator: kytv <killyourtv@i2pmail.org>\n" +"Language-Team: Romanian (http://www.transifex.com/projects/p/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/net/i2p/i2ptunnel/web/EditBean.java:363 +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:373 +msgid "internal" +msgstr "Intern" + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:449 +#, java-format +msgid "{0} inbound, {0} outbound tunnel" +msgid_plural "{0} inbound, {0} outbound tunnels" +msgstr[0] "{0} de intrare, {0} tuneluri de ieșire " +msgstr[1] "{0} de intrare, {0} tuneluri de ieșire" +msgstr[2] "{0} de intrare, {0} tuneluri de ieșire" + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:453 +msgid "lower bandwidth and reliability" +msgstr "lățime de bandă și fiabilitate joasa" + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:455 +msgid "standard bandwidth and reliability" +msgstr "lățime de bandă și fiabilitate standarda," + +#: ../java/src/net/i2p/i2ptunnel/web/EditBean.java:457 +msgid "higher bandwidth and reliability" +msgstr "lățime de bandă și fiabilitate inalta," + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:123 +msgid "Tunnels are not initialized yet, please reload in two minutes." +msgstr "Tuneluri încă nu sunt inițializate , vă rugăm să reîncărcați în două minute." + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:196 +msgid "" +"Invalid form submission, probably because you used the 'back' or 'reload' " +"button on your browser. Please resubmit." +msgstr "Transmiterea formularului invalid, probabil pentru că ați folosit butonul \"reload\" sau \"inapoi\" din browser-ul dumneavoastră. Vă rugăm retrimiteți." + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:198 +msgid "" +"If the problem persists, verify that you have cookies enabled in your " +"browser." +msgstr "Dacă problema persistă, verificați dacă aveți activate cookie-urile în browser-ul dumneavoastră." + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:244 +msgid "Configuration reloaded for all tunnels" +msgstr "Configurare reîncărcata pentru toate tunelurile" + +#. and give them something to look at in any case +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:257 +msgid "Starting tunnel" +msgstr "Pornirea tunelului" + +#. and give them something to look at in any case +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:270 +msgid "Stopping tunnel" +msgstr "Oprirea tunelului" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:336 +msgid "Configuration changes saved" +msgstr "Schimbarea configuraţiei salvat" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:339 +msgid "Failed to save configuration" +msgstr "Eșec la salvarea configurației" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:461 +msgid "New Tunnel" +msgstr "Tunel nou" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:484 +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:494 +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:611 +msgid "Port not set" +msgstr "Portul nu este setat" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:487 +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:613 +msgid "Invalid port" +msgstr "Port incorect" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:490 +msgid "Warning - ports less than 1024 are not recommended" +msgstr "Atenție - nu sunt recomandate porturi mai mici de 1024" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:506 +msgid "Standard client" +msgstr "Client standart" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:507 +msgid "HTTP/HTTPS client" +msgstr "" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:508 +msgid "IRC client" +msgstr "Client IRC" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:509 +msgid "Standard server" +msgstr "Server standard" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:510 +msgid "HTTP server" +msgstr "Server HTTP" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:511 +msgid "SOCKS 4/4a/5 proxy" +msgstr "SOCKS 4/4a/5 proxy" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:512 +msgid "SOCKS IRC proxy" +msgstr "SOCKS IRC proxy" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:513 +msgid "CONNECT/SSL/HTTPS proxy" +msgstr "CONNECTEAZA/SSL/HTTPS proxy" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:514 +msgid "IRC server" +msgstr "Server IRC" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:515 +msgid "Streamr client" +msgstr "Client Streamr" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:516 +msgid "Streamr server" +msgstr "Server streamr" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:517 +msgid "HTTP bidir" +msgstr "HTTP bidir" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:605 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:313 +msgid "Host not set" +msgstr "Gazdă nu este setata" + +#: ../java/src/net/i2p/i2ptunnel/web/IndexBean.java:607 +msgid "Invalid address" +msgstr "Adresă nevalidă" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:82 +msgid "I2P Tunnel Manager - Edit Client Tunnel" +msgstr "I2P Tunnel manager - Editare Client Tunnel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:110 +msgid "Edit proxy settings" +msgstr "Editați setările proxy" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:118 +msgid "New proxy settings" +msgstr "Opțiuni proxy noi" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:129 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:129 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:126 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:140 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:271 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:286 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:326 +msgid "Name" +msgstr "Nume" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:133 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:133 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:275 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:302 +msgid "Type" +msgstr "Tip" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:137 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:137 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:255 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:422 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:330 +msgid "Description" +msgstr "Descriere" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:143 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:153 +msgid "Target" +msgstr "Destinație" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:147 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:149 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:186 +msgid "Access Point" +msgstr "Punct de acces" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:154 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:167 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:223 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:170 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:191 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:236 +msgid "required" +msgstr "necesar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:175 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:201 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:482 +msgid "Reachable by" +msgstr "accesibil cu" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:196 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:358 +msgid "Outproxies" +msgstr "Outproxy" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:203 +msgid "SSL Outproxies" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:209 +msgid "Use Outproxy Plugin" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:213 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:251 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:259 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:145 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:526 +msgid "(Check the Box for 'YES')" +msgstr "(Bifați căsuța pentru \"DA\")" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:218 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:378 +msgid "Tunnel Destination" +msgstr "destinație tunel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:230 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:382 +msgid "name, name:port, or destination" +msgstr "nume, nume: port, sau destinație" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:233 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:386 +msgid "b32 not recommended" +msgstr "B32 nu este recomandat" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:239 +msgid "Shared Client" +msgstr "client comun" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:243 +msgid "" +"(Share tunnels with other clients and irc/httpclients? Change requires " +"restart of client proxy)" +msgstr "(Cota de tuneluri cu alți clienți și irc / httpclients? Schimbarea necesită repornirea de proxy client)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:247 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:141 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:522 +msgid "Auto Start" +msgstr "Start automat" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:255 +msgid "Enable DCC" +msgstr "Activează DCC" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:263 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:266 +msgid "Advanced networking options" +msgstr "Opțiuni avansate de rețea" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:265 +msgid "" +"(NOTE: when this client proxy is configured to share tunnels, then these " +"options are for all the shared proxy clients!)" +msgstr "(NOTĂ: când acest proxy client este configurat pentru a partaja tuneluri, atunci aceste opțiuni sunt pentru toti clientii proxy comune!)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:267 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:268 +msgid "Tunnel Options" +msgstr "Opțiuni tunel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:269 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:270 +msgid "Length" +msgstr "Durată" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:276 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:277 +msgid "0 hop tunnel (no anonymity)" +msgstr "0 tunel hop (fara anonimat)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:280 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:281 +msgid "1 hop tunnel (low anonymity)" +msgstr "1 tunel hop (anonimat mic)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:284 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:285 +msgid "2 hop tunnel (medium anonymity)" +msgstr "2 tunel hop (anonimat mediu)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:288 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:289 +msgid "3 hop tunnel (high anonymity)" +msgstr "3 tunel hop (anonimat maxim)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:296 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:297 +msgid "hop tunnel (very poor performance)" +msgstr "tunel hop (performanță foarte slabă)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:301 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:302 +msgid "Variance" +msgstr "Varianță" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:308 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:309 +msgid "0 hop variance (no randomisation, consistant performance)" +msgstr "variație 0 hop (fără randomizare, performanță consistenta)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:312 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:313 +msgid "" +"+ 0-1 hop variance (medium additive randomisation, subtractive performance)" +msgstr "+ 0-1 hop variație (randomizare aditiv mediu, performanță substractiva)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:316 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:317 +msgid "" +"+ 0-2 hop variance (high additive randomisation, subtractive performance)" +msgstr "+ 0-2 hop variație (randomizare ridicat aditiva, performanță substractiva)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:320 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:321 +msgid "+/- 0-1 hop variance (standard randomisation, standard performance)" +msgstr "+ / - 0-1 hop varianța (randomizare standarda, performanță Standard)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:324 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:325 +msgid "+/- 0-2 hop variance (not recommended)" +msgstr "+ / - 0-2 hop variație (nu se recomandă)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:335 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:336 +msgid "hop variance" +msgstr "hop variație" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:340 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:341 +msgid "Count" +msgstr "Număr" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:344 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:345 +msgid "Backup Count" +msgstr "Numar de rezervă" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:351 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:352 +msgid "0 backup tunnels (0 redundancy, no added resource usage)" +msgstr "0 tuneluri de rezerva (0 redundanță, utilizarea resurselor nu e adăugata)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:355 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:356 +msgid "1 backup tunnel each direction (low redundancy, low resource usage)" +msgstr "1 tunel de rezervă pentru fiecare direcție (redundanță scăzuta, utilizarea redusă a resurselor)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:359 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:360 +msgid "" +"2 backup tunnels each direction (medium redundancy, medium resource usage)" +msgstr "2 tunele de rezervă pentru fiecare direcție (redundanță maxima, utilizarea maxima a resurselor)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:363 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:364 +msgid "3 backup tunnels each direction (high redundancy, high resource usage)" +msgstr "3 tunel de rezervă pentru fiecare direcție (redundanță maxima, utilizarea maxima a resurselor)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:371 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:372 +msgid "backup tunnels" +msgstr "tuneluri de rezervă" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:378 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:379 +msgid "Profile" +msgstr "Profil" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:385 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:386 +msgid "interactive connection" +msgstr "conexiune interactiva" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:389 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:390 +msgid "bulk connection (downloads/websites/BT)" +msgstr "conexiune în vrac (download-uri / site-uri / BT)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:391 +msgid "Delay Connect" +msgstr "întârziere Connectarii" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:395 +msgid "for request/response connections" +msgstr "pentru conexiuni de cerere/răspuns" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:399 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:394 +msgid "Router I2CP Address" +msgstr "Router I2CP Adresa" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:401 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:159 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:396 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:413 +msgid "Host" +msgstr "Gazdă" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:409 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:165 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:404 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:273 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:295 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:434 +msgid "Port" +msgstr "Port" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:419 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:502 +msgid "Reduce tunnel quantity when idle" +msgstr "Reducerea cantitatii tunelilor atunci când este inactiva" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:421 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:435 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:443 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:455 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:465 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:493 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:503 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:414 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:504 +msgid "Enable" +msgstr "Activează" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:425 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:508 +msgid "Reduced tunnel count" +msgstr "Scăderea numărului de tunelu" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:429 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:449 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:512 +msgid "Idle minutes" +msgstr "minute inactive" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:433 +msgid "Close tunnels when idle" +msgstr "Inchiderea tunelurilor când e inactiv" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:439 +msgid "New Keys on Reopen" +msgstr "Tastele noi la fiecare redeschidere" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:447 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:430 +msgid "Disable" +msgstr "Deactivare" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:453 +msgid "Delay tunnel open until required" +msgstr "Întârziere tunelului deschis până este necesar" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:463 +msgid "Persistent private key" +msgstr "Cheie privată persistenta" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:469 +msgid "File" +msgstr "Fișier" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:478 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:243 +msgid "Local destination" +msgstr "Destinația locala" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:482 +msgid "Local Base 32" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:491 +msgid "Local Authorization" +msgstr "Autorizare locala" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:497 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:507 +msgid "Username" +msgstr "Numele utilizatorului" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:499 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:511 +msgid "Password" +msgstr "Parolă" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:501 +msgid "Outproxy Authorization" +msgstr "Outproxy Autorizare" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:518 +msgid "Jump URL List" +msgstr "Sari la Lista de URL" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:524 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:548 +msgid "Custom options" +msgstr "Opțiuni personalizate" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:528 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:552 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:702 +msgid "Cancel" +msgstr "Renunță" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:532 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:556 +msgid "Delete" +msgstr "Șterge" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editClient_jsp.java:534 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:558 +msgid "Save" +msgstr "Salvează" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:82 +msgid "I2P Tunnel Manager - Edit Server Tunnel" +msgstr "Manager de tunele I2P - Editraza tunel de server" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:110 +msgid "Edit server settings" +msgstr "Editați setările de server" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:118 +msgid "New server settings" +msgstr "Setările de server noi" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:179 +msgid "Use SSL?" +msgstr "Utilizați SSL?" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:222 +msgid "Website name" +msgstr "Numele site-ului" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:226 +msgid "(leave blank for outproxies)" +msgstr "(lăsați gol pentru outproxies)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:231 +msgid "Private key file" +msgstr "Fișier cheie privată" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:253 +msgid "Add to local addressbook" +msgstr "Adauga la agenda locala" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:260 +msgid "Hostname Signature" +msgstr "Semnătura hostname" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:412 +msgid "Encrypt Leaseset" +msgstr "Criptarea Leaseset" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:418 +msgid "Encryption Key" +msgstr "Cheie de criptare" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:422 +msgid "Generate New Key" +msgstr "Generează o cheie noua" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:424 +msgid "Generate" +msgstr "Generează" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:426 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:546 +msgid "(Tunnel must be stopped first)" +msgstr "(Tunnelul mai întâi trebuie să fie oprit )" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:428 +msgid "Restricted Access List" +msgstr "Lista de acces restricționat" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:434 +msgid "Whitelist" +msgstr "Listă de excepții" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:438 +msgid "Blacklist" +msgstr "Listă de blocare" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:442 +msgid "Access List" +msgstr "Lista de acces" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:446 +msgid "Inbound connection limits (0=unlimited)" +msgstr "Limitele de conectare la intrare (0 = nelimitat)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:448 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:479 +msgid "Per client" +msgstr "pe client" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:450 +msgid "Per minute" +msgstr "pe minut" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:454 +msgid "Per hour" +msgstr "pe ora" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:458 +msgid "Per day" +msgstr "pe zi" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:462 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:489 +msgid "Total" +msgstr "Total" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:470 +msgid "Max concurrent connections (0=unlimited)" +msgstr "Conexiuni concurente max (0 = nelimitat)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:477 +msgid "POST limits (0=unlimited)" +msgstr "Limitele POST (0 = nelimitat)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:481 +msgid "Per period" +msgstr "pe perioadă" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:485 +msgid "Ban minutes" +msgstr "ban minute" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:495 +msgid "POST limit period (minutes)" +msgstr "Perioada limita POST (minute)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:516 +msgid "New Certificate type" +msgstr "Nou tip de certificat" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:518 +msgid "None" +msgstr "Niciunul" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:522 +msgid "Hashcash (effort)" +msgstr "Hashcash (efort)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:528 +msgid "Hashcash Calc Time" +msgstr "Hashcash Calc Timp" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:530 +msgid "Estimate" +msgstr "Estimare" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:532 +msgid "Hidden" +msgstr "Ascuns" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:536 +msgid "Signed (signed by)" +msgstr "Semnat (semnată de)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:542 +msgid "Modify Certificate" +msgstr "Modificare certificat" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/editServer_jsp.java:544 +msgid "Modify" +msgstr "Modifică" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:83 +msgid "I2P Tunnel Manager - List" +msgstr "Managerul tunelului I2P" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:97 +msgid "Status Messages" +msgstr "Mesaje de status" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:101 +msgid "Refresh" +msgstr "Reîmprospătează" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:109 +msgid "Tunnel Wizard" +msgstr "Expert tunel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:113 +msgid "Stop All" +msgstr "Oprește toate" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:117 +msgid "Start All" +msgstr "Pornește toate" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:121 +msgid "Restart All" +msgstr "Repornește toate" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:124 +msgid "I2P Server Tunnels" +msgstr "I2P server Tunele" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:128 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:149 +msgid "Points at" +msgstr "Puncte la" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:130 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:182 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:186 +msgid "Preview" +msgstr "Previzualizare" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:132 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:206 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:279 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:320 +msgid "Status" +msgstr "Stare" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:192 +msgid "Base32 Address" +msgstr "Adresa Base32" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:200 +msgid "No Preview" +msgstr "Nici o previzualizare" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:213 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:327 +msgid "Starting..." +msgstr "Pornire..." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:220 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:234 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:334 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:348 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:362 +msgid "Stop" +msgstr "Stop" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:227 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:355 +msgid "Running" +msgstr "În execuţie" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:241 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:369 +msgid "Stopped" +msgstr "Oprit" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:248 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:376 +msgid "Start" +msgstr "Start" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:263 +msgid "New server tunnel" +msgstr "Tunel de server nou" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:265 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:432 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:223 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:265 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:295 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:301 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:576 +msgid "Standard" +msgstr "Standard" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:267 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:434 +msgid "Create" +msgstr "Creează" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:269 +msgid "I2P Client Tunnels" +msgstr "I2P Tunnel client" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:277 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:306 +msgid "Interface" +msgstr "Interfață" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:341 +msgid "Standby" +msgstr "Stare de veghe" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:385 +msgid "Outproxy" +msgstr "Outproxy" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:388 +msgid "Destination" +msgstr "Destinație" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:395 +msgid "internal plugin" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:414 +msgid "none" +msgstr "nici unul" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/index_jsp.java:430 +msgid "New client tunnel" +msgstr "Tunel client nou" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:119 +msgid "I2P Tunnel Manager - Tunnel Creation Wizard" +msgstr "I2P Tunnel manager - Expert Crearea Tunnel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:139 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:567 +msgid "Server or client tunnel?" +msgstr "Server sau tunel client?" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:145 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:571 +msgid "Tunnel type" +msgstr "Tipul tunerului" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:151 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:601 +msgid "Tunnel name and description" +msgstr "Numele tunel și descrierea" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:157 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:610 +msgid "Tunnel destination" +msgstr "destinație tunel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:163 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:626 +msgid "Binding address and port" +msgstr "Adresa de legare și de port" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:169 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:652 +msgid "Tunnel auto-start" +msgstr "Tunel auto-start" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:175 +msgid "Wizard completed" +msgstr "Expertul finalizat" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:189 +msgid "" +"This wizard will take you through the various options available for creating" +" tunnels in I2P." +msgstr "Acest asistent vă va lua prin diferite opțiuni disponibile pentru crearea tunelurilor în I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:191 +msgid "" +"The first thing to decide is whether you want to create a server or a client" +" tunnel." +msgstr "Primul lucru este de a decide dacă doriți să creați un server sau un tunel client." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:193 +msgid "" +"If you need to connect to a remote service, such as an IRC server inside I2P" +" or a code repository, then you will require a CLIENT tunnel." +msgstr "Dacă aveți nevoie pentru a vă conecta la un serviciu de la distanță, cum ar fi un server de IRC în interiorul I2P sau un depozit de cod, atunci veți avea nevoie de un tunel CLIENT." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:195 +msgid "" +"On the other hand, if you wish to host a service for others to connect to " +"you'll need to create a SERVER tunnel." +msgstr "Pe de altă parte, dacă doriți să găzduiti un serviciu pentru alții veți avea nevoie pentru a crea un server de tunel." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:197 +msgid "Server Tunnel" +msgstr "Tunnel serverului" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:199 +msgid "Client Tunnel" +msgstr "Tunnel client" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:217 +msgid "There are several types of tunnels to choose from:" +msgstr "Există mai multe tipuri de tuneluri pentru a alege din:" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:225 +msgid "Basic tunnel for connecting to a single service inside I2P." +msgstr "Tunel de bază pentru conectarea la un singur serviciu în interiorul I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:227 +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:269 +msgid "" +"Try this if none of the tunnel types below fit your requirements, or you " +"don't know what type of tunnel you need." +msgstr "Încercați acest lucru dacă nici unul dintre tipurile de tunel de mai jos se potrivesc cerințelor dumneavoastră, sau nu stiti ce tip de tunel de care aveți nevoie." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:229 +msgid "Tunnel that acts as an HTTP proxy for reaching eepsites inside I2P." +msgstr "Tunel care actioneaza ca un proxy HTTP pentru a ajunge la eepsites din interiorul I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:231 +msgid "" +"Set your browser to use this tunnel as an http proxy, or set your " +"\"http_proxy\" environment variable for command-line applications in " +"GNU/Linux." +msgstr "Setati browser-ul pentru a utiliza acest tunel ca un proxy HTTP, sau pentru a seta variabila de mediu \"http_proxy\", pentru aplicații de linie de comandă în GNU / Linux." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:233 +msgid "" +"Websites outside I2P can also be reached if an HTTP proxy within I2P is " +"known." +msgstr "Site-uri din afara I2P poate fi atins în cazul în care un proxy HTTP în I2P este cunoscut." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:235 +msgid "Customised client tunnel specific for IRC connections." +msgstr "Tunel client personalizate specific pentru conexiuni de IRC." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:237 +msgid "" +"With this tunnel type, your IRC client will be able to connect to an IRC " +"network inside I2P." +msgstr "Cu acest tip tunel, clientul tau de IRC va fi capabil să se conecteze la o retea IRC din interiorul I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:239 +msgid "" +"Each IRC network in I2P that you wish to connect to will require its own " +"tunnel. (See Also, SOCKS IRC)" +msgstr "Fiecare rețea de IRC în I2P la care doriți să vă conectați pentru a va necesita propriul tunel. (A se vedea de asemenea, SOCKS IRC)" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:241 +msgid "A tunnel that implements the SOCKS protocol." +msgstr "Un tunel care implementează protocolul SOCKS." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:243 +msgid "" +"This enables both TCP and UDP connections to be made through a SOCKS " +"outproxy within I2P." +msgstr "Acest lucru permite conexiunile cit TCP atât si UDP să se facă printr-un SOCKS outproxy în I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:245 +msgid "" +"A client tunnel implementing the SOCKS protocol, which is customised for " +"connecting to IRC networks." +msgstr "Un tunel client de punere în aplicare protocolul SOCKS, care este personalizat pentru conectarea la retele de IRC." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:247 +msgid "" +"With this tunnel type, IRC networks in I2P can be reached by typing the I2P " +"address into your IRC client, and configuring the IRC client to use this " +"SOCKS tunnel." +msgstr "Cu acest tip tunel, retele de IRC din I2P poate ajunge tastând adresa I2P in clientul tau de IRC, și configurarea clientul IRC pentru a utiliza acest tunel SOCKS." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:249 +msgid "" +"This means that only one I2P tunnel is required rather than a separate " +"tunnel per IRC network." +msgstr "Aceasta înseamnă că este necesar doar un tunel I2P mai degrabă decât un tunel separat pentru fiecare rețea IRC." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:251 +msgid "" +"IRC networks outside I2P can also be reached if a SOCKS outproxy within I2P " +"is known, though it depends on whether or not the outproxy has been blocked " +"by the IRC network." +msgstr "Retele IRC din afara I2P pot fi ajunse, de asemenea, în cazul în care SOCKS outproxy în I2P este cunoscut, deși aceasta depinde dacă outproxy a fost blocat sau nu de către rețeaua IRC." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:253 +msgid "A client tunnel that implements the HTTP CONNECT command." +msgstr "Un tunel client care implementează comanda HTTP CONNECT." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:255 +msgid "" +"This enables TCP connections to be made through an HTTP outproxy, assuming " +"the proxy supports the CONNECT command." +msgstr "Acest lucru permite conexiuni TCP pentru a fi efectuate printr-un outproxy HTTP, presupunând proxy acceptă comanda CONNECT." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:257 +msgid "A customised client tunnel for Streamr." +msgstr "Un tunel client personalizat pentru Streamr." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:267 +msgid "A basic server tunnel for hosting a generic service inside I2P." +msgstr "Un tunel de server de bază pentru găzduirea un serviciu generic în interiorul I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:271 +msgid "A server tunnel that is customised for HTTP connections." +msgstr "Un tunel de server, care este personalizat pentru conexiuni HTTP." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:273 +msgid "Use this tunnel type if you want to host an eepsite." +msgstr "Utilizați acest tip tunel, dacă doriți să găzduiti un eepsite." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:275 +msgid "" +"A customised server tunnel that can both serve HTTP data and connect to " +"other server tunnels." +msgstr "Un tunel de server personalizat, care poate servi atât pentru date HTTP cit și pentru conectarea la alte tuneluri de server." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:277 +msgid "This tunnel type is predominantly used when running a Seedless server." +msgstr "Acest tip tunel este folosit în principal atunci când rulează un server de Seedless." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:279 +msgid "A customised server tunnel for hosting IRC networks inside I2P." +msgstr "Un tunel de server personalizat pentru găzduirea retelei de IRC în interiorul I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:281 +msgid "" +"Usually, a separate tunnel needs to be created for each IRC server that is " +"to be accessible inside I2P." +msgstr "De obicei, un tunel separat trebuie să fie creat pentru fiecare server de IRC, care să fie accesibil în interiorul I2P." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:283 +msgid "A customised server tunnel for Streamr." +msgstr "Un tunel server personalizat pentru Streamr." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:322 +msgid "Choose a name and description for your tunnel." +msgstr "Alegeți un nume și o descriere pentru tunelul dumneavoastră." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:324 +msgid "" +"These can be anything you want - they are just for ease of identifying the " +"tunnel in the routerconsole." +msgstr "Acestea pot fi orice vrei - acestea sunt doar pentru a facilita identificarea tunelului în routerconsole." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:354 +msgid "" +"If you know of any outproxies for this type of tunnel (either HTTP or " +"SOCKS), fill them in below." +msgstr "Dacă știți de orice outproxies pentru acest tip de tunel (fie HTTP sau SOCKS), completaile-le mai jos." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:356 +msgid "Separate multiple proxies with commas." +msgstr "Mai multe proxy-uri separate prin virgula." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:374 +msgid "" +"Type in the I2P destination of the service that this client tunnel should " +"connect to." +msgstr "Tapati în destinația I2P a serviciului cu care acest tunel client trebuie să se conecteze." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:376 +msgid "" +"This could be the full base 64 destination key, or an I2P URL from your " +"address book." +msgstr "Acest lucru ar putea fi cheia base64 completa destinație, sau un URL I2P din agenda de adrese." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:409 +msgid "" +"This is the IP that your service is running on, this is usually on the same " +"machine so 127.0.0.1 is autofilled." +msgstr "Acesta este IP la care serviciul se execută, aceasta este, de obicei pe aceeași mașină, astfel 127.0.0.1 este autofilled." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:432 +msgid "This is the port that the service is accepting connections on." +msgstr "Acesta este portul pe care serviciul accepta conexiuni." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:453 +msgid "This is the port that the client tunnel will be accessed from locally." +msgstr "Acesta este portul la care tunelul client va fi accesat de la nivel local." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:455 +msgid "This is also the client port for the HTTPBidir server tunnel." +msgstr "Aceasta este, de asemenea, portul de client pentru tunelul de server HTTPBidir." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:474 +msgid "" +"How do you want this tunnel to be accessed? By just this machine, your " +"entire subnet, or external internet?" +msgstr "Cum vrei ca acest tunel sa fie accesat? Doar de la această mașină, întreaga subrețea, sau internet extern?" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:476 +msgid "You will most likely want to just allow 127.0.0.1" +msgstr "Veți dori, cel mai probabil, pentru a permite doar 127.0.0.1" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:518 +msgid "" +"The I2P router can automatically start this tunnel for you when the router " +"is started." +msgstr "Router-ul I2P poate porni automat acest tunel pentru tine atunci când este pornit router-ul." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:520 +msgid "" +"This can be useful for frequently-used tunnels (especially server tunnels), " +"but for tunnels that are only used occassionally it would mean that the I2P " +"router is creating and maintaining unnecessary tunnels." +msgstr "Acest lucru poate fi util pentru tuneluri utilizate frecvent (mai ales tuneluri server), dar pentru tuneluri care sunt utilizate doar ocazional, aceasta ar însemna că router-ul I2P creaza și menține tuneluri inutile." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:546 +msgid "The wizard has now collected enough information to create your tunnel." +msgstr "Expertul a colectat acum suficiente informații pentru a crea tunel dumneavoastră." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:548 +msgid "" +"Upon clicking the Save button below, the wizard will set up the tunnel, and " +"take you back to the main I2PTunnel page." +msgstr "La clic pe butonul Save de mai jos, expertul va configura tunelul, și te duce înapoi la pagina principală I2PTunnel." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:553 +msgid "" +"Because you chose to automatically start the tunnel when the router starts, " +"you don't have to do anything further." +msgstr "Pentru că ați ales să pornească automat tunel când router-ul începe, nu trebuie să faci nimic mai mult." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:555 +msgid "The router will start the tunnel once it has been set up." +msgstr "Router-ul va începe tunelul după ce a fost creat." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:559 +msgid "" +"Because you chose not to automatically start the tunnel, you will have to " +"manually start it." +msgstr "Pentru că ați ales să nu se pornească automat tunel, va trebui să-l porniți manual." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:561 +msgid "" +"You can do this by clicking the Start button on the main page which " +"corresponds to the new tunnel." +msgstr "Puteți face acest lucru făcând clic pe butonul Start de pe pagina principală, care corespunde cu noul tunel." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:565 +msgid "Below is a summary of the options you chose:" +msgstr "Mai jos este un rezumat al opțiunilor alese de tine:" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:663 +msgid "" +"Alongside these basic settings, there are a number of advanced options for " +"tunnel configuration." +msgstr "Alături de aceste setări de bază, există o serie de opțiuni avansate de configurare tunel." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:665 +msgid "" +"The wizard will set reasonably sensible default values for these, but you " +"can view and/or edit these by clicking on the tunnel's name in the main " +"I2PTunnel page." +msgstr "Expertul va stabili valorile implicite rezonabil sensibile pentru acestea, dar puteți vizualiza și/sau edita acestea, făcând clic pe numele tunelului pe pagina principală I2PTunnel." + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:707 +msgid "Previous" +msgstr "Precedent" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:715 +msgid "Save Tunnel" +msgstr "Salvare Tunnel" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:721 +msgid "Finish" +msgstr "Sfârșit" + +#: ../jsp/WEB-INF/classes/net/i2p/i2ptunnel/jsp/wizard_jsp.java:727 +msgid "Next" +msgstr "Următorul" diff --git a/apps/ministreaming/locale/messages_de.po b/apps/ministreaming/locale/messages_de.po new file mode 100644 index 0000000000..324420235c --- /dev/null +++ b/apps/ministreaming/locale/messages_de.po @@ -0,0 +1,91 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Ettore Atalan <atalanttore@googlemail.com>, 2014 +# Lars Schimmer <echelon@i2pmail.org>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"PO-Revision-Date: 2014-06-26 13:15+0000\n" +"Last-Translator: Lars Schimmer <echelon@i2pmail.org>\n" +"Language-Team: German (http://www.transifex.com/projects/p/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/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "Nachrichten timeout" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "Konnte nicht zur lokalen Destination zugestellt werden" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "Fehler im lokalen Router" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "Fehler im lokalen Netzwerk" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "Sitzung geschlossen" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "Ungültige Nachricht" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "Ungültige Nachrichtenoptionen" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "Pufferüberlauf" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "Nachricht nicht mehr gültig" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "Lokales Leaseset ungültig" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "Keine lokalen Tunnel" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "Nicht unterstützte Verschlüsselungsoptionen" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "Ungültiges Ziel" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "Leaseset der Destination abgelaufen" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "Destinations Leaseset nicht gefunden" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "Lokale Destination geschlossen" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "Fehlercode" diff --git a/apps/ministreaming/locale/messages_es.po b/apps/ministreaming/locale/messages_es.po new file mode 100644 index 0000000000..a8538e1663 --- /dev/null +++ b/apps/ministreaming/locale/messages_es.po @@ -0,0 +1,90 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# strel, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"PO-Revision-Date: 2014-06-25 04:23+0000\n" +"Last-Translator: strel\n" +"Language-Team: Spanish (http://www.transifex.com/projects/p/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/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "Tiempo hasta la expiración del mensaje" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "Fallo en la entrega al destino local" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "Fallo del router local" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "Fallo de la red local" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "Sesión cerrada" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "Mensaje no válido" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "Opciones de mensaje no válido" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "Desbordamiento de memoria intermedia (buffer)" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "El mensaje expiró" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "El lease set (túneles al mismo destino) local no es válido" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "No hay túneles locales" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "Opciones de cifrado no soportadas" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "Destino no válido" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "El lease set (túneles al mismo destino) del destino expiró" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "No se encontró el lease set (túneles al mismo destino) del destino" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "Cierre del destino local" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "Código de fallo" diff --git a/apps/ministreaming/locale/messages_fr.po b/apps/ministreaming/locale/messages_fr.po new file mode 100644 index 0000000000..6b692393ee --- /dev/null +++ b/apps/ministreaming/locale/messages_fr.po @@ -0,0 +1,90 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Towinet, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"PO-Revision-Date: 2014-06-26 19:02+0000\n" +"Last-Translator: Towinet\n" +"Language-Team: French (http://www.transifex.com/projects/p/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/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "Échéance de message" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "Échec de livraison vers la destination locale" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "Échec de routeur local" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "Échec de réseau local" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "Session fermée" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "Message invalide" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "Options de message invalide" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "Débordement de buffer" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "Message expiré" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "Jeu de bail local invalide" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "Pas de tunnels locaux" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "Options de chiffrement non supportées" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "Destination invalide" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "Jeu de bail de la destination expiré" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "Jeu de bail de la destination non trouvé" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "Arrêt de la destination locale" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "Code d'échec" diff --git a/apps/ministreaming/locale/messages_it.po b/apps/ministreaming/locale/messages_it.po new file mode 100644 index 0000000000..c5a805e2c3 --- /dev/null +++ b/apps/ministreaming/locale/messages_it.po @@ -0,0 +1,90 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# alamir <christianm@libero.it>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"PO-Revision-Date: 2014-06-24 22:56+0000\n" +"Last-Translator: alamir <christianm@libero.it>\n" +"Language-Team: Italian (http://www.transifex.com/projects/p/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/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "Timeout del messaggio" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "Spedizione fallita alla destinazione locale" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "Errore del router locale" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "Errore della rete locale" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "Sessione chiusa" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "Messaggio non valido" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "Opzioni del messaggio non valide" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "Errore di buffer overflow" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "Messaggio scaduto" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "" diff --git a/apps/ministreaming/locale/messages_nb.po b/apps/ministreaming/locale/messages_nb.po new file mode 100644 index 0000000000..115fefc8be --- /dev/null +++ b/apps/ministreaming/locale/messages_nb.po @@ -0,0 +1,90 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Allan Nordhøy <comradekingu@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"PO-Revision-Date: 2014-06-24 23:11+0000\n" +"Last-Translator: Allan Nordhøy <comradekingu@gmail.com>\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/projects/p/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/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "Meldingsfrist utløp" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "Kunne ikke levere til lokal plassering" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "Lokal rutings-feil" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "Lokal nettverks-feil" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "Økt lukket" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "Ugyldig melding" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "Ugyldige meldingsvalg" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "Mellomlager gikk fullt" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "Melding utløp" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "Ingen lokale tunneler tilgjengelig" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "Ustøttede krypteringsvalg" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "Ugyldig destinasjon" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "Nedstengning av lokal destinasjon" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "Feilkode" diff --git a/apps/ministreaming/locale/messages_ru.po b/apps/ministreaming/locale/messages_ru.po new file mode 100644 index 0000000000..740bc9d3cc --- /dev/null +++ b/apps/ministreaming/locale/messages_ru.po @@ -0,0 +1,91 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# yume, 2014 +# Тимофей <nefelim4ag@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"PO-Revision-Date: 2014-06-26 19:53+0000\n" +"Last-Translator: yume\n" +"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/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" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "Время ожидания для сообщения истекло" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "Ошибка доставки до локального адресата" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "Ошибка локального маршрутизатора" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "Локальная ошибка сети" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "Сессия завершена" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "Неправильное сообщение" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "Неправильные параметры сообщения" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "Переполнение буфера" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "Истек срок действия сообщения" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "Нет локальных туннелей" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "Не поддерживаемые настройки шифрования" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "Недопустимый адрес назначения" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "Адрес локального отправителя отключен" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "Код ошибки" diff --git a/apps/ministreaming/locale/messages_uk.po b/apps/ministreaming/locale/messages_uk.po new file mode 100644 index 0000000000..e76654fdc2 --- /dev/null +++ b/apps/ministreaming/locale/messages_uk.po @@ -0,0 +1,90 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# puxud <puxud@alivance.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"PO-Revision-Date: 2014-08-07 13:56+0000\n" +"Last-Translator: puxud <puxud@alivance.com>\n" +"Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/projects/p/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" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "Крах локального роутеру" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "Крах локальної мережі" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "" diff --git a/apps/ministreaming/locale/messages_zh.po b/apps/ministreaming/locale/messages_zh.po new file mode 100644 index 0000000000..e55b602a75 --- /dev/null +++ b/apps/ministreaming/locale/messages_zh.po @@ -0,0 +1,90 @@ +# I2P +# Copyright (C) 2014 The I2P Project +# This file is distributed under the same license as the streaming package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# YF <yfdyh000@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-23 17:55+0000\n" +"PO-Revision-Date: 2014-06-24 22:23+0000\n" +"Last-Translator: YF <yfdyh000@gmail.com>\n" +"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/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/net/i2p/client/streaming/I2PSocketException.java:58 +msgid "Message timeout" +msgstr "消息超时" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:61 +msgid "Failed delivery to local destination" +msgstr "传送到本地目标失败" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:64 +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:97 +msgid "Local router failure" +msgstr "本地路由故障" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:67 +msgid "Local network failure" +msgstr "本地网络故障" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:70 +msgid "Session closed" +msgstr "会话已关闭" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:73 +msgid "Invalid message" +msgstr "无效消息" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:76 +msgid "Invalid message options" +msgstr "无效消息选项" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:79 +msgid "Buffer overflow" +msgstr "缓冲区溢出" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:82 +msgid "Message expired" +msgstr "消息已过期" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:85 +msgid "Local lease set invalid" +msgstr "本地租赁无效" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:88 +msgid "No local tunnels" +msgstr "没有本地隧道" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:91 +msgid "Unsupported encryption options" +msgstr "不支持的加密选项" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:94 +msgid "Invalid destination" +msgstr "无效目标" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:100 +msgid "Destination lease set expired" +msgstr "目标租赁已过期" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:103 +msgid "Destination lease set not found" +msgstr "找不到目标租赁" + +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:106 +msgid "Local destination shutdown" +msgstr "本地目标关机" + +#. Translate this one here, can't do it later +#: ../java/src/net/i2p/client/streaming/I2PSocketException.java:113 +msgid "Failure code" +msgstr "失败代码" diff --git a/apps/routerconsole/locale-countries/messages_ca.po b/apps/routerconsole/locale-countries/messages_ca.po new file mode 100644 index 0000000000..bd61f6b29c --- /dev/null +++ b/apps/routerconsole/locale-countries/messages_ca.po @@ -0,0 +1,763 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-10-14 13:33+0000\n" +"PO-Revision-Date: 2014-02-21 00:08+0000\n" +"Last-Translator: el_libre como el chaval <el.libre@gmail.com>\n" +"Language-Team: Catalan (http://www.transifex.com/projects/p/I2P/language/ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Anonymous Proxy" +msgstr "Proxy anònim" + +msgid "Satellite Provider" +msgstr "Proveïdor de satèl·lit " + +msgid "Andorra" +msgstr "Andorra" + +msgid "United Arab Emirates" +msgstr "Emirats Àrabs Units" + +msgid "Afghanistan" +msgstr "Afganistan" + +msgid "Antigua and Barbuda" +msgstr "Antigua i Barbuda " + +msgid "Anguilla" +msgstr "Anguilla " + +msgid "Albania" +msgstr "Albània " + +msgid "Armenia" +msgstr "Armènia " + +msgid "Netherlands Antilles" +msgstr "Antilles Holandeses " + +msgid "Angola" +msgstr "Angola " + +msgid "Antarctica" +msgstr "Antàrtida" + +msgid "Argentina" +msgstr "Argentina " + +msgid "American Samoa" +msgstr "Samoa Americana " + +msgid "Austria" +msgstr "Àustria " + +msgid "Australia" +msgstr "Austràlia" + +msgid "Aruba" +msgstr "Aruba " + +msgid "Åland Islands" +msgstr "Illes Åland " + +msgid "Azerbaijan" +msgstr "Azerbaidjan " + +msgid "Bosnia and Herzegovina" +msgstr "Bòsnia i Hercegovina " + +msgid "Barbados" +msgstr "Barbados " + +msgid "Bangladesh" +msgstr "Bangla Desh " + +msgid "Belgium" +msgstr "Bèlgica " + +msgid "Burkina Faso" +msgstr "Burkina Faso " + +msgid "Bulgaria" +msgstr "Bulgària " + +msgid "Bahrain" +msgstr "Bahrain " + +msgid "Burundi" +msgstr "Burundi" + +msgid "Benin" +msgstr "Benín " + +msgid "Bermuda" +msgstr "Bermuda " + +msgid "Brunei Darussalam" +msgstr "Brunei " + +msgid "Bolivia" +msgstr "Bolívia" + +msgid "Brazil" +msgstr "Brasil " + +msgid "Bahamas" +msgstr "Bahames " + +msgid "Bhutan" +msgstr "Butan " + +msgid "Bouvet Island" +msgstr "Bouvet Island " + +msgid "Botswana" +msgstr "Botswana " + +msgid "Belarus" +msgstr "Bielorússia " + +msgid "Belize" +msgstr "Belize " + +msgid "Canada" +msgstr "Canadà " + +msgid "Cocos (Keeling) Islands" +msgstr "Illes Cocos (Keeling) " + +msgid "The Democratic Republic of the Congo" +msgstr "La República Democràtica del Congo " + +msgid "Central African Republic" +msgstr "República Centreafricana " + +msgid "Congo" +msgstr "Congo " + +msgid "Switzerland" +msgstr "Suïssa " + +msgid "Cote D'Ivoire" +msgstr "Costa d'Ivori" + +msgid "Cook Islands" +msgstr "Illes Cook " + +msgid "Chile" +msgstr "Xile " + +msgid "Cameroon" +msgstr "Camerun " + +msgid "China" +msgstr "Xina " + +msgid "Colombia" +msgstr "Colòmbia " + +msgid "Costa Rica" +msgstr "Costa Rica " + +msgid "Serbia and Montenegro" +msgstr "Sèrbia i Montenegro " + +msgid "Cuba" +msgstr "Cuba " + +msgid "Cape Verde" +msgstr "Cap Verd " + +msgid "Curaçao" +msgstr "Curaçao " + +msgid "Christmas Island" +msgstr "Illa de Christmas" + +msgid "Cyprus" +msgstr "Xipre " + +msgid "Czech Republic" +msgstr "República Txeca " + +msgid "Germany" +msgstr "Alemanya " + +msgid "Djibouti" +msgstr "Djibuti " + +msgid "Denmark" +msgstr "Dinamarca " + +msgid "Dominica" +msgstr "Dominica " + +msgid "Dominican Republic" +msgstr "República Dominicana " + +msgid "Algeria" +msgstr "Algèria " + +msgid "Ecuador" +msgstr "Equador " + +msgid "Estonia" +msgstr "Estònia " + +msgid "Egypt" +msgstr "Egipte " + +msgid "Western Sahara" +msgstr "Sàhara Occidental " + +msgid "Eritrea" +msgstr "Eritrea " + +msgid "Spain" +msgstr "Espanya " + +msgid "Ethiopia" +msgstr "Etiòpia " + +msgid "European Union" +msgstr "Unió Europea" + +msgid "Finland" +msgstr "Finlàndia " + +msgid "Fiji" +msgstr "Fiji " + +msgid "Falkland Islands (Malvinas)" +msgstr "Illes Malvines (Falkland) " + +msgid "Federated States of Micronesia" +msgstr "Els Estats Federats de Micronèsia " + +msgid "Faroe Islands" +msgstr "Illes Fèroe " + +msgid "France" +msgstr "França " + +msgid "Gabon" +msgstr "Gabon " + +msgid "United Kingdom" +msgstr "Regne Unit " + +msgid "Grenada" +msgstr "Granada " + +msgid "Georgia" +msgstr "Geòrgia " + +msgid "French Guiana" +msgstr "Guiana francesa" + +msgid "Guernsey" +msgstr "Guernsey " + +msgid "Ghana" +msgstr "Ghana " + +msgid "Gibraltar" +msgstr "Gibraltar " + +msgid "Greenland" +msgstr "Groenlàndia " + +msgid "Gambia" +msgstr "Gàmbia " + +msgid "Guinea" +msgstr "Guinea " + +msgid "Guadeloupe" +msgstr "Guadalupe " + +msgid "Equatorial Guinea" +msgstr "Guinea Equatorial " + +msgid "Greece" +msgstr "Grècia " + +msgid "South Georgia and the South Sandwich Islands" +msgstr "Geòrgia del Sud i Illes Sandwich del Sud " + +msgid "Guatemala" +msgstr "Guatemala " + +msgid "Guam" +msgstr "Guam " + +msgid "Guinea-Bissau" +msgstr "Guinea Bissau " + +msgid "Guyana" +msgstr "Guaiana " + +msgid "Hong Kong" +msgstr "Hong Kong " + +msgid "Honduras" +msgstr "Hondures " + +msgid "Croatia" +msgstr "Croàcia " + +msgid "Haiti" +msgstr "Haití " + +msgid "Hungary" +msgstr "Hongria " + +msgid "Indonesia" +msgstr "Indonèsia " + +msgid "Ireland" +msgstr "Irlanda " + +msgid "Israel" +msgstr "Israel " + +msgid "Isle of Man" +msgstr "Illa de Man " + +msgid "India" +msgstr "Índia " + +msgid "British Indian Ocean Territory" +msgstr "Territori Britànic de l'Oceà Índic " + +msgid "Iraq" +msgstr "Iraq " + +msgid "Islamic Republic of Iran" +msgstr "República Islàmica de l'Iran " + +msgid "Iceland" +msgstr "Islàndia " + +msgid "Italy" +msgstr "Itàlia " + +msgid "Jersey" +msgstr "Jersey " + +msgid "Jamaica" +msgstr "Jamaica " + +msgid "Jordan" +msgstr "Jordània " + +msgid "Japan" +msgstr "Japó " + +msgid "Kenya" +msgstr "Kènia" + +msgid "Kyrgyzstan" +msgstr "Kirguizistan " + +msgid "Cambodia" +msgstr "Cambodja " + +msgid "Kiribati" +msgstr "Kiribati " + +msgid "Comoros" +msgstr "Comores " + +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts i Nevis " + +msgid "The Democratic People's Republic of Korea" +msgstr "La República Popular Democràtica de Corea " + +msgid "Republic of Korea" +msgstr "República de Corea " + +msgid "Kuwait" +msgstr "Kuwait " + +msgid "Cayman Islands" +msgstr "Illes Caiman " + +msgid "Kazakhstan" +msgstr "Kazakhstan " + +msgid "Lao People's Democratic Republic" +msgstr "República Democràtica Popular Lao " + +msgid "Lebanon" +msgstr "Líban " + +msgid "Saint Lucia" +msgstr "Santa Lucia " + +msgid "Liechtenstein" +msgstr "Liechtenstein " + +msgid "Sri Lanka" +msgstr "Sri Lanka " + +msgid "Liberia" +msgstr "Libèria " + +msgid "Lesotho" +msgstr "Lesotho " + +msgid "Lithuania" +msgstr "Lituània " + +msgid "Luxembourg" +msgstr "Luxemburg " + +msgid "Latvia" +msgstr "Letònia " + +msgid "Libyan Arab Jamahiriya" +msgstr "Jamahiriya Àrab Líbia " + +msgid "Morocco" +msgstr "Marroc " + +msgid "Monaco" +msgstr "Mònaco " + +msgid "Republic of Moldova" +msgstr "República de Moldàvia " + +msgid "Montenegro" +msgstr "Montenegro " + +msgid "Saint Martin" +msgstr "Saint Martin " + +msgid "Madagascar" +msgstr "Madagascar " + +msgid "Marshall Islands" +msgstr "Illes Marshall " + +msgid "The Former Yugoslav Republic of Macedonia" +msgstr "L'Antiga República Iugoslava de Macedònia " + +msgid "Mali" +msgstr "Mali " + +msgid "Myanmar" +msgstr "Myanmar " + +msgid "Mongolia" +msgstr "Mongòlia " + +msgid "Macao" +msgstr "Macau " + +msgid "Northern Mariana Islands" +msgstr "Illes Mariannes del Nord " + +msgid "Martinique" +msgstr "Martinica " + +msgid "Mauritania" +msgstr "Mauritània " + +msgid "Montserrat" +msgstr "Montserrat " + +msgid "Malta" +msgstr "Malta " + +msgid "Mauritius" +msgstr "Maurici " + +msgid "Maldives" +msgstr "Maldives " + +msgid "Malawi" +msgstr "Malawi " + +msgid "Mexico" +msgstr "Mèxic " + +msgid "Malaysia" +msgstr "Malàisia " + +msgid "Mozambique" +msgstr "Moçambic " + +msgid "Namibia" +msgstr "Namíbia " + +msgid "New Caledonia" +msgstr "Nova Caledònia " + +msgid "Niger" +msgstr "Níger " + +msgid "Norfolk Island" +msgstr "Illa Norfolk " + +msgid "Nigeria" +msgstr "Nigèria " + +msgid "Nicaragua" +msgstr "Nicaragua " + +msgid "Netherlands" +msgstr "Països Baixos " + +msgid "Norway" +msgstr "Noruega " + +msgid "Nepal" +msgstr "Nepal " + +msgid "Nauru" +msgstr "Nauru " + +msgid "Niue" +msgstr "Niueà " + +msgid "New Zealand" +msgstr "Nova Zelanda " + +msgid "Oman" +msgstr "Oman " + +msgid "Panama" +msgstr "Panamà " + +msgid "Peru" +msgstr "Perú " + +msgid "French Polynesia" +msgstr "Polinèsia francesa" + +msgid "Papua New Guinea" +msgstr "Papua Nova Guinea " + +msgid "Philippines" +msgstr "Filipines " + +msgid "Pakistan" +msgstr "Pakistan " + +msgid "Poland" +msgstr "Polònia " + +msgid "Saint Pierre and Miquelon" +msgstr "Sant Pere i Miquelon " + +msgid "Pitcairn Islands" +msgstr "Illes Pitcairn " + +msgid "Puerto Rico" +msgstr "Puerto Rico" + +msgid "Palestinian Territory" +msgstr "Territori palestí " + +msgid "Portugal" +msgstr "Portugal " + +msgid "Palau" +msgstr "Palau " + +msgid "Paraguay" +msgstr "Paraguai " + +msgid "Qatar" +msgstr "Qatar " + +msgid "Réunion" +msgstr "Réunion " + +msgid "Romania" +msgstr "Romania " + +msgid "Serbia" +msgstr "Sèrbia " + +msgid "Russian Federation" +msgstr "Federació de Rússia " + +msgid "Rwanda" +msgstr "Ruanda" + +msgid "Saudi Arabia" +msgstr "Aràbia Saudita " + +msgid "Solomon Islands" +msgstr "Illes Salomó " + +msgid "Seychelles" +msgstr "Seychelles " + +msgid "Sudan" +msgstr "Sudan " + +msgid "Sweden" +msgstr "Suècia " + +msgid "Singapore" +msgstr "Singapur " + +msgid "Saint Helena" +msgstr "Santa Elena " + +msgid "Slovenia" +msgstr "Eslovènia " + +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard i Jan Mayen " + +msgid "Slovakia" +msgstr "Eslovàquia " + +msgid "Sierra Leone" +msgstr "Sierra Leone " + +msgid "San Marino" +msgstr "San Marino " + +msgid "Senegal" +msgstr "Senegal " + +msgid "Somalia" +msgstr "Somàlia " + +msgid "Suriname" +msgstr "Suriname " + +msgid "Sao Tome and Principe" +msgstr "Sao Tome i Principe" + +msgid "El Salvador" +msgstr "El Salvador " + +msgid "Syrian Arab Republic" +msgstr "República Àrab Síria " + +msgid "Swaziland" +msgstr "Swazilàndia " + +msgid "Turks and Caicos Islands" +msgstr "Turks i Caicos " + +msgid "Chad" +msgstr "Txad " + +msgid "French Southern Territories" +msgstr "Territoris Francesos " + +msgid "Togo" +msgstr "Togo " + +msgid "Thailand" +msgstr "Tailàndia " + +msgid "Tajikistan" +msgstr "Tadjikistan " + +msgid "Tokelau" +msgstr "Tokelau " + +msgid "Timor-Leste" +msgstr "Timor Oriental " + +msgid "Turkmenistan" +msgstr "Turkmenistan " + +msgid "Tunisia" +msgstr "Tunísia " + +msgid "Tonga" +msgstr "Tonga " + +msgid "Turkey" +msgstr "Turquia " + +msgid "Trinidad and Tobago" +msgstr "Trinitat i Tobago " + +msgid "Tuvalu" +msgstr "Tuvalu " + +msgid "Taiwan" +msgstr "Taiwan " + +msgid "United Republic of Tanzania" +msgstr "República Unida de Tanzània " + +msgid "Ukraine" +msgstr "Ucraïna " + +msgid "Uganda" +msgstr "Uganda " + +msgid "United States Minor Outlying Islands" +msgstr "Illes menors allunyades dels Estats Units " + +msgid "United States" +msgstr "Estats Units " + +msgid "Uruguay" +msgstr "Uruguai " + +msgid "Uzbekistan" +msgstr "Uzbekistan " + +msgid "Holy See (Vatican City State)" +msgstr "Santa Seu (Ciutat del Vaticà) " + +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent i les Grenadines " + +msgid "Venezuela" +msgstr "Veneçuela " + +msgid "Virgin Islands" +msgstr "Illes Verges " + +msgid "Viet Nam" +msgstr "Vietnam " + +msgid "Vanuatu" +msgstr "Vanuatu " + +msgid "Wallis and Futuna" +msgstr "Wallis i Futuna " + +msgid "Samoa" +msgstr "Samoa " + +msgid "Yemen" +msgstr "Iemen " + +msgid "Mayotte" +msgstr "Mayotte " + +msgid "South Africa" +msgstr "Sud-àfrica " + +msgid "Zambia" +msgstr "Zàmbia " + +msgid "Zimbabwe" +msgstr "Zimbabwe " diff --git a/apps/routerconsole/locale-countries/messages_sq.po b/apps/routerconsole/locale-countries/messages_sq.po new file mode 100644 index 0000000000..c29ac607cb --- /dev/null +++ b/apps/routerconsole/locale-countries/messages_sq.po @@ -0,0 +1,764 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Shpetim <shpetim@privacysolutions.no>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-10-14 13:33+0000\n" +"PO-Revision-Date: 2014-08-10 18:13+0000\n" +"Last-Translator: Shpetim <shpetim@privacysolutions.no>\n" +"Language-Team: Albanian (http://www.transifex.com/projects/p/I2P/language/sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Anonymous Proxy" +msgstr "Reprezentim i fshehur" + +msgid "Satellite Provider" +msgstr "Furnizues i Satelitit" + +msgid "Andorra" +msgstr "Andora" + +msgid "United Arab Emirates" +msgstr "Emiratet e bashkuara Arabe" + +msgid "Afghanistan" +msgstr "Afganistani" + +msgid "Antigua and Barbuda" +msgstr "Antigua dhe Barbuda" + +msgid "Anguilla" +msgstr "Anguilla " + +msgid "Albania" +msgstr "Shqipëria" + +msgid "Armenia" +msgstr "Armenia" + +msgid "Netherlands Antilles" +msgstr "Antilet Holandeze" + +msgid "Angola" +msgstr "Angola" + +msgid "Antarctica" +msgstr "Antarktida" + +msgid "Argentina" +msgstr "Argjentina" + +msgid "American Samoa" +msgstr "Samoat Amerikane" + +msgid "Austria" +msgstr "Austria" + +msgid "Australia" +msgstr "Australia" + +msgid "Aruba" +msgstr "Aruba" + +msgid "Åland Islands" +msgstr "Ishujt Åland" + +msgid "Azerbaijan" +msgstr "Azerbajxhani" + +msgid "Bosnia and Herzegovina" +msgstr "Bosnja dhe Hercegovina" + +msgid "Barbados" +msgstr "Barbadosi" + +msgid "Bangladesh" +msgstr "Bangladeshi" + +msgid "Belgium" +msgstr "Belgjika" + +msgid "Burkina Faso" +msgstr "Burkina Faso" + +msgid "Bulgaria" +msgstr "Bullgaria" + +msgid "Bahrain" +msgstr "Bahraini" + +msgid "Burundi" +msgstr "Burundi" + +msgid "Benin" +msgstr "Benini" + +msgid "Bermuda" +msgstr "Bermuda" + +msgid "Brunei Darussalam" +msgstr "" + +msgid "Bolivia" +msgstr "Bolivia" + +msgid "Brazil" +msgstr "Brazili" + +msgid "Bahamas" +msgstr "Bahamas" + +msgid "Bhutan" +msgstr "Butani" + +msgid "Bouvet Island" +msgstr "Ishulli Bouvet" + +msgid "Botswana" +msgstr "Botsvana" + +msgid "Belarus" +msgstr "Bellorusia" + +msgid "Belize" +msgstr "Beliza" + +msgid "Canada" +msgstr "Kanada" + +msgid "Cocos (Keeling) Islands" +msgstr "Ishujt Cocos (Keeling)" + +msgid "The Democratic Republic of the Congo" +msgstr "Republika Demokratike e Kongos" + +msgid "Central African Republic" +msgstr "Republika e Afrikës Qëndrore. " + +msgid "Congo" +msgstr "Kongo" + +msgid "Switzerland" +msgstr "Zvicrra" + +msgid "Cote D'Ivoire" +msgstr "Bregu i Fildishtë" + +msgid "Cook Islands" +msgstr "Ishujt Cook" + +msgid "Chile" +msgstr "Kili" + +msgid "Cameroon" +msgstr "Kameruni" + +msgid "China" +msgstr "Kina" + +msgid "Colombia" +msgstr "Kollumbia" + +msgid "Costa Rica" +msgstr "Kosta Rika" + +msgid "Serbia and Montenegro" +msgstr "Serbia dhe Mali i Zi" + +msgid "Cuba" +msgstr "Kuba" + +msgid "Cape Verde" +msgstr "Kepi i Gjelbër" + +msgid "Curaçao" +msgstr "Kurakao" + +msgid "Christmas Island" +msgstr "Christmas Island" + +msgid "Cyprus" +msgstr "Qipro" + +msgid "Czech Republic" +msgstr "Republika Çeke" + +msgid "Germany" +msgstr "Gjermania" + +msgid "Djibouti" +msgstr "Gjibuti" + +msgid "Denmark" +msgstr "Danimarka" + +msgid "Dominica" +msgstr "Dominika" + +msgid "Dominican Republic" +msgstr "Republika Dominikane" + +msgid "Algeria" +msgstr "Algjeria" + +msgid "Ecuador" +msgstr "Ekuadori" + +msgid "Estonia" +msgstr "Estonia" + +msgid "Egypt" +msgstr "Egjipti" + +msgid "Western Sahara" +msgstr "Sahara Perëndimore" + +msgid "Eritrea" +msgstr "Eritrea" + +msgid "Spain" +msgstr "Spanja" + +msgid "Ethiopia" +msgstr "Etiopia" + +msgid "European Union" +msgstr "Bashkimi Evropian " + +msgid "Finland" +msgstr "Finlanda" + +msgid "Fiji" +msgstr "Fixhi" + +msgid "Falkland Islands (Malvinas)" +msgstr "Ishujt Falkand (Malvinas)" + +msgid "Federated States of Micronesia" +msgstr "Shtetet Federate të Mikronezisë " + +msgid "Faroe Islands" +msgstr "Ishujt Faroe" + +msgid "France" +msgstr "Franca" + +msgid "Gabon" +msgstr "Gaboni" + +msgid "United Kingdom" +msgstr "Mbretëria e Bashkuar" + +msgid "Grenada" +msgstr "Grenada" + +msgid "Georgia" +msgstr "Gjeorgjia" + +msgid "French Guiana" +msgstr "Guiana Franceze" + +msgid "Guernsey" +msgstr "Guernesey" + +msgid "Ghana" +msgstr "Gana" + +msgid "Gibraltar" +msgstr "Gjibraltari" + +msgid "Greenland" +msgstr "Groenlanda" + +msgid "Gambia" +msgstr "Gambia" + +msgid "Guinea" +msgstr "Guinea" + +msgid "Guadeloupe" +msgstr "Guadeloupe" + +msgid "Equatorial Guinea" +msgstr "Guinea Ekuotariale" + +msgid "Greece" +msgstr "Greqia" + +msgid "South Georgia and the South Sandwich Islands" +msgstr "Gjeorgjia Jugore dhe Ishujt e Sandwich'it Jugor" + +msgid "Guatemala" +msgstr "Guatemala" + +msgid "Guam" +msgstr "Guam" + +msgid "Guinea-Bissau" +msgstr "Guinea Bisau" + +msgid "Guyana" +msgstr "Guyana" + +msgid "Hong Kong" +msgstr "Hong Kongu" + +msgid "Honduras" +msgstr "Hondurasi" + +msgid "Croatia" +msgstr "Kroacia" + +msgid "Haiti" +msgstr "Haiti" + +msgid "Hungary" +msgstr "Hungaria" + +msgid "Indonesia" +msgstr "Indonezia" + +msgid "Ireland" +msgstr "Irlanda" + +msgid "Israel" +msgstr "Izraeli" + +msgid "Isle of Man" +msgstr "Ishulli i Man" + +msgid "India" +msgstr "India" + +msgid "British Indian Ocean Territory" +msgstr "Territor oqeanik Indiano-Britanik" + +msgid "Iraq" +msgstr "Iraku" + +msgid "Islamic Republic of Iran" +msgstr "Republika Islamike e Iranit" + +msgid "Iceland" +msgstr "Islanda" + +msgid "Italy" +msgstr "Italia" + +msgid "Jersey" +msgstr "Gjerzi" + +msgid "Jamaica" +msgstr "Xhamajka" + +msgid "Jordan" +msgstr "Jordania" + +msgid "Japan" +msgstr "Japonia" + +msgid "Kenya" +msgstr "Kenia" + +msgid "Kyrgyzstan" +msgstr "Kirgizistani" + +msgid "Cambodia" +msgstr "Kamboxha" + +msgid "Kiribati" +msgstr "Kiribati" + +msgid "Comoros" +msgstr "Komorosi" + +msgid "Saint Kitts and Nevis" +msgstr "Shenjt Kitts dhe Nevis" + +msgid "The Democratic People's Republic of Korea" +msgstr "Republika Demokratike Popullore e Koresë" + +msgid "Republic of Korea" +msgstr "Republika e Koresë" + +msgid "Kuwait" +msgstr "Kuvaiti" + +msgid "Cayman Islands" +msgstr "Ishujt Cayman" + +msgid "Kazakhstan" +msgstr "Kazakistani" + +msgid "Lao People's Democratic Republic" +msgstr "Republika Popullore Demokratike e Laos" + +msgid "Lebanon" +msgstr "Liban" + +msgid "Saint Lucia" +msgstr "Sankt Lucia" + +msgid "Liechtenstein" +msgstr "Likhtenshtejn" + +msgid "Sri Lanka" +msgstr "Shri Lanka" + +msgid "Liberia" +msgstr "Liberia" + +msgid "Lesotho" +msgstr "Lesoto" + +msgid "Lithuania" +msgstr "Lituania" + +msgid "Luxembourg" +msgstr "Luksemburgu" + +msgid "Latvia" +msgstr "Latvia" + +msgid "Libyan Arab Jamahiriya" +msgstr "Jamahiriya Libiane Arabe" + +msgid "Morocco" +msgstr "Maroko" + +msgid "Monaco" +msgstr "Monako" + +msgid "Republic of Moldova" +msgstr "Republika e Moldovës" + +msgid "Montenegro" +msgstr "Mali i Zi" + +msgid "Saint Martin" +msgstr "Saint Martin" + +msgid "Madagascar" +msgstr "Madagaskari" + +msgid "Marshall Islands" +msgstr "Ishujt Marshall" + +msgid "The Former Yugoslav Republic of Macedonia" +msgstr "Ish-Republika Jugosllave e Maqedonisë" + +msgid "Mali" +msgstr "Mali" + +msgid "Myanmar" +msgstr "Myanmari" + +msgid "Mongolia" +msgstr "Mongolia" + +msgid "Macao" +msgstr "Makao" + +msgid "Northern Mariana Islands" +msgstr "Ishujt Veriorë të Marianëve" + +msgid "Martinique" +msgstr "Martinikë" + +msgid "Mauritania" +msgstr "Mauritania" + +msgid "Montserrat" +msgstr "Montserrat" + +msgid "Malta" +msgstr "Malta" + +msgid "Mauritius" +msgstr "Mauritiusi" + +msgid "Maldives" +msgstr "Maldivene" + +msgid "Malawi" +msgstr "Malavi" + +msgid "Mexico" +msgstr "Meksiko" + +msgid "Malaysia" +msgstr "Malajzia" + +msgid "Mozambique" +msgstr "Mozambiku" + +msgid "Namibia" +msgstr "Namibia" + +msgid "New Caledonia" +msgstr "Kadelonia e Re" + +msgid "Niger" +msgstr "Nigeri" + +msgid "Norfolk Island" +msgstr "Ishujt Norfolk" + +msgid "Nigeria" +msgstr "Nigeria" + +msgid "Nicaragua" +msgstr "Nikaragua" + +msgid "Netherlands" +msgstr "Hollanda" + +msgid "Norway" +msgstr "Norvegjia" + +msgid "Nepal" +msgstr "Nepali" + +msgid "Nauru" +msgstr "Nauru" + +msgid "Niue" +msgstr "Niue" + +msgid "New Zealand" +msgstr "Zelanda e Re" + +msgid "Oman" +msgstr "Omani" + +msgid "Panama" +msgstr "Panama" + +msgid "Peru" +msgstr "Peru" + +msgid "French Polynesia" +msgstr "Polinezia Franceze" + +msgid "Papua New Guinea" +msgstr "Papua Guinea e Re" + +msgid "Philippines" +msgstr "Filipinet" + +msgid "Pakistan" +msgstr "Pakistani" + +msgid "Poland" +msgstr "Polonia" + +msgid "Saint Pierre and Miquelon" +msgstr "Sankt Pierre dhe Mikelon" + +msgid "Pitcairn Islands" +msgstr "Ishujt Pitcairn " + +msgid "Puerto Rico" +msgstr "Puerto Riko" + +msgid "Palestinian Territory" +msgstr "Territoret Palestineze" + +msgid "Portugal" +msgstr "Portugalia" + +msgid "Palau" +msgstr "Palau" + +msgid "Paraguay" +msgstr "Paraguai" + +msgid "Qatar" +msgstr "Katari" + +msgid "Réunion" +msgstr "Réunion" + +msgid "Romania" +msgstr "Romania" + +msgid "Serbia" +msgstr "Serbia" + +msgid "Russian Federation" +msgstr "Federata Ruse" + +msgid "Rwanda" +msgstr "Ruanda" + +msgid "Saudi Arabia" +msgstr "Arabia Saudite" + +msgid "Solomon Islands" +msgstr "Ishujt Solomon" + +msgid "Seychelles" +msgstr "Seikelles" + +msgid "Sudan" +msgstr "Sudani" + +msgid "Sweden" +msgstr "Suedia" + +msgid "Singapore" +msgstr "Singapuri" + +msgid "Saint Helena" +msgstr "Saint Helena" + +msgid "Slovenia" +msgstr "Sllovenia" + +msgid "Svalbard and Jan Mayen" +msgstr "Svallbardi dhe Jan Mayeni" + +msgid "Slovakia" +msgstr "Sllovakia" + +msgid "Sierra Leone" +msgstr "Sierra Leone" + +msgid "San Marino" +msgstr "San Marino" + +msgid "Senegal" +msgstr "Senegali" + +msgid "Somalia" +msgstr "Somalia" + +msgid "Suriname" +msgstr "Surinami" + +msgid "Sao Tome and Principe" +msgstr "Sao Tome dhe Principe" + +msgid "El Salvador" +msgstr "El Salvador" + +msgid "Syrian Arab Republic" +msgstr "Republika Arabe e Sirisë" + +msgid "Swaziland" +msgstr "Svaziland" + +msgid "Turks and Caicos Islands" +msgstr "Ishujt Turks dhe Kaikos" + +msgid "Chad" +msgstr "Çadi" + +msgid "French Southern Territories" +msgstr "Territoret Jugore Franceze" + +msgid "Togo" +msgstr "Togo" + +msgid "Thailand" +msgstr "Tailanda" + +msgid "Tajikistan" +msgstr "Taxhikistani" + +msgid "Tokelau" +msgstr "Tokelau" + +msgid "Timor-Leste" +msgstr "Timor-Leste" + +msgid "Turkmenistan" +msgstr "Turkmenistani" + +msgid "Tunisia" +msgstr "Tunizia" + +msgid "Tonga" +msgstr "Tonga" + +msgid "Turkey" +msgstr "Turqia" + +msgid "Trinidad and Tobago" +msgstr "Triniadi dhe Tobago" + +msgid "Tuvalu" +msgstr "Tuvalu" + +msgid "Taiwan" +msgstr "Taivani" + +msgid "United Republic of Tanzania" +msgstr "Republika e Bashkuar e Tanzanisë" + +msgid "Ukraine" +msgstr "Ukraina" + +msgid "Uganda" +msgstr "Uganda" + +msgid "United States Minor Outlying Islands" +msgstr "United States Minor Outlying Islands" + +msgid "United States" +msgstr "Shtetet e Bashkuara" + +msgid "Uruguay" +msgstr "Uruguaji" + +msgid "Uzbekistan" +msgstr "Uzbekistani" + +msgid "Holy See (Vatican City State)" +msgstr "Holy See (Qytetshteti i Vatikanit) " + +msgid "Saint Vincent and the Grenadines" +msgstr "Sankt Vincenti dhe Grenadinet" + +msgid "Venezuela" +msgstr "Venezuela" + +msgid "Virgin Islands" +msgstr "Ishujt Virgin" + +msgid "Viet Nam" +msgstr "Vietnami" + +msgid "Vanuatu" +msgstr "Vanuatu" + +msgid "Wallis and Futuna" +msgstr "Wallis dhe Futuna" + +msgid "Samoa" +msgstr "Samoa" + +msgid "Yemen" +msgstr "Jemeni" + +msgid "Mayotte" +msgstr "Mayote" + +msgid "South Africa" +msgstr "Afrika Jugore" + +msgid "Zambia" +msgstr "Zambia" + +msgid "Zimbabwe" +msgstr "Zimbabve" diff --git a/apps/routerconsole/locale-countries/messages_uk.po b/apps/routerconsole/locale-countries/messages_uk.po new file mode 100644 index 0000000000..656243e9ee --- /dev/null +++ b/apps/routerconsole/locale-countries/messages_uk.po @@ -0,0 +1,764 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# LinuxChata, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-10-14 13:33+0000\n" +"PO-Revision-Date: 2014-07-18 21:09+0000\n" +"Last-Translator: LinuxChata\n" +"Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/projects/p/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" + +msgid "Anonymous Proxy" +msgstr "Анонімні проксі" + +msgid "Satellite Provider" +msgstr "Супутниковий провайдер" + +msgid "Andorra" +msgstr "Андорра" + +msgid "United Arab Emirates" +msgstr "Об'єднані Арабські Емірати" + +msgid "Afghanistan" +msgstr "Афганістан" + +msgid "Antigua and Barbuda" +msgstr "Антиґуа і Барбуда" + +msgid "Anguilla" +msgstr "Анґілла" + +msgid "Albania" +msgstr "Албанія" + +msgid "Armenia" +msgstr "Вірменія" + +msgid "Netherlands Antilles" +msgstr "Нідерландські Антильські острови" + +msgid "Angola" +msgstr "Ангола" + +msgid "Antarctica" +msgstr "Антарктика" + +msgid "Argentina" +msgstr "Аргентина" + +msgid "American Samoa" +msgstr "Американське Самоа" + +msgid "Austria" +msgstr "Австрія" + +msgid "Australia" +msgstr "Австралія" + +msgid "Aruba" +msgstr "Аруба" + +msgid "Åland Islands" +msgstr "Аландські острови" + +msgid "Azerbaijan" +msgstr "Азербайджан" + +msgid "Bosnia and Herzegovina" +msgstr "Боснія і Герцеґовина" + +msgid "Barbados" +msgstr "Барбадос" + +msgid "Bangladesh" +msgstr "Бангладеш" + +msgid "Belgium" +msgstr "Бельгія" + +msgid "Burkina Faso" +msgstr "Буркіна Фасо" + +msgid "Bulgaria" +msgstr "Болгарія" + +msgid "Bahrain" +msgstr "Бахрейн" + +msgid "Burundi" +msgstr "Бурунді" + +msgid "Benin" +msgstr "Бенін" + +msgid "Bermuda" +msgstr "Бермуда" + +msgid "Brunei Darussalam" +msgstr "Бруней Даруссалам" + +msgid "Bolivia" +msgstr "Болівія" + +msgid "Brazil" +msgstr "Бразилія" + +msgid "Bahamas" +msgstr "Багами" + +msgid "Bhutan" +msgstr "Бутан" + +msgid "Bouvet Island" +msgstr "Буве" + +msgid "Botswana" +msgstr "Ботсвана" + +msgid "Belarus" +msgstr "Білорусія" + +msgid "Belize" +msgstr "Беліз" + +msgid "Canada" +msgstr "Канада" + +msgid "Cocos (Keeling) Islands" +msgstr "Кокосові (Кілінгові) острови" + +msgid "The Democratic Republic of the Congo" +msgstr "Демократична Республіка Конго" + +msgid "Central African Republic" +msgstr "Центральна Африканська Республіка" + +msgid "Congo" +msgstr "Конго" + +msgid "Switzerland" +msgstr "Швейцарія" + +msgid "Cote D'Ivoire" +msgstr "Кот д'Івуар" + +msgid "Cook Islands" +msgstr "Острови Кука" + +msgid "Chile" +msgstr "Чилі" + +msgid "Cameroon" +msgstr "Камерун" + +msgid "China" +msgstr "Китай" + +msgid "Colombia" +msgstr "Колумбія" + +msgid "Costa Rica" +msgstr "Коста Ріка" + +msgid "Serbia and Montenegro" +msgstr "Сербія та Чорногорія" + +msgid "Cuba" +msgstr "Куба" + +msgid "Cape Verde" +msgstr "Кабо-Верде" + +msgid "Curaçao" +msgstr "Кюрасао" + +msgid "Christmas Island" +msgstr "Острів Різдва" + +msgid "Cyprus" +msgstr "Кіпр" + +msgid "Czech Republic" +msgstr "Чеська Республіка" + +msgid "Germany" +msgstr "Німеччина" + +msgid "Djibouti" +msgstr "Джибуті" + +msgid "Denmark" +msgstr "Данія" + +msgid "Dominica" +msgstr "Домініка" + +msgid "Dominican Republic" +msgstr "Домініканська Республіка" + +msgid "Algeria" +msgstr "Алжир" + +msgid "Ecuador" +msgstr "Еквадор" + +msgid "Estonia" +msgstr "Естонія" + +msgid "Egypt" +msgstr "Єгипет" + +msgid "Western Sahara" +msgstr "Західна Сахара" + +msgid "Eritrea" +msgstr "Еритрея" + +msgid "Spain" +msgstr "Іспанія" + +msgid "Ethiopia" +msgstr "Ефіопія" + +msgid "European Union" +msgstr "Європейський Союз" + +msgid "Finland" +msgstr "Фінляндія" + +msgid "Fiji" +msgstr "Фіджі" + +msgid "Falkland Islands (Malvinas)" +msgstr "Фолклендські острови (Мальвінські)" + +msgid "Federated States of Micronesia" +msgstr "Федеративні Штати Мікронезії" + +msgid "Faroe Islands" +msgstr "Фарерські острови" + +msgid "France" +msgstr "Франція" + +msgid "Gabon" +msgstr "Ґабон" + +msgid "United Kingdom" +msgstr "Об'єднане Королівство" + +msgid "Grenada" +msgstr "Ґренада" + +msgid "Georgia" +msgstr "Грузія" + +msgid "French Guiana" +msgstr "Французька Гвіана" + +msgid "Guernsey" +msgstr "Гернсі" + +msgid "Ghana" +msgstr "Ґана" + +msgid "Gibraltar" +msgstr "Ґібралтар" + +msgid "Greenland" +msgstr "Ґренландія" + +msgid "Gambia" +msgstr "Ґамбія" + +msgid "Guinea" +msgstr "Ґвінея" + +msgid "Guadeloupe" +msgstr "Ґваделупа" + +msgid "Equatorial Guinea" +msgstr "Екваторіальна Ґвінея" + +msgid "Greece" +msgstr "Греція" + +msgid "South Georgia and the South Sandwich Islands" +msgstr "Південна Джорджія та Південні Сандвічеві острови" + +msgid "Guatemala" +msgstr "Ґватемала" + +msgid "Guam" +msgstr "Ґуам" + +msgid "Guinea-Bissau" +msgstr "Ґвінея-Біссау" + +msgid "Guyana" +msgstr "Ґвіана" + +msgid "Hong Kong" +msgstr "Гон-Конґ" + +msgid "Honduras" +msgstr "Гондурас" + +msgid "Croatia" +msgstr "Хорватія" + +msgid "Haiti" +msgstr "Гаїті" + +msgid "Hungary" +msgstr "Угорщина" + +msgid "Indonesia" +msgstr "Індонезія" + +msgid "Ireland" +msgstr "Ірландія" + +msgid "Israel" +msgstr "Ізраїль" + +msgid "Isle of Man" +msgstr "Острів Мен" + +msgid "India" +msgstr "Індія" + +msgid "British Indian Ocean Territory" +msgstr "Британська територія в Індійському океані" + +msgid "Iraq" +msgstr "Ірак" + +msgid "Islamic Republic of Iran" +msgstr "Ісламська Республіка Іран" + +msgid "Iceland" +msgstr "Ісландія" + +msgid "Italy" +msgstr "Італія" + +msgid "Jersey" +msgstr "Джерсі (острів)" + +msgid "Jamaica" +msgstr "Ямайка" + +msgid "Jordan" +msgstr "Іорданія" + +msgid "Japan" +msgstr "Японія" + +msgid "Kenya" +msgstr "Кенія" + +msgid "Kyrgyzstan" +msgstr "Киргизстан" + +msgid "Cambodia" +msgstr "Камбоджа" + +msgid "Kiribati" +msgstr "Кірібаті" + +msgid "Comoros" +msgstr "Комори" + +msgid "Saint Kitts and Nevis" +msgstr "Федерація Сент-Кіттс і Невіс" + +msgid "The Democratic People's Republic of Korea" +msgstr "Корейська Народно-Демократична Республіка" + +msgid "Republic of Korea" +msgstr "Республіка Корея" + +msgid "Kuwait" +msgstr "Кувейт" + +msgid "Cayman Islands" +msgstr "Кайманові острови" + +msgid "Kazakhstan" +msgstr "Казахстан" + +msgid "Lao People's Democratic Republic" +msgstr "Лаоська Народно-Демократична Республіка" + +msgid "Lebanon" +msgstr "Ливан" + +msgid "Saint Lucia" +msgstr "Санта Люсія" + +msgid "Liechtenstein" +msgstr "Ліхтенштейн" + +msgid "Sri Lanka" +msgstr "Шрі Ланка" + +msgid "Liberia" +msgstr "Ліберія" + +msgid "Lesotho" +msgstr "Лесото" + +msgid "Lithuania" +msgstr "Литва" + +msgid "Luxembourg" +msgstr "Люксембург" + +msgid "Latvia" +msgstr "Латвія" + +msgid "Libyan Arab Jamahiriya" +msgstr "Лівія" + +msgid "Morocco" +msgstr "Марокко" + +msgid "Monaco" +msgstr "Монако" + +msgid "Republic of Moldova" +msgstr "Республіка Молдова" + +msgid "Montenegro" +msgstr "Чорногорія " + +msgid "Saint Martin" +msgstr "Сен-Ма́ртен" + +msgid "Madagascar" +msgstr "Мадагаскар" + +msgid "Marshall Islands" +msgstr "Маршаллові острови" + +msgid "The Former Yugoslav Republic of Macedonia" +msgstr "Македонія" + +msgid "Mali" +msgstr "Малі" + +msgid "Myanmar" +msgstr "М'янма" + +msgid "Mongolia" +msgstr "Монголія" + +msgid "Macao" +msgstr "Аоминь" + +msgid "Northern Mariana Islands" +msgstr "Північні Маріанські острови" + +msgid "Martinique" +msgstr "Мартиніка" + +msgid "Mauritania" +msgstr "Мавританія" + +msgid "Montserrat" +msgstr "Монтсеррат" + +msgid "Malta" +msgstr "Мальта" + +msgid "Mauritius" +msgstr "Маврикій" + +msgid "Maldives" +msgstr "Мальдиви" + +msgid "Malawi" +msgstr "Малаві" + +msgid "Mexico" +msgstr "Мексика" + +msgid "Malaysia" +msgstr "Малайзія" + +msgid "Mozambique" +msgstr "Мозамбік" + +msgid "Namibia" +msgstr "Намібія" + +msgid "New Caledonia" +msgstr "Нова Каледонія" + +msgid "Niger" +msgstr "Нігер" + +msgid "Norfolk Island" +msgstr "Острів Норфолк" + +msgid "Nigeria" +msgstr "Нігерія" + +msgid "Nicaragua" +msgstr "Нікарагуа" + +msgid "Netherlands" +msgstr "Нідерланди" + +msgid "Norway" +msgstr "Норвегія" + +msgid "Nepal" +msgstr "Непал" + +msgid "Nauru" +msgstr "Науру" + +msgid "Niue" +msgstr "Науру" + +msgid "New Zealand" +msgstr "Нова Зеландія" + +msgid "Oman" +msgstr "Оман" + +msgid "Panama" +msgstr "Панама" + +msgid "Peru" +msgstr "Перу" + +msgid "French Polynesia" +msgstr "Французька Полінезія" + +msgid "Papua New Guinea" +msgstr "Папуа Нова Ґвінея" + +msgid "Philippines" +msgstr "Філіппіни" + +msgid "Pakistan" +msgstr "Пакістан" + +msgid "Poland" +msgstr "Польща" + +msgid "Saint Pierre and Miquelon" +msgstr "Сен-П'єр і Мікелон" + +msgid "Pitcairn Islands" +msgstr "Острови Піткерн" + +msgid "Puerto Rico" +msgstr "Пуерто Ріко" + +msgid "Palestinian Territory" +msgstr "Ізраїль" + +msgid "Portugal" +msgstr "Португалія" + +msgid "Palau" +msgstr "Палау" + +msgid "Paraguay" +msgstr "Парагвай" + +msgid "Qatar" +msgstr "Катар" + +msgid "Réunion" +msgstr "Реуніон" + +msgid "Romania" +msgstr "Румунія" + +msgid "Serbia" +msgstr "Сербія" + +msgid "Russian Federation" +msgstr "Російська Федерація" + +msgid "Rwanda" +msgstr "Руанда" + +msgid "Saudi Arabia" +msgstr "Саудівська Аравія" + +msgid "Solomon Islands" +msgstr "Соломонові острови" + +msgid "Seychelles" +msgstr "Сейшели" + +msgid "Sudan" +msgstr "Судан" + +msgid "Sweden" +msgstr "Швеція" + +msgid "Singapore" +msgstr "Сингапур" + +msgid "Saint Helena" +msgstr "Острів Святої Єлени" + +msgid "Slovenia" +msgstr "Словенія" + +msgid "Svalbard and Jan Mayen" +msgstr "Шпіцберген і Ян-Маєн" + +msgid "Slovakia" +msgstr "Словаччина" + +msgid "Sierra Leone" +msgstr "Сьєрра Леоне" + +msgid "San Marino" +msgstr "Сан Маріно" + +msgid "Senegal" +msgstr "Сенегал" + +msgid "Somalia" +msgstr "Сомалі" + +msgid "Suriname" +msgstr "Сурінам" + +msgid "Sao Tome and Principe" +msgstr "Сан-Томе і Принсіпі" + +msgid "El Salvador" +msgstr "Ель Сальвадор" + +msgid "Syrian Arab Republic" +msgstr "Сирійська Арабська республіка" + +msgid "Swaziland" +msgstr "Свазиленд" + +msgid "Turks and Caicos Islands" +msgstr "Острови Теркс і Кайкос" + +msgid "Chad" +msgstr "Чад" + +msgid "French Southern Territories" +msgstr "Французькі Південні території" + +msgid "Togo" +msgstr "Тоґо" + +msgid "Thailand" +msgstr "Таїланд" + +msgid "Tajikistan" +msgstr "Таджикістан" + +msgid "Tokelau" +msgstr "Токелау" + +msgid "Timor-Leste" +msgstr "Східний Тимор" + +msgid "Turkmenistan" +msgstr "Туркменістан" + +msgid "Tunisia" +msgstr "Туніс" + +msgid "Tonga" +msgstr "Тонґа" + +msgid "Turkey" +msgstr "Туреччина" + +msgid "Trinidad and Tobago" +msgstr "Тринідад і Тобаґо" + +msgid "Tuvalu" +msgstr "Тувалу" + +msgid "Taiwan" +msgstr "Тайвань" + +msgid "United Republic of Tanzania" +msgstr "Об'єднана Республіка Танзанія" + +msgid "Ukraine" +msgstr "Україна" + +msgid "Uganda" +msgstr "Уґанда" + +msgid "United States Minor Outlying Islands" +msgstr "Зовнішні малі острови США" + +msgid "United States" +msgstr "США" + +msgid "Uruguay" +msgstr "Уругвай" + +msgid "Uzbekistan" +msgstr "Узбекістан" + +msgid "Holy See (Vatican City State)" +msgstr "Святий Престол (Ватикан)" + +msgid "Saint Vincent and the Grenadines" +msgstr "Сент Вінсент і Ґренадіни" + +msgid "Venezuela" +msgstr "Венесуела" + +msgid "Virgin Islands" +msgstr "Віргінські острови" + +msgid "Viet Nam" +msgstr "В'єтнам" + +msgid "Vanuatu" +msgstr "Вануату" + +msgid "Wallis and Futuna" +msgstr "Волліс і Футуна" + +msgid "Samoa" +msgstr "Самоа" + +msgid "Yemen" +msgstr "Ємен" + +msgid "Mayotte" +msgstr "Майотта" + +msgid "South Africa" +msgstr "Південна Африка" + +msgid "Zambia" +msgstr "Замбія" + +msgid "Zimbabwe" +msgstr "Зимбабве" diff --git a/apps/routerconsole/locale-news/messages_he.po b/apps/routerconsole/locale-news/messages_he.po new file mode 100644 index 0000000000..a9d0256347 --- /dev/null +++ b/apps/routerconsole/locale-news/messages_he.po @@ -0,0 +1,66 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# GenghisKhan <genghiskhan@gmx.ca>, 2014 +# GenghisKhan <genghiskhan@gmx.ca>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-07-13 21:46+0000\n" +"PO-Revision-Date: 2014-02-23 16:51+0000\n" +"Last-Translator: kytv <killyourtv@i2pmail.org>\n" +"Language-Team: Hebrew (http://www.transifex.com/projects/p/I2P/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Congratulations on getting I2P installed!" +msgstr "ברכותינו על כך שהתקנת I2P!" + +msgid "Welcome to I2P!" +msgstr "ברוך בואך אל I2P!" + +#, java-format +msgid "Please {0}have patience{1} as I2P boots up and finds peers." +msgstr "" + +#, java-format +msgid "" +"While you are waiting, please {0}adjust your bandwidth settings{1} on the " +"{2}configuration page{3}." +msgstr "" + +msgid "" +"Also you can setup your browser to use the I2P proxy to reach eepsites." +msgstr "" + +msgid "" +"Just enter 127.0.0.1 (or localhost) port 4444 as a http proxy into your " +"browser settings." +msgstr "" + +msgid "Do not use SOCKS for this." +msgstr "אל תשתמש ב-SOCKS לשם זאת." + +#, java-format +msgid "" +"More information can be found on the {0}I2P browser proxy setup page{1}." +msgstr "" + +#, java-format +msgid "" +"Once you have a \"shared clients\" destination listed on the left, please " +"{0}check out{1} our {2}FAQ{3}." +msgstr "" + +#, java-format +msgid "" +"Point your IRC client to {0}localhost:6668{1} and say hi to us on " +"{2}#i2p{3}." +msgstr "" diff --git a/apps/routerconsole/locale-news/messages_ko.po b/apps/routerconsole/locale-news/messages_ko.po new file mode 100644 index 0000000000..062765aa81 --- /dev/null +++ b/apps/routerconsole/locale-news/messages_ko.po @@ -0,0 +1,65 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Choi Yeon-Ung <kqwe1859@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-07-13 21:46+0000\n" +"PO-Revision-Date: 2014-02-23 16:51+0000\n" +"Last-Translator: kytv <killyourtv@i2pmail.org>\n" +"Language-Team: Korean (http://www.transifex.com/projects/p/I2P/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Congratulations on getting I2P installed!" +msgstr "I2P 설치를 축하드립니다!" + +msgid "Welcome to I2P!" +msgstr "I2P에 환영합니다!" + +#, java-format +msgid "Please {0}have patience{1} as I2P boots up and finds peers." +msgstr "I2P가 시작되고 피어를 찾는 동안 {0} 기다려 주세요{1}." + +#, java-format +msgid "" +"While you are waiting, please {0}adjust your bandwidth settings{1} on the " +"{2}configuration page{3}." +msgstr "기다리는 동안, {2}설정 페이지{3}에서 {0}대역폭 설정을 조정{1}해 주세요." + +msgid "" +"Also you can setup your browser to use the I2P proxy to reach eepsites." +msgstr "또한 eepsite들을 접속하기 위해 I2P의 프록시를 사용하도록 브라우저를 설정할 수 있습니다." + +msgid "" +"Just enter 127.0.0.1 (or localhost) port 4444 as a http proxy into your " +"browser settings." +msgstr "127.0.0.1 (또는 localhost) 포트 4444를 HTTP 프록시로 브라우저 설정에 입력하면 됩니다." + +msgid "Do not use SOCKS for this." +msgstr "SOCKS를 사용하지 마십시요." + +#, java-format +msgid "" +"More information can be found on the {0}I2P browser proxy setup page{1}." +msgstr "{0}I2P 브라우저 프록시 설정 페이지{1}에서 더 많은 정보를 얻을 수 있습니다." + +#, java-format +msgid "" +"Once you have a \"shared clients\" destination listed on the left, please " +"{0}check out{1} our {2}FAQ{3}." +msgstr "\"공유된 클라이언트\"의 행선지가 왼쪽에 있습니다. {2}FAQ{3}를 {0}참조해 주세요{1}." + +#, java-format +msgid "" +"Point your IRC client to {0}localhost:6668{1} and say hi to us on " +"{2}#i2p{3}." +msgstr "" diff --git a/apps/routerconsole/locale-news/messages_nb.po b/apps/routerconsole/locale-news/messages_nb.po new file mode 100644 index 0000000000..fa2b24d532 --- /dev/null +++ b/apps/routerconsole/locale-news/messages_nb.po @@ -0,0 +1,65 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Allan Nordhøy <comradekingu@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-07-13 21:46+0000\n" +"PO-Revision-Date: 2014-05-01 19:52+0000\n" +"Last-Translator: Allan Nordhøy <comradekingu@gmail.com>\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/projects/p/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" + +msgid "Congratulations on getting I2P installed!" +msgstr "" + +msgid "Welcome to I2P!" +msgstr "Velkommen til I2P!" + +#, java-format +msgid "Please {0}have patience{1} as I2P boots up and finds peers." +msgstr "{0}vær tolmodig{1} i påvente av I2P-oppstart og tilknytning til likemenn." + +#, java-format +msgid "" +"While you are waiting, please {0}adjust your bandwidth settings{1} on the " +"{2}configuration page{3}." +msgstr "" + +msgid "" +"Also you can setup your browser to use the I2P proxy to reach eepsites." +msgstr "" + +msgid "" +"Just enter 127.0.0.1 (or localhost) port 4444 as a http proxy into your " +"browser settings." +msgstr "" + +msgid "Do not use SOCKS for this." +msgstr "" + +#, java-format +msgid "" +"More information can be found on the {0}I2P browser proxy setup page{1}." +msgstr "" + +#, java-format +msgid "" +"Once you have a \"shared clients\" destination listed on the left, please " +"{0}check out{1} our {2}FAQ{3}." +msgstr "" + +#, java-format +msgid "" +"Point your IRC client to {0}localhost:6668{1} and say hi to us on " +"{2}#i2p{3}." +msgstr "" diff --git a/apps/routerconsole/locale-news/messages_uk.po b/apps/routerconsole/locale-news/messages_uk.po new file mode 100644 index 0000000000..52d73bebf6 --- /dev/null +++ b/apps/routerconsole/locale-news/messages_uk.po @@ -0,0 +1,67 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Anton Zub <azb.0x7dc@gmail.com>, 2014 +# jonny_nut, 2014 +# LinuxChata, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-07-13 21:46+0000\n" +"PO-Revision-Date: 2014-06-22 10:26+0000\n" +"Last-Translator: LinuxChata\n" +"Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/projects/p/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" + +msgid "Congratulations on getting I2P installed!" +msgstr "Ґратулюємо за успішне виконання установки I2P!" + +msgid "Welcome to I2P!" +msgstr "Ласкаво просимо в I2P!" + +#, java-format +msgid "Please {0}have patience{1} as I2P boots up and finds peers." +msgstr "Будь ласка {0}майте терпіння{1} поки I2P завантажиться і визначить пірів." + +#, java-format +msgid "" +"While you are waiting, please {0}adjust your bandwidth settings{1} on the " +"{2}configuration page{3}." +msgstr "" + +msgid "" +"Also you can setup your browser to use the I2P proxy to reach eepsites." +msgstr "Також Ви можете налагодити Ваш браузер для використанні I2P-проксі для доступу до захищених веб-вузлів" + +msgid "" +"Just enter 127.0.0.1 (or localhost) port 4444 as a http proxy into your " +"browser settings." +msgstr "Просто введіть 127.0.0.1 (чи localhost) і вкажіть порт 4444 як параметри http-проксі у налаштуваннях Вашого браузера." + +msgid "Do not use SOCKS for this." +msgstr "Не використовуйте SOCKS для цього." + +#, java-format +msgid "" +"More information can be found on the {0}I2P browser proxy setup page{1}." +msgstr "Додаткова інформація доступна на {0}I2P сторінці налагодення проксі браузера{1}." + +#, java-format +msgid "" +"Once you have a \"shared clients\" destination listed on the left, please " +"{0}check out{1} our {2}FAQ{3}." +msgstr "" + +#, java-format +msgid "" +"Point your IRC client to {0}localhost:6668{1} and say hi to us on " +"{2}#i2p{3}." +msgstr "" diff --git a/apps/susidns/locale/messages_tr.po b/apps/susidns/locale/messages_tr.po new file mode 100644 index 0000000000..bbfe4d5aa0 --- /dev/null +++ b/apps/susidns/locale/messages_tr.po @@ -0,0 +1,703 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the susidns package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# Kaya Zeren <kayazeren@gmail.com>, 2013 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-06 18:27+0000\n" +"PO-Revision-Date: 2014-02-06 18:45+0000\n" +"Last-Translator: kytv <killyourtv@i2pmail.org>\n" +"Language-Team: Turkish (Turkey) (http://www.transifex.com/projects/p/I2P/language/tr_TR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr_TR\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:130 +#, java-format +msgid "Host name \"{0}\" contains illegal character {1}" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:143 +#: ../src/java/src/i2p/susi/dns/AddressBean.java:145 +#: ../src/java/src/i2p/susi/dns/AddressBean.java:152 +#, java-format +msgid "Host name cannot start with \"{0}\"" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:147 +#: ../src/java/src/i2p/susi/dns/AddressBean.java:149 +#, java-format +msgid "Host name cannot end with \"{0}\"" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:154 +#, java-format +msgid "Host name cannot contain \"{0}\"" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:157 +#, java-format +msgid "" +"Host name \"{0}\" requires conversion to ASCII but the conversion library is" +" unavailable in this JVM" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:218 +msgid "None" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:226 +msgid "Hashcash" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:228 +msgid "Hidden" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:230 +msgid "Signed" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressBean.java:232 +#, java-format +msgid "Type {0}" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:201 +#, java-format +msgid "One result for search within filtered list." +msgid_plural "{0} results for search within filtered list." +msgstr[0] "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:205 +#, java-format +msgid "Filtered list contains 1 entry." +msgid_plural "Filtered list contains {0} entries." +msgstr[0] "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:210 +#, java-format +msgid "One result for search." +msgid_plural "{0} results for search." +msgstr[0] "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:219 +#, java-format +msgid "Address book contains 1 entry." +msgid_plural "Address book contains {0} entries." +msgstr[0] "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:235 +#, java-format +msgid "Showing {0} of {1}" +msgstr "{0} / {1} görüntüleniyor" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:257 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:227 +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:410 +msgid "Add" +msgstr "Ekleyin" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:257 +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:268 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:227 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:239 +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:408 +msgid "Replace" +msgstr "Değiştirin" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:267 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:238 +#, java-format +msgid "Host name {0} is already in address book, unchanged." +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:269 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:240 +#, java-format +msgid "" +"Host name {0} is already in address book with a different destination. Click" +" \"Replace\" to overwrite." +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:282 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:253 +#, java-format +msgid "Destination added for {0}." +msgstr "{0} için hedef eklendi." + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:284 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:255 +#, java-format +msgid "Destination changed for {0}." +msgstr "{0} için hedef değiştirildi." + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:286 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:257 +msgid "Warning - host name does not end with \".i2p\"" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:291 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:265 +msgid "Invalid Base 64 destination." +msgstr "Base 64 hedefi geçersiz." + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:297 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:271 +#, java-format +msgid "Invalid host name \"{0}\"." +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:300 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:274 +msgid "Please enter a host name and destination" +msgstr "Lütfen bir sunucu adı ve hedef yazın" + +#. clear search when deleting +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:304 +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:325 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:278 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:303 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:267 +msgid "Delete Entry" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:304 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:278 +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:349 +msgid "Delete Selected" +msgstr "Seçileri Silin" + +#. parameter is a host name +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:318 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:295 +#, java-format +msgid "Destination {0} deleted." +msgstr "{0} hedefi silindi." + +#. parameter will always be >= 2 +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:321 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:298 +#, java-format +msgid "1 destination deleted." +msgid_plural "{0} destinations deleted." +msgstr[0] "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:323 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:300 +msgid "No entries selected to delete." +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:331 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:307 +msgid "Address book saved." +msgstr "" + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:334 +msgid "ERROR: Could not write addressbook file." +msgstr "HATA: Adres defteri dosyasına yazılamadı." + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:339 +#: ../src/java/src/i2p/susi/dns/ConfigBean.java:139 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:311 +#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:141 +msgid "" +"Invalid form submission, probably because you used the \"back\" or " +"\"reload\" button on your browser. Please resubmit." +msgstr "Büyük olasılıkla web tarayıcınızdaki \"Geri\" ya da \"Yenile\" düğmesine tıkladığınızdan, gönderilen form geçersiz sayıldı. Lütfen yeniden gönderin." + +#: ../src/java/src/i2p/susi/dns/AddressbookBean.java:341 +#: ../src/java/src/i2p/susi/dns/ConfigBean.java:141 +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:313 +#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:143 +msgid "" +"If the problem persists, verify that you have cookies enabled in your " +"browser." +msgstr "" + +#: ../src/java/src/i2p/susi/dns/ConfigBean.java:130 +#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:116 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:153 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:145 +msgid "Save" +msgstr "Kaydedin" + +#: ../src/java/src/i2p/susi/dns/ConfigBean.java:132 +msgid "Configuration saved." +msgstr "Ayarlar kaydedildi." + +#: ../src/java/src/i2p/susi/dns/ConfigBean.java:133 +#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:135 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:151 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:143 +msgid "Reload" +msgstr "Yeniden yükleyin" + +#: ../src/java/src/i2p/susi/dns/ConfigBean.java:135 +msgid "Configuration reloaded." +msgstr "Ayarlar yeniden yüklendi" + +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:100 +#, java-format +msgid "{0} address book in {1} database" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:248 +msgid "Manually added via SusiDNS" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:262 +#, java-format +msgid "Failed to add Destination for {0} to naming service {1}" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/NamingServiceBean.java:286 +#, java-format +msgid "Failed to delete Destination for {0} from naming service {1}" +msgstr "" + +#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:128 +msgid "" +"Subscriptions saved, updating addressbook from subscription sources now." +msgstr "Abonelikler kaydedildi, adres defteri abonelik kaynaklarına göre güncelleniyor." + +#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:133 +msgid "Subscriptions saved." +msgstr "Abonelikler kaydedildi." + +#: ../src/java/src/i2p/susi/dns/SubscriptionsBean.java:137 +msgid "Subscriptions reloaded." +msgstr "Abonelikler yeniden yüklendi" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:125 +msgid "address book" +msgstr "adres defteri" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:131 +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:147 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:125 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:141 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:116 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:132 +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:130 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:117 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:133 +msgid "Overview" +msgstr "Özet" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:133 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:127 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:118 +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:116 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:119 +msgid "Address books" +msgstr "Adres defterleri" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:135 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:129 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:120 +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:118 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:121 +msgid "private" +msgstr "kişisel" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:137 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:131 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:122 +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:120 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:123 +msgid "master" +msgstr "genel" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:139 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:133 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:124 +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:122 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:125 +msgid "router" +msgstr "yöneltici" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:141 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:135 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:126 +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:124 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:127 +msgid "published" +msgstr "yayınlanmış" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:143 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:137 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:128 +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:126 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:129 +msgid "Subscriptions" +msgstr "Abonelikler" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:145 +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:139 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:130 +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:128 +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:131 +msgid "Configuration" +msgstr "Ayarlar" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:149 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:134 +msgid "Address book" +msgstr "Adres defteri" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:154 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:139 +msgid "Storage" +msgstr "Kayıt yeri" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:172 +msgid "Filter" +msgstr "Süzgeç" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:175 +msgid "other" +msgstr "diğer" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:177 +msgid "all" +msgstr "tümü" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:191 +msgid "Current filter" +msgstr "Geçerli süzgeç" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:196 +msgid "clear filter" +msgstr "süzgeci temizleyin" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:209 +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:213 +msgid "Search" +msgstr "Arayın" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:246 +msgid "Name" +msgstr "Ad" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:248 +msgid "Links" +msgstr "Bağlantılar" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:250 +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:402 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:259 +msgid "Destination" +msgstr "Hedef" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:286 +msgid "Mark for deletion" +msgstr "Silmek üzere işaretleyin" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:305 +msgid "Base 32 address" +msgstr "Base 32 adresi" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:309 +msgid "More information on this entry" +msgstr "Kayıtla ilgili diğer bilgiler" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:312 +msgid "details" +msgstr "ayrıntılar" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:347 +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:406 +msgid "Cancel" +msgstr "İptal" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:381 +msgid "This address book is empty." +msgstr "Bu adres defteri boş." + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:396 +msgid "Add new destination" +msgstr "Yeni hedef ekleyin" + +#: ../src/tmp/i2p/susi/dns/jsp/addressbook_jsp.java:398 +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:165 +msgid "Host Name" +msgstr "Sunucu Adı" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:119 +msgid "configuration" +msgstr "ayarlar" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:155 +msgid "Hints" +msgstr "İpuçları" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:157 +msgid "" +"File and directory paths here are relative to the addressbook's working " +"directory, which is normally ~/.i2p/addressbook/ (Linux) or " +"%APPDATA%\\I2P\\addressbook\\ (Windows)." +msgstr "Buradaki dosya ve klasör yolları, normal durumda ~i2p/addressbook/ (Linux) ya da %APPDATA%\\I2P\\addressbook\\ (Windows) şeklinde olan adres defteri klasörüne göre yazılmıştır. " + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:159 +msgid "" +"If you want to manually add lines to an addressbook, add them to the private" +" or master addressbooks." +msgstr "El ile eklenen satırlar kişisel ya da genel adres defterine eklenmelidir." + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:160 +msgid "" +"The router addressbook and the published addressbook are updated by the " +"addressbook application." +msgstr "Adres defteri uygulaması yöneltici ve yayınlanan adres defterlerini güncelledi." + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:162 +msgid "" +"When you publish your addressbook, ALL destinations from the master and " +"router addressbooks appear there." +msgstr "Adres defteri yayınlandığında, genel ve yöneltici adres defterlerindeki TÜM hedefler burada görüntülenir." + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:163 +msgid "" +"Use the private addressbook for private destinations, these are not " +"published." +msgstr "Kişisel adres defterine kaydedilen hedefler yayınlanmaz." + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:165 +msgid "Options" +msgstr "Ayarlar" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:167 +msgid "File containing the list of subscriptions URLs (no need to change)" +msgstr "Abonelik İnternet adreslerini içeren dosya (değiştirilmesine gerek yok)" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:169 +msgid "Update interval in hours" +msgstr "Saat cinsinden güncelleme aralığı" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:171 +msgid "" +"Your public hosts.txt file (choose a path within your webserver document " +"root)" +msgstr "Herkese açık hosts.txt dosyası (web sunucunuzun belge kök klasörü altında bir yol seçin)" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:173 +msgid "Your hosts.txt (don't change)" +msgstr "Hosts.txt dosyanız (değiştirmeyin)" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:175 +msgid "Your personal addressbook, these hosts will be published" +msgstr "Bu sunucuların yayınlanacağı kişisel adres defteriniz" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:177 +msgid "Your private addressbook, it is never published" +msgstr "Asla yayınlanmayacak kişisel adres defteriniz" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:179 +msgid "Port for your eepProxy (no need to change)" +msgstr "eepProxy kapınız (değiştirilmesine gerek yok)" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:181 +msgid "Hostname for your eepProxy (no need to change)" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:183 +msgid "Whether to update the published addressbook" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:185 +msgid "" +"File containing the etags header from the fetched subscription URLs (no need" +" to change)" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:187 +msgid "" +"File containing the modification timestamp for each fetched subscription URL" +" (no need to change)" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:189 +msgid "File to log activity to (change to /dev/null if you like)" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/config_jsp.java:191 +msgid "Name of the theme to use (defaults to 'light')" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:110 +msgid "addressbook" +msgstr "adres defteri" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:179 +msgid "Encoded Name" +msgstr "Kodlanmış Ad" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:193 +msgid "Base 32 Address" +msgstr "Base 32 Adresi" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:201 +msgid "Base 64 Hash" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:207 +msgid "Address Helper" +msgstr "Adres Yardımcısı" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:213 +msgid "link" +msgstr "bağlantı" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:217 +msgid "Public Key" +msgstr "Genel Anahtar" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:219 +msgid "ElGamal 2048 bit" +msgstr "ElGamal 2048 bit" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:223 +msgid "Signing Key" +msgstr "İmzalama Anahtarı" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:225 +msgid "DSA 1024 bit" +msgstr "DSA 1024 bit" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:229 +msgid "Certificate" +msgstr "Sertifika" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:235 +msgid "Added Date" +msgstr "Eklendiği Tarih" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:241 +msgid "Source" +msgstr "Kaynak" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:247 +msgid "Last Modified" +msgstr "Son Değişiklik" + +#: ../src/tmp/i2p/susi/dns/jsp/details_jsp.java:253 +msgid "Notes" +msgstr "Notlar" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:110 +msgid "Introduction" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:132 +msgid "What is the addressbook?" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:134 +msgid "The addressbook application is part of your I2P installation." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:135 +msgid "" +"It regularly updates your hosts.txt file from distributed sources or " +"\"subscriptions\"." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:137 +msgid "" +"In the default configuration, the address book is only subscribed to " +"www.i2p2.i2p." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:138 +msgid "" +"Subscribing to additional sites is easy, just add them to your <a " +"href=\"subscriptions\">subscriptions</a> file." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:140 +msgid "" +"For more information on naming in I2P, see <a href=\"http://i2p-" +"projekt.i2p/naming.html\" target=\"_top\">the overview</a>." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:142 +msgid "How does the addressbook application work?" +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:144 +msgid "" +"The addressbook application regularly polls your subscriptions and merges " +"their content into your \"router\" address book." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:145 +msgid "" +"Then it merges your \"master\" address book into the router address book as " +"well." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:146 +msgid "" +"If configured, the router address book is now written to the \"published\" " +"address book, which will be publicly available if you are running an " +"eepsite." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:148 +msgid "" +"The router also uses a private address book (not shown in the picture), " +"which is not merged or published." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:149 +msgid "" +"Hosts in the private address book can be accessed by you but their addresses" +" are never distributed to others." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/index_jsp.java:150 +msgid "" +"The private address book can also be used for aliases of hosts in your other" +" address books." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:111 +msgid "subscriptions" +msgstr "abonelikler" + +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:147 +msgid "The subscription file contains a list of i2p URLs." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:148 +msgid "" +"The addressbook application regularly checks this list for new eepsites." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:149 +msgid "Those URLs refer to published hosts.txt files." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:150 +msgid "" +"The default subscription is the hosts.txt from www.i2p2.i2p, which is " +"updated infrequently." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:151 +msgid "" +"So it is a good idea to add additional subscriptions to sites that have the " +"latest addresses." +msgstr "" + +#: ../src/tmp/i2p/susi/dns/jsp/subscriptions_jsp.java:153 +msgid "See the FAQ for a list of subscription URLs." +msgstr "" diff --git a/apps/susimail/locale/messages_da.po b/apps/susimail/locale/messages_da.po new file mode 100644 index 0000000000..ec198d424c --- /dev/null +++ b/apps/susimail/locale/messages_da.po @@ -0,0 +1,520 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the susimail package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# +# Translators: +# cacapo <handelsehorisont@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: I2P\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-05-01 11:45+0000\n" +"PO-Revision-Date: 2014-05-01 12:00+0000\n" +"Last-Translator: zzzi2p\n" +"Language-Team: Danish (http://www.transifex.com/projects/p/I2P/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/src/i2p/susi/webmail/MailPart.java:207 +#, java-format +msgid "No encoder found for encoding \\''{0}\\''." +msgstr "Ingen encoder funden for kodning \\\"{0}\\\"." + +#: src/src/i2p/susi/webmail/WebMail.java:304 +#: src/src/i2p/susi/webmail/WebMail.java:318 +#: src/src/i2p/susi/webmail/WebMail.java:1005 +msgid "Re:" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:308 +#: src/src/i2p/susi/webmail/WebMail.java:322 +#: src/src/i2p/susi/webmail/WebMail.java:1043 +msgid "Fwd:" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:594 +msgid "unknown" +msgstr "ukendt" + +#: src/src/i2p/susi/webmail/WebMail.java:615 +msgid "Warning: no charset found, fallback to US-ASCII." +msgstr "Advarsel, ingen tegnsæt fundet, bruger US-ASCII." + +#: src/src/i2p/susi/webmail/WebMail.java:629 +#, java-format +msgid "Charset \\''{0}\\'' not supported." +msgstr "Tegnsæt \\\"{0}\\\" ikke understøttet." + +#: src/src/i2p/susi/webmail/WebMail.java:633 +#, java-format +msgid "Part ({0}) not shown, because of {1}" +msgstr "Del ({0}) er ikke vist på grund af {1}" + +#: src/src/i2p/susi/webmail/WebMail.java:669 +#: src/src/i2p/susi/webmail/WebMail.java:672 +#, java-format +msgid "Download attachment {0}" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:673 +msgid "File is packed into a zipfile for security reasons." +msgstr "Filen er pakket ind i en zip-fil af sikkerhedsmæssige årsager." + +#: src/src/i2p/susi/webmail/WebMail.java:678 +#, java-format +msgid "Attachment ({0})." +msgstr "Vedhæftet fil ({0})." + +#: src/src/i2p/susi/webmail/WebMail.java:729 +msgid "Need username for authentication." +msgstr "Behøver brugernavn til godkendelse" + +#: src/src/i2p/susi/webmail/WebMail.java:733 +msgid "Need password for authentication." +msgstr "Behøver adgangskode til godkendelse" + +#: src/src/i2p/susi/webmail/WebMail.java:737 +msgid "Need hostname for connect." +msgstr "Behøver værtsnavn til forbindelse" + +#: src/src/i2p/susi/webmail/WebMail.java:742 +msgid "Need port number for pop3 connect." +msgstr "Behøver portnummer til POP3 forbindelse." + +#: src/src/i2p/susi/webmail/WebMail.java:749 +msgid "POP3 port number is not in range 0..65535." +msgstr "POP3 nummer er ikke inden for rækkevidde 0..65535." + +#: src/src/i2p/susi/webmail/WebMail.java:755 +msgid "POP3 port number is invalid." +msgstr "POP3 portnummer er ugyldigt." + +#: src/src/i2p/susi/webmail/WebMail.java:761 +msgid "Need port number for smtp connect." +msgstr "Behøver port nummer til smtp forbindelse." + +#: src/src/i2p/susi/webmail/WebMail.java:768 +msgid "SMTP port number is not in range 0..65535." +msgstr "SMTP nummer er ikke inden for rækkevidde 0..65535." + +#: src/src/i2p/susi/webmail/WebMail.java:774 +msgid "SMTP port number is invalid." +msgstr "SMTP portnummer er ugyldigt." + +#: src/src/i2p/susi/webmail/WebMail.java:848 +msgid "User logged out." +msgstr "Bruger logget ud" + +#: src/src/i2p/susi/webmail/WebMail.java:851 +msgid "Internal error, lost connection." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1008 +#, java-format +msgid "On {0} {1} wrote:" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1055 +msgid "begin forwarded mail" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1077 +msgid "end forwarded mail" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1084 +#: src/src/i2p/susi/webmail/WebMail.java:2290 +msgid "Could not fetch mail body." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1114 +msgid "Message id not valid." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1152 +msgid "Configuration reloaded" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1213 +#, java-format +msgid "No Encoding found for {0}" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1217 +#, java-format +msgid "Could not encode data: {0}" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1222 +#, java-format +msgid "Error reading uploaded file: {0}" +msgstr "" + +#. error if we get here +#: src/src/i2p/susi/webmail/WebMail.java:1307 +#: src/src/i2p/susi/webmail/WebMail.java:1310 +msgid "Attachment not found." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1357 +#: src/src/i2p/susi/webmail/WebMail.java:1483 +msgid "Invalid pagesize number, resetting to default value." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1381 +msgid "No messages marked for deletion." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1397 +#, java-format +msgid "1 message deleted." +msgid_plural "{0} messages deleted." +msgstr[0] "" +msgstr[1] "" + +#: src/src/i2p/susi/webmail/WebMail.java:1462 +msgid "Configuration saved" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1673 +#: src/src/i2p/susi/webmail/WebMail.java:2085 +msgid "Login" +msgstr "" + +#. mailbox.getNumMails() forces a connection, don't use it +#. Not only does it slow things down, but a failure causes all our messages to +#. "vanish" +#. subtitle = ngettext("1 Message", "{0} Messages", +#. sessionObject.mailbox.getNumMails()); +#: src/src/i2p/susi/webmail/WebMail.java:1678 +#, java-format +msgid "1 Message" +msgid_plural "{0} Messages" +msgstr[0] "" +msgstr[1] "" + +#: src/src/i2p/susi/webmail/WebMail.java:1684 +msgid "Show Message" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1686 +msgid "New Message" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1688 +msgid "Configuration" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1699 +msgid "SusiMail" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1712 +msgid "Message has not been sent. Do you want to discard it?" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1773 +#, java-format +msgid "Error decoding content: {0}" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1833 +msgid "no subject" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1850 +msgid "Found no valid sender address." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1856 +#, java-format +msgid "Found no valid address in \\''{0}\\''." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1877 +msgid "No recipients found." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1941 +msgid "Mail sent." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1985 +msgid "Send" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:1986 +#: src/src/i2p/susi/webmail/WebMail.java:2199 +#: src/src/i2p/susi/webmail/WebMail.java:2330 +msgid "Cancel" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2029 +#: src/src/i2p/susi/webmail/WebMail.java:2128 +#: src/src/i2p/susi/webmail/WebMail.java:2278 +msgid "From" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2030 +msgid "To" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2031 +msgid "Cc" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2032 +msgid "Bcc" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2033 +msgid "Bcc to self" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2034 +#: src/src/i2p/susi/webmail/WebMail.java:2129 +#: src/src/i2p/susi/webmail/WebMail.java:2280 +msgid "Subject" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2037 +msgid "Add Attachment" +msgstr "" + +#. TODO disable/hide in JS if no file selected +#: src/src/i2p/susi/webmail/WebMail.java:2039 +msgid "Add another attachment" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2045 +msgid "Attachments" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2054 +msgid "Delete selected attachments" +msgstr "" + +#. current postman hq length limits 16/12, new postman version 32/32 +#: src/src/i2p/susi/webmail/WebMail.java:2073 +msgid "User" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2074 +msgid "Password" +msgstr "Adgangskode" + +#: src/src/i2p/susi/webmail/WebMail.java:2079 +msgid "Host" +msgstr "Vært" + +#: src/src/i2p/susi/webmail/WebMail.java:2080 +msgid "POP3 Port" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2081 +msgid "SMTP Port" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2086 +msgid "Read Mail Offline" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2090 +#: src/src/i2p/susi/webmail/WebMail.java:2218 +msgid "Settings" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2093 +msgid "Learn about I2P mail" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2094 +msgid "Create Account" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2107 +#: src/src/i2p/susi/webmail/WebMail.java:2262 +msgid "New" +msgstr "" + +#. In theory, these are valid and will apply to the first checked message, +#. but that's not obvious and did it work? +#. button( REPLY, _("Reply") ) + +#. button( REPLYALL, _("Reply All") ) + +#. button( FORWARD, _("Forward") ) + spacer + +#. button( DELETE, _("Delete") ) + spacer + +#: src/src/i2p/susi/webmail/WebMail.java:2114 +msgid "Check Mail" +msgstr "" + +#. if (Config.hasConfigFile()) +#. out.println(button( RELOAD, _("Reload Config") ) + spacer); +#: src/src/i2p/susi/webmail/WebMail.java:2117 +msgid "Logout" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2130 +#: src/src/i2p/susi/webmail/WebMail.java:2282 +msgid "Date" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2133 +msgid "Size" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2173 +msgid "Message is new" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2175 +msgid "Message has an attachment" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2177 +msgid "Message is spam" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2185 +msgid "No messages" +msgstr "" + +#. TODO ngettext +#: src/src/i2p/susi/webmail/WebMail.java:2197 +msgid "Really delete the marked messages?" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2198 +msgid "Yes, really delete them!" +msgstr "" + +#. TODO js +#: src/src/i2p/susi/webmail/WebMail.java:2202 +msgid "Delete Selected" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2204 +msgid "Mark All" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2206 +msgid "Clear All" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2231 +#: src/src/i2p/susi/webmail/WebMail.java:2232 +msgid "First" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2231 +#: src/src/i2p/susi/webmail/WebMail.java:2232 +#: src/src/i2p/susi/webmail/WebMail.java:2268 +msgid "Previous" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2234 +#, java-format +msgid "Page {0} of {1}" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2237 +#: src/src/i2p/susi/webmail/WebMail.java:2238 +msgid "Last" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2237 +#: src/src/i2p/susi/webmail/WebMail.java:2238 +#: src/src/i2p/susi/webmail/WebMail.java:2270 +msgid "Next" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2250 +msgid "Really delete this message?" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2250 +msgid "Yes, really delete it!" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2263 +msgid "Reply" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2264 +msgid "Reply All" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2265 +msgid "Forward" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2266 +msgid "Delete" +msgstr "Slet" + +#: src/src/i2p/susi/webmail/WebMail.java:2269 +msgid "Back to Folder" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2294 +msgid "Could not fetch mail." +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2312 +msgid "Folder Page Size" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2315 +msgid "Set" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2318 +msgid "Advanced Configuration" +msgstr "" + +#: src/src/i2p/susi/webmail/WebMail.java:2329 +msgid "Save Configuration" +msgstr "" + +#. this appears in the UI so translate +#: src/src/i2p/susi/webmail/pop3/POP3MailBox.java:102 +#: src/src/i2p/susi/webmail/pop3/POP3MailBox.java:747 +#: src/src/i2p/susi/webmail/pop3/POP3MailBox.java:789 +msgid "No response from server" +msgstr "" + +#: src/src/i2p/susi/webmail/pop3/POP3MailBox.java:664 +msgid "Error connecting to server" +msgstr "" + +#: src/src/i2p/susi/webmail/pop3/POP3MailBox.java:669 +#: src/src/i2p/susi/webmail/pop3/POP3MailBox.java:672 +msgid "Error opening mailbox" +msgstr "" + +#: src/src/i2p/susi/webmail/pop3/POP3MailBox.java:1021 +#: src/src/i2p/susi/webmail/smtp/SMTPClient.java:249 +msgid "Login failed" +msgstr "" + +#: src/src/i2p/susi/webmail/smtp/SMTPClient.java:214 +msgid "Cannot connect" +msgstr "" + +#: src/src/i2p/susi/webmail/smtp/SMTPClient.java:225 +#: src/src/i2p/susi/webmail/smtp/SMTPClient.java:237 +msgid "Server refused connection" +msgstr "" + +#. TODO which recipient? +#: src/src/i2p/susi/webmail/smtp/SMTPClient.java:262 +msgid "Mail rejected" +msgstr "" + +#: src/src/i2p/susi/webmail/smtp/SMTPClient.java:276 +#: src/src/i2p/susi/webmail/smtp/SMTPClient.java:279 +msgid "Error sending mail" +msgstr "" From 7c3d3b41282b9abf8992d8b1fdf6eef342e6a3e3 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 13 Aug 2014 19:07:39 +0000 Subject: [PATCH 31/40] fix dependency checking for ministreaming po files --- apps/ministreaming/java/bundle-messages.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ministreaming/java/bundle-messages.sh b/apps/ministreaming/java/bundle-messages.sh index 82974403c6..37d9ae4654 100755 --- a/apps/ministreaming/java/bundle-messages.sh +++ b/apps/ministreaming/java/bundle-messages.sh @@ -51,8 +51,8 @@ do find $JPATHS -name *.java -newer $i > $TMPFILE fi - if [ -s build/obj/net/i2p/streaming/messages_$LG.class -a \ - build/obj/net/i2p/streaming/messages_$LG.class -nt $i -a \ + if [ -s build/obj/net/i2p/client/streaming/messages_$LG.class -a \ + build/obj/net/i2p/client/streaming/messages_$LG.class -nt $i -a \ ! -s $TMPFILE ] then continue From 9c38e1e191e822ba184a78f285eb87a3a5a0d7b2 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 13 Aug 2014 19:10:25 +0000 Subject: [PATCH 32/40] * Console: Escaping fix (ticket #1346) --- .../java/src/net/i2p/router/web/ConfigUpdateHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java index b1fb3379c9..6ff7f35649 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java @@ -210,7 +210,7 @@ public class ConfigUpdateHandler extends FormHandler { try { oldFreq = Long.parseLong(oldFreqStr); } catch (NumberFormatException nfe) {} if (_refreshFrequency != oldFreq) { changes.put(PROP_REFRESH_FREQUENCY, ""+_refreshFrequency); - addFormNotice(_("Updating refresh frequency to {0}", + addFormNoticeNoEscape(_("Updating refresh frequency to {0}", _refreshFrequency <= 0 ? _("Never") : DataHelper.formatDuration2(_refreshFrequency))); } From eb97ef4cb2680e403abefbd140edfef7f5d8924d Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 13 Aug 2014 19:17:26 +0000 Subject: [PATCH 33/40] * i2psnark: Fix add torrent NPE --- apps/i2psnark/java/src/org/klomp/snark/Snark.java | 2 +- history.txt | 4 ++++ router/java/src/net/i2p/router/RouterVersion.java | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java index 297f37c6b0..7f0c0305b0 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java @@ -484,7 +484,7 @@ public class Snark this.torrent = torrent; this.infoHash = ih; this.additionalTrackerURL = trackerURL; - this.rootDataDir = new File(rootDir); + this.rootDataDir = rootDir != null ? new File(rootDir) : null; // null only for FetchAndAdd extension stopped = true; id = generateID(); diff --git a/history.txt b/history.txt index aa11143a60..93eabed0f7 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,7 @@ +2014-08-13 zzz + * Console: Escaping fix (ticket #1346) + * i2psnark: Fix add torrent NPE + 2014-08-10 zzz Prop from i2p.i2p.zzz.snarkconfig: * i2psnark: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 0725033fa6..f6e6df3a5c 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 3; + public final static long BUILD = 4; /** for example "-test" */ public final static String EXTRA = ""; From d5edcbc6e1818ad906a030113aba1a171ebe05cc Mon Sep 17 00:00:00 2001 From: dg2-new <dg2-new@mail.i2p> Date: Wed, 13 Aug 2014 21:29:17 +0000 Subject: [PATCH 34/40] * Console, EventLog: Added {BECAME,NOT}_FLOODFILL events. They will now be shown on the console's /events page when the router's ff status changes. * EventLog: Fix a minor typo. --- .../java/src/net/i2p/router/web/EventLogHelper.java | 2 ++ history.txt | 3 ++- .../router/networkdb/kademlia/FloodfillMonitorJob.java | 9 ++++++++- router/java/src/net/i2p/router/util/EventLog.java | 4 +++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/EventLogHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/EventLogHelper.java index d6882f0a6d..00293a5678 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/EventLogHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/EventLogHelper.java @@ -32,6 +32,7 @@ public class EventLogHelper extends FormHandler { private static final String ALL = "all"; private static final String[] _events = new String[] { EventLog.ABORTED, _x("Aborted startup"), + EventLog.BECAME_FLOODFILL, _x("Enabled floodfill"), EventLog.CHANGE_IP, _x("Changed IP"), EventLog.CHANGE_PORT, _x("Changed port"), EventLog.CLOCK_SHIFT, _x("Clock shifted"), @@ -41,6 +42,7 @@ public class EventLogHelper extends FormHandler { EventLog.INSTALL_FAILED, _x("Install failed"), EventLog.NETWORK, _x("Network error"), EventLog.NEW_IDENT, _x("New router identity"), + EventLog.NOT_FLOODFILL, _x("Disabled floodfill"), EventLog.OOM, _x("Out of memory error"), EventLog.REKEYED, _x("New router identity"), EventLog.RESEED, _x("Reseeded router"), diff --git a/history.txt b/history.txt index 93eabed0f7..e333f71cb5 100644 --- a/history.txt +++ b/history.txt @@ -1,6 +1,7 @@ -2014-08-13 zzz +2014-08-13 zzz, dg * Console: Escaping fix (ticket #1346) * i2psnark: Fix add torrent NPE + * Console, EventLog: add BECAME_FLOODFILL and NOT_FLOODFILL, they are now shown at the /events page when the router changes its floodfill state 2014-08-10 zzz Prop from i2p.i2p.zzz.snarkconfig: diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java index c61ed40f18..99c4beda29 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java @@ -9,6 +9,7 @@ import net.i2p.router.JobImpl; import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.router.peermanager.PeerProfile; +import net.i2p.router.util.EventLog; import net.i2p.util.Log; /** @@ -42,8 +43,14 @@ class FloodfillMonitorJob extends JobImpl { boolean wasFF = _facade.floodfillEnabled(); boolean ff = shouldBeFloodfill(); _facade.setFloodfillEnabled(ff); - if (ff != wasFF) + if (ff != wasFF) { + if(ff) { + getContext().router().eventLog().addEvent(EventLog.BECAME_FLOODFILL); + } else { + getContext().router().eventLog().addEvent(EventLog.NOT_FLOODFILL); + } getContext().router().rebuildRouterInfo(); + } if (_log.shouldLog(Log.INFO)) _log.info("Should we be floodfill? " + ff); int delay = (REQUEUE_DELAY / 2) + getContext().random().nextInt(REQUEUE_DELAY); diff --git a/router/java/src/net/i2p/router/util/EventLog.java b/router/java/src/net/i2p/router/util/EventLog.java index 086fbbdc5f..ef59c5fc6b 100644 --- a/router/java/src/net/i2p/router/util/EventLog.java +++ b/router/java/src/net/i2p/router/util/EventLog.java @@ -32,15 +32,17 @@ public class EventLog { /** for convenience, not required */ public static final String ABORTED = "aborted"; + public static final String BECAME_FLOODFILL = "becameFloodfill"; public static final String CHANGE_IP = "changeIP"; public static final String CHANGE_PORT = "changePort"; public static final String CLOCK_SHIFT = "clockShift"; public static final String CRASHED = "crashed"; public static final String CRITICAL = "critical"; public static final String INSTALLED = "installed"; - public static final String INSTALL_FAILED = "intallFailed"; + public static final String INSTALL_FAILED = "installFailed"; public static final String NETWORK = "network"; public static final String NEW_IDENT = "newIdent"; + public static final String NOT_FLOODFILL = "disabledFloodfill"; public static final String OOM = "oom"; public static final String REKEYED = "rekeyed"; public static final String RESEED = "reseed"; From 3839c8d1c07fc1b0b217bb935bf3a7eb15a718ec Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Fri, 15 Aug 2014 11:48:02 +0000 Subject: [PATCH 35/40] * I2CP: Lookup synch cleanups --- .../src/net/i2p/client/I2PSessionImpl.java | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java index d146726474..d0ed301380 100644 --- a/core/java/src/net/i2p/client/I2PSessionImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionImpl.java @@ -149,7 +149,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa * Since 0.9.11, key is either a Hash or a String * @since 0.8.9 */ - private static final Map<Object, Destination> _lookupCache = new LHMCache<Object, Destination>(16); + private static final Map<Object, Destination> _lookupCache = new LHMCache<Object, Destination>(64); private static final String MIN_HOST_LOOKUP_VERSION = "0.9.11"; private static final boolean TEST_LOOKUP = false; @@ -1029,6 +1029,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa /** * Called by the message handler * on reception of DestReplyMessage + * @param d non-null */ void destReceived(Destination d) { Hash h = d.calculateHash(); @@ -1037,8 +1038,8 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa } for (LookupWaiter w : _pendingLookups) { if (h.equals(w.hash)) { - w.destination = d; synchronized (w) { + w.destination = d; w.notifyAll(); } } @@ -1048,6 +1049,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa /** * Called by the message handler * on reception of DestReplyMessage + * @param h non-null */ void destLookupFailed(Hash h) { for (LookupWaiter w : _pendingLookups) { @@ -1062,21 +1064,21 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa /** * Called by the message handler * on reception of HostReplyMessage + * @param d non-null * @since 0.9.11 */ void destReceived(long nonce, Destination d) { - // notify by hash - destReceived(d); - // notify by nonce + // notify by nonce and hash + Hash h = d.calculateHash(); for (LookupWaiter w : _pendingLookups) { - if (nonce == w.nonce) { - w.destination = d; - if (w.name != null) { - synchronized (_lookupCache) { + if (nonce == w.nonce || h.equals(w.hash)) { + synchronized (_lookupCache) { + if (w.name != null) _lookupCache.put(w.name, d); - } + _lookupCache.put(h, d); } synchronized (w) { + w.destination = d; w.notifyAll(); } } @@ -1117,8 +1119,8 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa public final String name; /** the request (nonce mode) */ public final long nonce; - /** the reply */ - public volatile Destination destination; + /** the reply; synch on this */ + public Destination destination; public LookupWaiter(Hash h) { this(h, -1); @@ -1178,6 +1180,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa waiter = new LookupWaiter(h); } _pendingLookups.offer(waiter); + Destination rv = null; try { if (_routerSupportsHostLookup) { if (_log.shouldLog(Log.INFO)) @@ -1194,6 +1197,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa try { synchronized (waiter) { waiter.wait(maxWait); + rv = waiter.destination; } } catch (InterruptedException ie) { throw new I2PSessionException("Interrupted", ie); @@ -1201,7 +1205,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa } finally { _pendingLookups.remove(waiter); } - return waiter.destination; + return rv; } /** @@ -1269,6 +1273,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa int nonce = _lookupID.incrementAndGet() & 0x7fffffff; LookupWaiter waiter = new LookupWaiter(name, nonce); _pendingLookups.offer(waiter); + Destination rv = null; try { if (_log.shouldLog(Log.INFO)) _log.info("Sending HostLookup for " + name); @@ -1279,6 +1284,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa try { synchronized (waiter) { waiter.wait(maxWait); + rv = waiter.destination; } } catch (InterruptedException ie) { throw new I2PSessionException("Interrupted", ie); @@ -1286,7 +1292,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa } finally { _pendingLookups.remove(waiter); } - return waiter.destination; + return rv; } /** From 15facc72b395870cff158b267f07d2197ee7bad1 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Fri, 15 Aug 2014 11:49:56 +0000 Subject: [PATCH 36/40] * Console: Escaping fix (ticket #1348) --- .../java/src/net/i2p/router/web/ConfigUIHandler.java | 4 ++-- history.txt | 11 +++++++++-- router/java/src/net/i2p/router/RouterVersion.java | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHandler.java index e9de89c315..7a9b2c406b 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHandler.java @@ -60,12 +60,12 @@ public class ConfigUIHandler extends FormHandler { boolean ok = _context.router().saveConfig(changes, removes); if (ok) { if (!oldTheme.equals(_config)) - addFormNotice(_("Theme change saved.") + + addFormNoticeNoEscape(_("Theme change saved.") + " <a href=\"configui\">" + _("Refresh the page to view.") + "</a>"); if (oldForceMobileConsole != _forceMobileConsole) - addFormNotice(_("Mobile console option saved.") + + addFormNoticeNoEscape(_("Mobile console option saved.") + " <a href=\"configui\">" + _("Refresh the page to view.") + "</a>"); diff --git a/history.txt b/history.txt index e333f71cb5..cf3931dc68 100644 --- a/history.txt +++ b/history.txt @@ -1,7 +1,14 @@ -2014-08-13 zzz, dg +2014-08-15 zzz + * Console: Escaping fix (ticket #1348) + * I2CP: Lookup synch cleanups + +2014-08-13 dg + * Console, EventLog: add BECAME_FLOODFILL and NOT_FLOODFILL, they are now shown + at the /events page when the router changes its floodfill state + +2014-08-13 zzz * Console: Escaping fix (ticket #1346) * i2psnark: Fix add torrent NPE - * Console, EventLog: add BECAME_FLOODFILL and NOT_FLOODFILL, they are now shown at the /events page when the router changes its floodfill state 2014-08-10 zzz Prop from i2p.i2p.zzz.snarkconfig: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index f6e6df3a5c..4e28a2c8d2 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 4; + public final static long BUILD = 5; /** for example "-test" */ public final static String EXTRA = ""; From a3e3a305ce94149b6a682db5a231c06818032421 Mon Sep 17 00:00:00 2001 From: echelon2 <echelon2@mail.i2p> Date: Sun, 17 Aug 2014 14:54:50 +0000 Subject: [PATCH 37/40] removed notification of port 8887 --- apps/routerconsole/jsp/confignet.jsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/routerconsole/jsp/confignet.jsp b/apps/routerconsole/jsp/confignet.jsp index 779bef578f..6c4b6149c3 100644 --- a/apps/routerconsole/jsp/confignet.jsp +++ b/apps/routerconsole/jsp/confignet.jsp @@ -184,7 +184,7 @@ <%=intl._("I2P detected that you are firewalled by a Symmetric NAT.")%> <%=intl._("I2P does not work well behind this type of firewall. You will probably not be able to accept inbound connections, which will limit your participation in the network.")%> <li class="tidylist"><b><%=intl._("ERR - UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart")%></b> - - <%=intl._("I2P was unable to bind to port 8887 or other configured port.")%> + <%=intl._("I2P was unable to bind to the configured port noted on the advanced network configuration page .")%> <%=intl._("Check to see if another program is using the configured port. If so, stop that program or configure I2P to use a different port.")%> <%=intl._("This may be a transient error, if the other program is no longer using the port.")%> <%=intl._("However, a restart is always required after this error.")%> From 51995cc42862914d70605e1b709b911cfa8ae63a Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Mon, 18 Aug 2014 18:52:47 +0000 Subject: [PATCH 38/40] * i2psnark: - Don't send HTML-only headers for icons - Catch IllegalStateException for icons --- .../src/org/klomp/snark/web/BasicServlet.java | 7 ++++++- .../org/klomp/snark/web/I2PSnarkServlet.java | 21 ++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) 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 350a6bb689..d171a3f186 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java @@ -282,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; 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 f03d841bdb..af2e9fa8f4 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -172,10 +172,19 @@ 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(); + + // 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); + } + + _themePath = "/themes/snark/" + _manager.getTheme() + '/'; + _imgPath = _themePath + "images/"; resp.setHeader("X-Frame-Options", "SAMEORIGIN"); resp.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'"); resp.setHeader("X-XSS-Protection", "1; mode=block"); @@ -209,14 +218,6 @@ public class I2PSnarkServlet extends BasicServlet { return; } - // 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); - } - 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") || From 66bbe21a87e25f51157ffa8676146b73cb9cb087 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Mon, 18 Aug 2014 18:57:19 +0000 Subject: [PATCH 39/40] * Tunnels: Use consistent tunnel pair for Delivery Status Message to reduce network connections (ticket #1350) --- history.txt | 7 +++++++ router/java/src/net/i2p/router/RouterVersion.java | 2 +- .../router/message/OutboundClientMessageOneShotJob.java | 3 ++- .../net/i2p/router/tunnel/InboundMessageDistributor.java | 3 ++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/history.txt b/history.txt index cf3931dc68..ac9306c56c 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,10 @@ +2014-08-18 zzz + * i2psnark: + - Don't send HTML-only headers for icons + - Catch IllegalStateException for icons + * Tunnels: Use consistent tunnel pair for Delivery Status Message + to reduce network connections (ticket #1350) + 2014-08-15 zzz * Console: Escaping fix (ticket #1348) * I2CP: Lookup synch cleanups diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 4e28a2c8d2..c10128fe62 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 5; + public final static long BUILD = 6; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java index a550a492c1..5040606e8d 100644 --- a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java +++ b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java @@ -729,7 +729,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl { * */ private TunnelInfo selectInboundTunnel() { - return getContext().tunnelManager().selectInboundTunnel(_from.calculateHash()); + // Use tunnel EP closest to his hash, as a simple cache to minimize connections + return getContext().tunnelManager().selectInboundTunnel(_from.calculateHash(), _to.calculateHash()); } /** diff --git a/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java b/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java index 9830e42bdf..ec3529b48f 100644 --- a/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java +++ b/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java @@ -160,7 +160,8 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver { } else { // ok, they want us to send it remotely, but that'd bust our anonymity, // so we send it out a tunnel first - TunnelInfo out = _context.tunnelManager().selectOutboundTunnel(_client); + // TODO use the OCMOSJ cache to pick OB tunnel we are already using? + TunnelInfo out = _context.tunnelManager().selectOutboundTunnel(_client, target); if (out == null) { if (_log.shouldLog(Log.WARN)) _log.warn("no outbound tunnel to send the client message for " + _client + ": " + msg); From 33b7f08d5c5eea26fc33000aa8c58e0504b2701e Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Tue, 19 Aug 2014 20:34:46 +0000 Subject: [PATCH 40/40] * i2psnark: - Don't filter create torrent form, and fix exception on ':' in file names (ticket #1342) - Don't remap file names on torrents we created, and save remap setting in torrent config file (tickets #571, 771) - Escaping fixes since names may not be remapped - Use better encodePath() from Jetty - Don't say create torrent succeeded when it didn't - Add more sanity checks for torrent creation --- .../src/org/klomp/snark/CompleteListener.java | 1 + .../java/src/org/klomp/snark/MagnetURI.java | 4 +- .../java/src/org/klomp/snark/Snark.java | 9 +- .../src/org/klomp/snark/SnarkManager.java | 64 ++++-- .../java/src/org/klomp/snark/Storage.java | 30 ++- .../src/org/klomp/snark/UpdateRunner.java | 4 + .../src/org/klomp/snark/web/BasicServlet.java | 19 +- .../org/klomp/snark/web/I2PSnarkServlet.java | 130 ++++++++--- .../java/src/org/klomp/snark/web/URIUtil.java | 206 ++++++++++++++++++ history.txt | 11 + .../src/net/i2p/router/RouterVersion.java | 2 +- 11 files changed, 419 insertions(+), 61 deletions(-) create mode 100644 apps/i2psnark/java/src/org/klomp/snark/web/URIUtil.java diff --git a/apps/i2psnark/java/src/org/klomp/snark/CompleteListener.java b/apps/i2psnark/java/src/org/klomp/snark/CompleteListener.java index 77fa9c98b4..bd2f78e531 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/CompleteListener.java +++ b/apps/i2psnark/java/src/org/klomp/snark/CompleteListener.java @@ -57,4 +57,5 @@ public interface CompleteListener { // not really listeners but the easiest way to get back to an optional SnarkManager public long getSavedTorrentTime(Snark snark); public BitField getSavedTorrentBitField(Snark snark); + public boolean getSavedPreserveNamesSetting(Snark snark); } diff --git a/apps/i2psnark/java/src/org/klomp/snark/MagnetURI.java b/apps/i2psnark/java/src/org/klomp/snark/MagnetURI.java index 9044d62ff6..60698a0915 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; diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java index 7f0c0305b0..e9d0937e65 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java @@ -420,14 +420,17 @@ public class Snark try { activity = "Checking storage"; + boolean shouldPreserve = completeListener != null && completeListener.getSavedPreserveNamesSetting(this); if (baseFile == null) { - String base = Storage.filterName(meta.getName()); + 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); + storage = new Storage(_util, baseFile, meta, slistener, shouldPreserve); if (completeListener != null) { storage.check(completeListener.getSavedTorrentTime(this), completeListener.getSavedTorrentBitField(this)); @@ -1141,7 +1144,7 @@ public class Snark else baseFile = new SecureFile(rootDataDir, base); // The following two may throw IOE... - storage = new Storage(_util, baseFile, metainfo, this); + storage = new Storage(_util, baseFile, metainfo, this, false); storage.check(); // ... so don't set meta until here meta = metainfo; diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 3e2e8bcf78..b910e32d58 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -91,8 +91,9 @@ public class SnarkManager implements CompleteListener { 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_BITFIELD_SUFFIX = ".bitfield"; - private static final String PROP_META_PRIORITY_SUFFIX = ".priority"; + private static final String PROP_META_PRESERVE_NAMES = "preserveFileNames"; + //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"; @@ -1335,7 +1336,7 @@ 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. + * 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 @@ -1343,18 +1344,20 @@ public class SnarkManager implements CompleteListener { * 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, File baseFile, 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; + return false; } // so addTorrent won't recheck - saveTorrentStatus(metainfo, bitfield, null, baseFile); // no file priorities + saveTorrentStatus(metainfo, bitfield, null, baseFile, true); // no file priorities try { locked_writeMetaInfo(metainfo, filename, areFilesPublic()); // hold the lock for a long time @@ -1362,8 +1365,10 @@ public class SnarkManager implements CompleteListener { } catch (IOException ioe) { addMessage(_("Failed to copy torrent file to {0}", filename)); _log.error("Failed to write torrent file", ioe); + return false; } } + return true; } /** @@ -1500,14 +1505,39 @@ public class SnarkManager implements CompleteListener { * @return File or null, doesn't necessarily exist * @since 0.9.11 */ - public File getSavedBaseFile(byte[] ih) { + 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)); + } + /** + * 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()); + } + /** * Save the completion status of a torrent and the current time in the config file * for that torrent. @@ -1519,13 +1549,15 @@ public class SnarkManager implements CompleteListener { * @param priorities may be null * @param base may be null */ - public void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, File base) { + private void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, + File base, boolean preserveNames) { synchronized (_configLock) { - locked_saveTorrentStatus(metainfo, bitfield, priorities, base); + locked_saveTorrentStatus(metainfo, bitfield, priorities, base, preserveNames); } } - private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, File base) { + private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, + File base, boolean preserveNames) { byte[] ih = metainfo.getInfoHash(); String bfs; if (bitfield.complete()) { @@ -1537,6 +1569,7 @@ public class SnarkManager implements CompleteListener { Properties config = getConfig(ih); config.setProperty(PROP_META_STAMP, Long.toString(System.currentTimeMillis())); config.setProperty(PROP_META_BITFIELD, bfs); + config.setProperty(PROP_META_PRESERVE_NAMES, Boolean.toString(preserveNames)); if (base != null) config.setProperty(PROP_META_BASE, base.getAbsolutePath()); @@ -1776,10 +1809,11 @@ public class SnarkManager implements CompleteListener { if (meta == null || storage == null) return; StringBuilder buf = new StringBuilder(256); - buf.append("<a href=\"").append(_contextPath).append('/').append(storage.getBaseName()); + String base = DataHelper.escapeHTML(storage.getBaseName()); + buf.append("<a href=\"").append(_contextPath).append('/').append(base); if (meta.getFiles() != null) buf.append('/'); - buf.append("\">").append(storage.getBaseName()).append("</a>"); + buf.append("\">").append(base).append("</a>"); addMessageNoEscape(_("Download finished: {0}", buf.toString())); // + " (" + _("size: {0}B", DataHelper.formatSize2(len)) + ')'); updateStatus(snark); } @@ -1791,7 +1825,8 @@ public class SnarkManager implements CompleteListener { MetaInfo meta = snark.getMetaInfo(); Storage storage = snark.getStorage(); if (meta != null && storage != null) - saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities(), storage.getBase()); + saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities(), + storage.getBase(), storage.getPreserveFileNames()); } /** @@ -1813,7 +1848,8 @@ public class SnarkManager implements CompleteListener { snark.stopTorrent(); return null; } - saveTorrentStatus(meta, storage.getBitField(), null, storage.getBase()); // no file priorities + saveTorrentStatus(meta, storage.getBitField(), null, + storage.getBase(), storage.getPreserveFileNames()); // no file priorities // temp for addMessage() in case canonical throws String name = storage.getBaseName(); try { diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index f0477b4787..efae9baad0 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -66,6 +66,7 @@ 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(); @@ -92,8 +93,9 @@ public class Storage * try to create and/or check all needed files in the MetaInfo. * * @param baseFile the torrent data file or dir + * @param preserveFileNames if true, do not remap names to a 'safe' charset */ - public Storage(I2PSnarkUtil util, File baseFile, 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); @@ -108,6 +110,7 @@ public class Storage List<List<String>> files = metainfo.getFiles(); int sz = files != null ? files.size() : 1; _torrentFiles = new ArrayList<TorrentFile>(sz); + _preserveFileNames = preserveFileNames; } /** @@ -130,6 +133,7 @@ public class Storage _base = baseFile; _log = util.getContext().logManager().getLog(Storage.class); this.listener = listener; + _preserveFileNames = true; // Create names, rafs and lengths arrays. _torrentFiles = getFiles(baseFile); @@ -469,7 +473,12 @@ 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; } /** @@ -618,6 +627,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 @@ -674,13 +696,13 @@ public class Storage * * @param names path elements */ - private static File createFileFromNames(File base, List<String> names, boolean areFilesPublic) throws IOException + private File createFileFromNames(File base, List<String> names, boolean areFilesPublic) throws IOException { File f = null; Iterator<String> it = names.iterator(); while (it.hasNext()) { - String name = filterName(it.next()); + String name = optFilterName(it.next()); if (it.hasNext()) { // Another dir in the hierarchy. diff --git a/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java b/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java index 5812fb49cb..28fe34ef91 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java +++ b/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java @@ -290,6 +290,10 @@ class UpdateRunner implements UpdateTask, CompleteListener { return _smgr.getSavedTorrentBitField(snark); } + public boolean getSavedPreserveNamesSetting(Snark snark) { + return _smgr.getSavedPreserveNamesSetting(snark); + } + //////// end CompleteListener methods private static String linkify(String url) { 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 d171a3f186..b3a1a6a5c3 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/BasicServlet.java @@ -559,14 +559,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/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index af2e9fa8f4..3296ea0f41 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; @@ -73,6 +74,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; @@ -942,7 +944,7 @@ public class I2PSnarkServlet extends BasicServlet { if (taction != null) processTrackerForm(taction, req); } else if ("Create".equals(action)) { - String baseData = req.getParameter("baseFile"); + String baseData = req.getParameter("nofilter_baseFile"); if (baseData != null && baseData.trim().length() > 0) { File baseFile = new File(baseData.trim()); if (!baseFile.isAbsolute()) @@ -954,6 +956,40 @@ public class I2PSnarkServlet extends BasicServlet { // announceURL = announceURLOther; if (baseFile.exists()) { + String torrentName = baseFile.getName(); + if (torrentName.toLowerCase(Locale.US).endsWith(".torrent")) { + _manager.addMessage(_("Cannot add a torrent ending in \".torrent\": {0}", baseFile.getAbsolutePath())); + return; + } + Snark snark = _manager.getTorrentByBaseName(torrentName); + if (snark != null) { + _manager.addMessage(_("Torrent with this name is already running: {0}", torrentName)); + return; + } + if (isParentOf(baseFile,_manager.getDataDir()) || + isParentOf(baseFile, _manager.util().getContext().getBaseDir()) || + isParentOf(baseFile, _manager.util().getContext().getConfigDir())) { + _manager.addMessage(_("Cannot add a torrent including an I2P directory: {0}", baseFile.getAbsolutePath())); + return; + } + Collection<Snark> snarks = _manager.getTorrents(); + for (Snark s : snarks) { + Storage storage = s.getStorage(); + if (storage == null) + continue; + File sbase = storage.getBase(); + if (isParentOf(sbase, baseFile)) { + _manager.addMessage(_("Cannot add torrent {0} inside another torrent: {1}", + baseFile.getAbsolutePath(), sbase)); + return; + } + if (isParentOf(baseFile, sbase)) { + _manager.addMessage(_("Cannot add torrent {0} including another torrent: {1}", + baseFile.getAbsolutePath(), sbase)); + return; + } + } + if (announceURL.equals("none")) announceURL = null; _lastAnnounceURL = announceURL; @@ -1006,7 +1042,9 @@ public class I2PSnarkServlet extends BasicServlet { File torrentFile = new File(_manager.getDataDir(), s.getBaseName() + ".torrent"); // FIXME is the storage going to stay around thanks to the info reference? // now add it, but don't automatically start it - _manager.addTorrent(info, s.getBitField(), torrentFile.getAbsolutePath(), baseFile, true); + boolean ok = _manager.addTorrent(info, s.getBitField(), torrentFile.getAbsolutePath(), baseFile, true); + if (!ok) + return; _manager.addMessage(_("Torrent created for \"{0}\"", baseFile.getName()) + ": " + torrentFile.getAbsolutePath()); if (announceURL != null && !_manager.util().getOpenTrackers().contains(announceURL)) _manager.addMessage(_("Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\"", baseFile.getName())); @@ -1357,7 +1395,7 @@ public class I2PSnarkServlet extends BasicServlet { } } - String encodedBaseName = urlEncode(fullBasename); + String encodedBaseName = encodePath(fullBasename); // File type icon column out.write("</td>\n<td>"); if (isValid) { @@ -1407,7 +1445,7 @@ public class I2PSnarkServlet extends BasicServlet { buf.append("\">"); out.write(buf.toString()); } - out.write(basename); + out.write(DataHelper.escapeHTML(basename)); if (remaining == 0 || isMultiFile) out.write("</a>"); @@ -1786,12 +1824,6 @@ public class I2PSnarkServlet extends BasicServlet { } private void writeSeedForm(PrintWriter out, HttpServletRequest req, List<Tracker> sortedTrackers) throws IOException { - String baseFile = req.getParameter("baseFile"); - if (baseFile == null || baseFile.trim().length() <= 0) - baseFile = ""; - else - baseFile = DataHelper.stripHTML(baseFile); // XSS - out.write("<a name=\"add\"></a><div class=\"newtorrentsection\"><div class=\"snarkNewTorrent\">\n"); // *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file out.write("<form action=\"_post\" method=\"POST\">\n"); @@ -1808,7 +1840,7 @@ public class I2PSnarkServlet extends BasicServlet { //out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n"); out.write(_("Data to seed")); out.write(":<td>" - + "<input type=\"text\" name=\"baseFile\" size=\"58\" value=\"" + baseFile + + "<input type=\"text\" name=\"nofilter_baseFile\" size=\"58\" value=\"" + "\" spellcheck=\"false\" title=\""); out.write(_("File or directory to seed (full path or within the directory {0} )", _manager.getDataDir().getAbsolutePath() + File.separatorChar)); @@ -2211,26 +2243,35 @@ public class I2PSnarkServlet extends BasicServlet { return ((bytes + 512*1024*1024)/(1024*1024*1024)) + " GB"; } - /** @since 0.7.14 */ + /** + * This is for a full URL. For a path only, use encodePath(). + * @since 0.7.14 + */ static String urlify(String s) { return urlify(s, 100); } - /** @since 0.9 */ + /** + * This is for a full URL. For a path only, use encodePath(). + * @since 0.9 + */ private static String urlify(String s, int max) { StringBuilder buf = new StringBuilder(256); // browsers seem to work without doing this but let's be strict String link = urlEncode(s); String display; if (s.length() <= max) - display = link; + display = DataHelper.escapeHTML(link); else - display = urlEncode(s.substring(0, max)) + "…"; + display = DataHelper.escapeHTML(s.substring(0, max)) + "…"; buf.append("<a href=\"").append(link).append("\">").append(display).append("</a>"); return buf.toString(); } - /** @since 0.8.13 */ + /** + * This is for a full URL. For a path only, use encodePath(). + * @since 0.8.13 + */ private static String urlEncode(String s) { return s.replace(";", "%3B").replace("&", "&").replace(" ", "%20") .replace("<", "<").replace(">", ">") @@ -2289,7 +2330,7 @@ public class I2PSnarkServlet extends BasicServlet { * * Get the resource list as a HTML directory listing. * @param xxxr The Resource unused - * @param base The base URL + * @param base The encoded base URL * @param parent True if the parent directory should be included * @param postParams map of POST parameters or null if not a POST * @return String of HTML or null if postParams != null @@ -2298,7 +2339,8 @@ public class I2PSnarkServlet extends BasicServlet { private String getListHTML(File xxxr, String base, boolean parent, Map<String, String[]> postParams) throws IOException { - String title = decodePath(base); + String decodedBase = decodePath(base); + String title = decodedBase; String cpath = _contextPath + '/'; if (title.startsWith(cpath)) title = title.substring(cpath.length()); @@ -2351,7 +2393,7 @@ public class I2PSnarkServlet extends BasicServlet { if (title.endsWith("/")) title = title.substring(0, title.length() - 1); String directory = title; - title = _("Torrent") + ": " + title; + title = _("Torrent") + ": " + DataHelper.escapeHTML(title); buf.append(title); buf.append("").append(HEADER_A).append(_themePath).append(HEADER_B).append("" + "\n
") .append(_("Torrent")) .append(": ") - .append(snark.getBaseName()) + .append(DataHelper.escapeHTML(snark.getBaseName())) .append("
") .append("\"\" ") .append(_("Torrent file")) .append(": ") - .append(fullPath) + .append(DataHelper.escapeHTML(fullPath)) .append("
") .append("\"\" ") .append(_("Data location")) .append(": ") - .append(urlEncode(snark.getStorage().getBase().getPath())) + .append(DataHelper.escapeHTML(snark.getStorage().getBase().getPath())) .append("
\"\" ") .append(_("Up to higher level directory")) .append("
"); @@ -2677,7 +2719,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(""); @@ -2808,6 +2850,36 @@ public class I2PSnarkServlet extends BasicServlet { } } snark.updatePiecePriorities(); - _manager.saveTorrentStatus(snark.getMetaInfo(), storage.getBitField(), storage.getFilePriorities(), storage.getBase()); + _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/URIUtil.java b/apps/i2psnark/java/src/org/klomp/snark/web/URIUtil.java new file mode 100644 index 0000000000..3a9c3088e0 --- /dev/null +++ b/apps/i2psnark/java/src/org/klomp/snark/web/URIUtil.java @@ -0,0 +1,206 @@ +// +// ======================================================================== +// 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. + * @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 ' ': + buf=new StringBuilder(path.length()*2); + break loop; + default: + if (c>127) + { + 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; + default: + if (c<0) + { + buf.append('%'); + toHex(c,buf); + } + else + buf.append((char)c); + continue; + } + } + + } + else + { + for (int i=0;i': + buf.append("%3E"); + continue; + case ' ': + buf.append("%20"); + continue; + default: + buf.append(c); + continue; + } + } + } + //} + + return buf; + } + + /** + * Modded from Jetty TypeUtil + */ + private static void toHex(byte b, StringBuilder buf) + { + 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)); + } +} + + + diff --git a/history.txt b/history.txt index ac9306c56c..68e84e9411 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,14 @@ +2014-08-19 zzz + * i2psnark: + - Don't filter create torrent form, and + fix exception on ':' in file names (ticket #1342) + - Don't remap file names on torrents we created, and + save remap setting in torrent config file (tickets #571, 771) + - Escaping fixes since names may not be remapped + - Use better encodePath() from Jetty + - Don't say create torrent succeeded when it didn't + - Add more sanity checks for base path of created torrent + 2014-08-18 zzz * i2psnark: - Don't send HTML-only headers for icons diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index c10128fe62..fecba78d69 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 6; + public final static long BUILD = 7; /** for example "-test" */ public final static String EXTRA = "";