forked from I2P_Developers/i2p.i2p
* i2psnark:
- Add refresh time option - Add public file permissions option (ticket #501) - Fix configuration of tunnel parameters (ticket #524) - Allow changing I2CP parameters while tunnel is open - Remove duplicated options in I2CP options string - Don't open tunnel when saving config
This commit is contained in:
@@ -44,34 +44,34 @@ import org.klomp.snark.dht.DHT;
|
|||||||
* (but not multiple SnarkManagers, it is still static)
|
* (but not multiple SnarkManagers, it is still static)
|
||||||
*/
|
*/
|
||||||
public class I2PSnarkUtil {
|
public class I2PSnarkUtil {
|
||||||
private I2PAppContext _context;
|
private final I2PAppContext _context;
|
||||||
private Log _log;
|
private final Log _log;
|
||||||
|
|
||||||
private boolean _shouldProxy;
|
private boolean _shouldProxy;
|
||||||
private String _proxyHost;
|
private String _proxyHost;
|
||||||
private int _proxyPort;
|
private int _proxyPort;
|
||||||
private String _i2cpHost;
|
private String _i2cpHost;
|
||||||
private int _i2cpPort;
|
private int _i2cpPort;
|
||||||
private Map<String, String> _opts;
|
private final Map<String, String> _opts;
|
||||||
private I2PSocketManager _manager;
|
private I2PSocketManager _manager;
|
||||||
private boolean _configured;
|
private boolean _configured;
|
||||||
private final Set<Hash> _shitlist;
|
private final Set<Hash> _shitlist;
|
||||||
private int _maxUploaders;
|
private int _maxUploaders;
|
||||||
private int _maxUpBW;
|
private int _maxUpBW;
|
||||||
private int _maxConnections;
|
private int _maxConnections;
|
||||||
private File _tmpDir;
|
private final File _tmpDir;
|
||||||
private int _startupDelay;
|
private int _startupDelay;
|
||||||
private boolean _shouldUseOT;
|
private boolean _shouldUseOT;
|
||||||
|
private boolean _areFilesPublic;
|
||||||
|
private String _openTrackerString;
|
||||||
private DHT _dht;
|
private DHT _dht;
|
||||||
|
|
||||||
public static final int DEFAULT_STARTUP_DELAY = 3;
|
public static final int DEFAULT_STARTUP_DELAY = 3;
|
||||||
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
|
|
||||||
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
|
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
|
||||||
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
|
|
||||||
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
|
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
|
||||||
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
|
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
|
||||||
public static final int MAX_CONNECTIONS = 16; // per torrent
|
public static final int MAX_CONNECTIONS = 16; // per torrent
|
||||||
private static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond";
|
public static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond";
|
||||||
//private static final boolean ENABLE_DHT = true;
|
//private static final boolean ENABLE_DHT = true;
|
||||||
|
|
||||||
public I2PSnarkUtil(I2PAppContext ctx) {
|
public I2PSnarkUtil(I2PAppContext ctx) {
|
||||||
@@ -125,6 +125,8 @@ public class I2PSnarkUtil {
|
|||||||
// can't remove any options this way...
|
// can't remove any options this way...
|
||||||
if (opts != null)
|
if (opts != null)
|
||||||
_opts.putAll(opts);
|
_opts.putAll(opts);
|
||||||
|
// this updates the session options and tells the router
|
||||||
|
setMaxUpBW(_maxUpBW);
|
||||||
_configured = true;
|
_configured = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,6 +136,7 @@ public class I2PSnarkUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This updates the session options and tells the router
|
||||||
* @param limit KBps
|
* @param limit KBps
|
||||||
*/
|
*/
|
||||||
public void setMaxUpBW(int limit) {
|
public void setMaxUpBW(int limit) {
|
||||||
@@ -175,6 +178,12 @@ public class I2PSnarkUtil {
|
|||||||
public int getMaxConnections() { return _maxConnections; }
|
public int getMaxConnections() { return _maxConnections; }
|
||||||
public int getStartupDelay() { return _startupDelay; }
|
public int getStartupDelay() { return _startupDelay; }
|
||||||
|
|
||||||
|
/** @since 0.8.9 */
|
||||||
|
public boolean getFilesPublic() { return _areFilesPublic; }
|
||||||
|
|
||||||
|
/** @since 0.8.9 */
|
||||||
|
public void setFilesPublic(boolean yes) { _areFilesPublic = yes; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to the router, if we aren't already
|
* Connect to the router, if we aren't already
|
||||||
*/
|
*/
|
||||||
@@ -433,14 +442,13 @@ public class I2PSnarkUtil {
|
|||||||
|
|
||||||
/** @param ot non-null */
|
/** @param ot non-null */
|
||||||
public void setOpenTrackerString(String ot) {
|
public void setOpenTrackerString(String ot) {
|
||||||
_opts.put(PROP_OPENTRACKERS, ot);
|
_openTrackerString = ot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOpenTrackerString() {
|
public String getOpenTrackerString() {
|
||||||
String rv = (String) _opts.get(PROP_OPENTRACKERS);
|
if (_openTrackerString == null)
|
||||||
if (rv == null)
|
|
||||||
return DEFAULT_OPENTRACKERS;
|
return DEFAULT_OPENTRACKERS;
|
||||||
return rv;
|
return _openTrackerString;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** comma delimited list open trackers to use as backups */
|
/** comma delimited list open trackers to use as backups */
|
||||||
|
@@ -3,6 +3,7 @@ package org.klomp.snark;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileFilter;
|
import java.io.FileFilter;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@@ -71,17 +72,23 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
public static final String PROP_META_MAGNET_PREFIX = "i2psnark.magnet.";
|
public static final String PROP_META_MAGNET_PREFIX = "i2psnark.magnet.";
|
||||||
|
|
||||||
private static final String CONFIG_FILE = "i2psnark.config";
|
private static final String CONFIG_FILE = "i2psnark.config";
|
||||||
|
public static final String PROP_FILES_PUBLIC = "i2psnark.filesPublic";
|
||||||
public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops
|
public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops
|
||||||
public static final String DEFAULT_AUTO_START = "false";
|
public static final String DEFAULT_AUTO_START = "false";
|
||||||
public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
|
//public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
|
||||||
public static final String DEFAULT_LINK_PREFIX = "file:///";
|
//public static final String DEFAULT_LINK_PREFIX = "file:///";
|
||||||
public static final String PROP_STARTUP_DELAY = "i2psnark.startupDelay";
|
public static final String PROP_STARTUP_DELAY = "i2psnark.startupDelay";
|
||||||
|
public static final String PROP_REFRESH_DELAY = "i2psnark.refreshSeconds";
|
||||||
public static final String PROP_THEME = "i2psnark.theme";
|
public static final String PROP_THEME = "i2psnark.theme";
|
||||||
public static final String DEFAULT_THEME = "ubergine";
|
public static final String DEFAULT_THEME = "ubergine";
|
||||||
|
private static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
|
||||||
|
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
|
||||||
|
|
||||||
public static final int MIN_UP_BW = 2;
|
public static final int MIN_UP_BW = 2;
|
||||||
public static final int DEFAULT_MAX_UP_BW = 10;
|
public static final int DEFAULT_MAX_UP_BW = 10;
|
||||||
public static final int DEFAULT_STARTUP_DELAY = 3;
|
public static final int DEFAULT_STARTUP_DELAY = 3;
|
||||||
|
public static final int DEFAULT_REFRESH_DELAY_SECS = 60;
|
||||||
|
|
||||||
private SnarkManager() {
|
private SnarkManager() {
|
||||||
_snarks = new ConcurrentHashMap();
|
_snarks = new ConcurrentHashMap();
|
||||||
_magnets = new ConcurrentHashSet();
|
_magnets = new ConcurrentHashSet();
|
||||||
@@ -136,20 +143,57 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldAutoStart() {
|
/**
|
||||||
return Boolean.valueOf(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START+"")).booleanValue();
|
* @return default false
|
||||||
|
* @since 0.8.9
|
||||||
|
*/
|
||||||
|
public boolean areFilesPublic() {
|
||||||
|
return Boolean.valueOf(_config.getProperty(PROP_FILES_PUBLIC)).booleanValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean shouldAutoStart() {
|
||||||
|
return Boolean.valueOf(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****
|
||||||
public String linkPrefix() {
|
public String linkPrefix() {
|
||||||
return _config.getProperty(PROP_LINK_PREFIX, DEFAULT_LINK_PREFIX + getDataDir().getAbsolutePath() + File.separatorChar);
|
return _config.getProperty(PROP_LINK_PREFIX, DEFAULT_LINK_PREFIX + getDataDir().getAbsolutePath() + File.separatorChar);
|
||||||
}
|
}
|
||||||
private int getStartupDelayMinutes() {
|
****/
|
||||||
return Integer.valueOf(_config.getProperty(PROP_STARTUP_DELAY)).intValue();
|
|
||||||
|
/**
|
||||||
|
* @return -1 for never
|
||||||
|
* @since 0.8.9
|
||||||
|
*/
|
||||||
|
public int getRefreshDelaySeconds() {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(_config.getProperty(PROP_REFRESH_DELAY));
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
return DEFAULT_REFRESH_DELAY_SECS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getStartupDelayMinutes() {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(_config.getProperty(PROP_STARTUP_DELAY));
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
return DEFAULT_STARTUP_DELAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public File getDataDir() {
|
public File getDataDir() {
|
||||||
String dir = _config.getProperty(PROP_DIR, "i2psnark");
|
String dir = _config.getProperty(PROP_DIR, "i2psnark");
|
||||||
File f = new SecureDirectory(dir);
|
File f;
|
||||||
if (!f.isAbsolute())
|
if (areFilesPublic())
|
||||||
f = new SecureDirectory(_context.getAppDir(), dir);
|
f = new File(dir);
|
||||||
|
else
|
||||||
|
f = new SecureDirectory(dir);
|
||||||
|
if (!f.isAbsolute()) {
|
||||||
|
if (areFilesPublic())
|
||||||
|
f = new File(_context.getAppDir(), dir);
|
||||||
|
else
|
||||||
|
f = new SecureDirectory(_context.getAppDir(), dir);
|
||||||
|
}
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,8 +231,10 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
_config.setProperty(PROP_DIR, "i2psnark");
|
_config.setProperty(PROP_DIR, "i2psnark");
|
||||||
if (!_config.containsKey(PROP_AUTO_START))
|
if (!_config.containsKey(PROP_AUTO_START))
|
||||||
_config.setProperty(PROP_AUTO_START, DEFAULT_AUTO_START);
|
_config.setProperty(PROP_AUTO_START, DEFAULT_AUTO_START);
|
||||||
|
if (!_config.containsKey(PROP_REFRESH_DELAY))
|
||||||
|
_config.setProperty(PROP_REFRESH_DELAY, Integer.toString(DEFAULT_REFRESH_DELAY_SECS));
|
||||||
if (!_config.containsKey(PROP_STARTUP_DELAY))
|
if (!_config.containsKey(PROP_STARTUP_DELAY))
|
||||||
_config.setProperty(PROP_STARTUP_DELAY, "" + DEFAULT_STARTUP_DELAY);
|
_config.setProperty(PROP_STARTUP_DELAY, Integer.toString(DEFAULT_STARTUP_DELAY));
|
||||||
if (!_config.containsKey(PROP_THEME))
|
if (!_config.containsKey(PROP_THEME))
|
||||||
_config.setProperty(PROP_THEME, DEFAULT_THEME);
|
_config.setProperty(PROP_THEME, DEFAULT_THEME);
|
||||||
updateConfig();
|
updateConfig();
|
||||||
@@ -258,10 +304,11 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
|
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
|
||||||
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
||||||
_util.setStartupDelay(getInt(PROP_STARTUP_DELAY, DEFAULT_STARTUP_DELAY));
|
_util.setStartupDelay(getInt(PROP_STARTUP_DELAY, DEFAULT_STARTUP_DELAY));
|
||||||
String ot = _config.getProperty(I2PSnarkUtil.PROP_OPENTRACKERS);
|
_util.setFilesPublic(areFilesPublic());
|
||||||
|
String ot = _config.getProperty(PROP_OPENTRACKERS);
|
||||||
if (ot != null)
|
if (ot != null)
|
||||||
_util.setOpenTrackerString(ot);
|
_util.setOpenTrackerString(ot);
|
||||||
String useOT = _config.getProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS);
|
String useOT = _config.getProperty(PROP_USE_OPENTRACKERS);
|
||||||
boolean bOT = useOT == null || Boolean.valueOf(useOT).booleanValue();
|
boolean bOT = useOT == null || Boolean.valueOf(useOT).booleanValue();
|
||||||
_util.setUseOpenTrackers(bOT);
|
_util.setUseOpenTrackers(bOT);
|
||||||
getDataDir().mkdirs();
|
getDataDir().mkdirs();
|
||||||
@@ -278,7 +325,8 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
return defaultVal;
|
return defaultVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateConfig(String dataDir, boolean autoStart, String startDelay, String seedPct, String eepHost,
|
public void updateConfig(String dataDir, boolean filesPublic, boolean autoStart, String refreshDelay,
|
||||||
|
String startDelay, String seedPct, String eepHost,
|
||||||
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
|
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
|
||||||
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers, String theme) {
|
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers, String theme) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
@@ -333,19 +381,34 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
changed = true;
|
changed = true;
|
||||||
_config.setProperty(PROP_STARTUP_DELAY, "" + minutes);
|
_config.setProperty(PROP_STARTUP_DELAY, "" + minutes);
|
||||||
addMessage(_("Startup delay changed to {0}", DataHelper.formatDuration2(minutes * 60 * 1000)));
|
addMessage(_("Startup delay changed to {0}", DataHelper.formatDuration2(minutes * 60 * 1000)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// FIXME do this even if == null
|
|
||||||
if (i2cpHost != null) {
|
if (refreshDelay != null) {
|
||||||
|
try {
|
||||||
|
int secs = Integer.parseInt(refreshDelay);
|
||||||
|
if (secs != getRefreshDelaySeconds()) {
|
||||||
|
changed = true;
|
||||||
|
_config.setProperty(PROP_REFRESH_DELAY, refreshDelay);
|
||||||
|
if (secs >= 0)
|
||||||
|
addMessage(_("Refresh time changed to {0}", DataHelper.formatDuration2(secs * 1000)));
|
||||||
|
else
|
||||||
|
addMessage(_("Refresh disabled"));
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start of I2CP stuff.
|
||||||
|
// i2cpHost will generally be null since it is hidden from the form if in router context.
|
||||||
|
|
||||||
int oldI2CPPort = _util.getI2CPPort();
|
int oldI2CPPort = _util.getI2CPPort();
|
||||||
String oldI2CPHost = _util.getI2CPHost();
|
String oldI2CPHost = _util.getI2CPHost();
|
||||||
int port = oldI2CPPort;
|
int port = oldI2CPPort;
|
||||||
if (i2cpPort != null) {
|
if (i2cpPort != null) {
|
||||||
try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {}
|
try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {}
|
||||||
}
|
}
|
||||||
String host = oldI2CPHost;
|
|
||||||
Map opts = new HashMap();
|
Map<String, String> opts = new HashMap();
|
||||||
if (i2cpOpts == null) i2cpOpts = "";
|
if (i2cpOpts == null) i2cpOpts = "";
|
||||||
StringTokenizer tok = new StringTokenizer(i2cpOpts, " \t\n");
|
StringTokenizer tok = new StringTokenizer(i2cpOpts, " \t\n");
|
||||||
while (tok.hasMoreTokens()) {
|
while (tok.hasMoreTokens()) {
|
||||||
@@ -354,7 +417,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
if (split > 0)
|
if (split > 0)
|
||||||
opts.put(pair.substring(0, split), pair.substring(split+1));
|
opts.put(pair.substring(0, split), pair.substring(split+1));
|
||||||
}
|
}
|
||||||
Map oldOpts = new HashMap();
|
Map<String, String> oldOpts = new HashMap();
|
||||||
String oldI2CPOpts = _config.getProperty(PROP_I2CP_OPTS);
|
String oldI2CPOpts = _config.getProperty(PROP_I2CP_OPTS);
|
||||||
if (oldI2CPOpts == null) oldI2CPOpts = "";
|
if (oldI2CPOpts == null) oldI2CPOpts = "";
|
||||||
tok = new StringTokenizer(oldI2CPOpts, " \t\n");
|
tok = new StringTokenizer(oldI2CPOpts, " \t\n");
|
||||||
@@ -365,37 +428,39 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
oldOpts.put(pair.substring(0, split), pair.substring(split+1));
|
oldOpts.put(pair.substring(0, split), pair.substring(split+1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (i2cpHost.trim().length() > 0) && (port > 0) &&
|
boolean reconnect = i2cpHost != null && i2cpHost.trim().length() > 0 && port > 0 &&
|
||||||
((!host.equals(i2cpHost) ||
|
(port != _util.getI2CPPort() || !oldI2CPHost.equals(i2cpHost));
|
||||||
(port != _util.getI2CPPort()) ||
|
if (reconnect || !oldOpts.equals(opts)) {
|
||||||
(!oldOpts.equals(opts)))) ) {
|
|
||||||
boolean snarksActive = false;
|
boolean snarksActive = false;
|
||||||
Set names = listTorrentFiles();
|
if (reconnect) {
|
||||||
for (Iterator iter = names.iterator(); iter.hasNext(); ) {
|
for (Snark snark : _snarks.values()) {
|
||||||
Snark snark = getTorrent((String)iter.next());
|
if (!snark.isStopped()) {
|
||||||
if ( (snark != null) && (!snark.isStopped()) ) {
|
snarksActive = true;
|
||||||
snarksActive = true;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
|
||||||
|
+ "] oldOpts [" + oldOpts + "]");
|
||||||
if (snarksActive) {
|
if (snarksActive) {
|
||||||
Properties p = new Properties();
|
Properties p = new Properties();
|
||||||
p.putAll(opts);
|
p.putAll(opts);
|
||||||
_util.setI2CPConfig(i2cpHost, port, p);
|
_util.setI2CPConfig(i2cpHost, port, p);
|
||||||
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
||||||
addMessage(_("I2CP and tunnel changes will take effect after stopping all torrents"));
|
addMessage(_("I2CP and tunnel changes will take effect after stopping all torrents"));
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
} else if (!reconnect) {
|
||||||
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
|
// The usual case, the other two are if not in router context
|
||||||
+ "] oldOpts [" + oldOpts + "]");
|
_config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim());
|
||||||
|
addMessage(_("I2CP options changed to {0}", i2cpOpts));
|
||||||
|
_util.setI2CPConfig(oldI2CPHost, oldI2CPPort, opts);
|
||||||
} else {
|
} else {
|
||||||
if (_util.connected()) {
|
if (_util.connected()) {
|
||||||
_util.disconnect();
|
_util.disconnect();
|
||||||
addMessage(_("Disconnecting old I2CP destination"));
|
addMessage(_("Disconnecting old I2CP destination"));
|
||||||
}
|
}
|
||||||
Properties p = new Properties();
|
addMessage(_("I2CP settings changed to {0}", i2cpHost + ':' + port + ' ' + i2cpOpts));
|
||||||
p.putAll(opts);
|
_util.setI2CPConfig(i2cpHost, port, opts);
|
||||||
addMessage(_("I2CP settings changed to {0}", i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")"));
|
|
||||||
_util.setI2CPConfig(i2cpHost, port, p);
|
|
||||||
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
||||||
boolean ok = _util.connect();
|
boolean ok = _util.connect();
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -409,22 +474,29 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
_config.setProperty(PROP_I2CP_HOST, i2cpHost.trim());
|
_config.setProperty(PROP_I2CP_HOST, i2cpHost.trim());
|
||||||
_config.setProperty(PROP_I2CP_PORT, "" + port);
|
_config.setProperty(PROP_I2CP_PORT, "" + port);
|
||||||
_config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim());
|
_config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim());
|
||||||
changed = true;
|
|
||||||
// no PeerAcceptors/I2PServerSockets to deal with, since all snarks are inactive
|
// no PeerAcceptors/I2PServerSockets to deal with, since all snarks are inactive
|
||||||
for (Iterator iter = names.iterator(); iter.hasNext(); ) {
|
for (Snark snark : _snarks.values()) {
|
||||||
String name = (String)iter.next();
|
if (snark.restartAcceptor()) {
|
||||||
Snark snark = getTorrent(name);
|
|
||||||
if (snark != null && snark.restartAcceptor()) {
|
|
||||||
addMessage(_("I2CP listener restarted for \"{0}\"", snark.getBaseName()));
|
addMessage(_("I2CP listener restarted for \"{0}\"", snark.getBaseName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
} // reconnect || changed options
|
||||||
|
|
||||||
|
if (areFilesPublic() != filesPublic) {
|
||||||
|
_config.setProperty(PROP_FILES_PUBLIC, Boolean.toString(filesPublic));
|
||||||
|
_util.setFilesPublic(filesPublic);
|
||||||
|
if (filesPublic)
|
||||||
|
addMessage(_("New files will be publicly readable"));
|
||||||
|
else
|
||||||
|
addMessage(_("New files will not be publicly readable"));
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldAutoStart() != autoStart) {
|
if (shouldAutoStart() != autoStart) {
|
||||||
_config.setProperty(PROP_AUTO_START, autoStart + "");
|
_config.setProperty(PROP_AUTO_START, Boolean.toString(autoStart));
|
||||||
if (autoStart)
|
if (autoStart)
|
||||||
addMessage(_("Enabled autostart"));
|
addMessage(_("Enabled autostart"));
|
||||||
else
|
else
|
||||||
@@ -432,7 +504,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
|
if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
|
||||||
_config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + "");
|
_config.setProperty(PROP_USE_OPENTRACKERS, useOpenTrackers + "");
|
||||||
if (useOpenTrackers)
|
if (useOpenTrackers)
|
||||||
addMessage(_("Enabled open trackers - torrent restart required to take effect."));
|
addMessage(_("Enabled open trackers - torrent restart required to take effect."));
|
||||||
else
|
else
|
||||||
@@ -442,7 +514,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
}
|
}
|
||||||
if (openTrackers != null) {
|
if (openTrackers != null) {
|
||||||
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(_util.getOpenTrackerString())) {
|
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(_util.getOpenTrackerString())) {
|
||||||
_config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim());
|
_config.setProperty(PROP_OPENTRACKERS, openTrackers.trim());
|
||||||
_util.setOpenTrackerString(openTrackers);
|
_util.setOpenTrackerString(openTrackers);
|
||||||
addMessage(_("Open Tracker list changed - torrent restart required to take effect."));
|
addMessage(_("Open Tracker list changed - torrent restart required to take effect."));
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -489,7 +561,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
* Grab the torrent given the (canonical) filename of the .torrent file
|
* Grab the torrent given the (canonical) filename of the .torrent file
|
||||||
* @return Snark or null
|
* @return Snark or null
|
||||||
*/
|
*/
|
||||||
public Snark getTorrent(String filename) { synchronized (_snarks) { return (Snark)_snarks.get(filename); } }
|
public Snark getTorrent(String filename) { synchronized (_snarks) { return _snarks.get(filename); } }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grab the torrent given the base name of the storage
|
* Grab the torrent given the base name of the storage
|
||||||
@@ -723,7 +795,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
// so addTorrent won't recheck
|
// so addTorrent won't recheck
|
||||||
saveTorrentStatus(metainfo, bitfield, null); // no file priorities
|
saveTorrentStatus(metainfo, bitfield, null); // no file priorities
|
||||||
try {
|
try {
|
||||||
locked_writeMetaInfo(metainfo, filename);
|
locked_writeMetaInfo(metainfo, filename, areFilesPublic());
|
||||||
// hold the lock for a long time
|
// hold the lock for a long time
|
||||||
addTorrent(filename, dontAutoStart);
|
addTorrent(filename, dontAutoStart);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
@@ -754,7 +826,8 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
_log.error("Failed to write torrent file to " + filename);
|
_log.error("Failed to write torrent file to " + filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SecureFileOutputStream.setPerms(new File(filename));
|
if (!areFilesPublic())
|
||||||
|
SecureFileOutputStream.setPerms(new File(filename));
|
||||||
// hold the lock for a long time
|
// hold the lock for a long time
|
||||||
addTorrent(filename);
|
addTorrent(filename);
|
||||||
}
|
}
|
||||||
@@ -769,13 +842,16 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
* Must be a filesystem-safe name.
|
* Must be a filesystem-safe name.
|
||||||
* @since 0.8.4
|
* @since 0.8.4
|
||||||
*/
|
*/
|
||||||
private static void locked_writeMetaInfo(MetaInfo metainfo, String filename) throws IOException {
|
private static void locked_writeMetaInfo(MetaInfo metainfo, String filename, boolean areFilesPublic) throws IOException {
|
||||||
File file = new File(filename);
|
File file = new File(filename);
|
||||||
if (file.exists())
|
if (file.exists())
|
||||||
throw new IOException("Cannot overwrite an existing .torrent file: " + file.getPath());
|
throw new IOException("Cannot overwrite an existing .torrent file: " + file.getPath());
|
||||||
OutputStream out = null;
|
OutputStream out = null;
|
||||||
try {
|
try {
|
||||||
out = new SecureFileOutputStream(filename);
|
if (areFilesPublic)
|
||||||
|
out = new FileOutputStream(filename);
|
||||||
|
else
|
||||||
|
out = new SecureFileOutputStream(filename);
|
||||||
out.write(metainfo.getTorrentData());
|
out.write(metainfo.getTorrentData());
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
// remove any partial
|
// remove any partial
|
||||||
@@ -1170,7 +1246,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
if (announce != null)
|
if (announce != null)
|
||||||
meta = meta.reannounce(announce);
|
meta = meta.reannounce(announce);
|
||||||
synchronized (_snarks) {
|
synchronized (_snarks) {
|
||||||
locked_writeMetaInfo(meta, name);
|
locked_writeMetaInfo(meta, name, areFilesPublic());
|
||||||
// put it in the list under the new name
|
// put it in the list under the new name
|
||||||
_snarks.remove(snark.getName());
|
_snarks.remove(snark.getName());
|
||||||
_snarks.put(name, snark);
|
_snarks.put(name, snark);
|
||||||
|
@@ -48,7 +48,7 @@ public class Storage
|
|||||||
private int[] priorities;
|
private int[] priorities;
|
||||||
|
|
||||||
private final StorageListener listener;
|
private final StorageListener listener;
|
||||||
private I2PSnarkUtil _util;
|
private final I2PSnarkUtil _util;
|
||||||
|
|
||||||
private /* FIXME final FIXME */ BitField bitfield; // BitField to represent the pieces
|
private /* FIXME final FIXME */ BitField bitfield; // BitField to represent the pieces
|
||||||
private int needed; // Number of pieces needed
|
private int needed; // Number of pieces needed
|
||||||
@@ -433,7 +433,12 @@ public class Storage
|
|||||||
/** use a saved bitfield and timestamp from a config file */
|
/** use a saved bitfield and timestamp from a config file */
|
||||||
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
|
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
|
||||||
{
|
{
|
||||||
File base = new SecureFile(rootDir, filterName(metainfo.getName()));
|
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;
|
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
|
||||||
|
|
||||||
List<List<String>> files = metainfo.getFiles();
|
List<List<String>> files = metainfo.getFiles();
|
||||||
@@ -479,7 +484,7 @@ public class Storage
|
|||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
List<String> path = files.get(i);
|
List<String> path = files.get(i);
|
||||||
File f = createFileFromNames(base, path);
|
File f = createFileFromNames(base, path, areFilesPublic);
|
||||||
// dup file name check after filtering
|
// dup file name check after filtering
|
||||||
for (int j = 0; j < i; j++) {
|
for (int j = 0; j < i; j++) {
|
||||||
if (f.equals(RAFfile[j])) {
|
if (f.equals(RAFfile[j])) {
|
||||||
@@ -495,7 +500,7 @@ public class Storage
|
|||||||
else
|
else
|
||||||
lastPath = '_' + lastPath;
|
lastPath = '_' + lastPath;
|
||||||
path.set(last, lastPath);
|
path.set(last, lastPath);
|
||||||
f = createFileFromNames(base, path);
|
f = createFileFromNames(base, path, areFilesPublic);
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -585,7 +590,7 @@ public class Storage
|
|||||||
* things going in the wrong place if there are duplicates
|
* things going in the wrong place if there are duplicates
|
||||||
* in intermediate path elements after filtering.
|
* in intermediate path elements after filtering.
|
||||||
*/
|
*/
|
||||||
private static File createFileFromNames(File base, List<String> names) throws IOException
|
private static File createFileFromNames(File base, List<String> names, boolean areFilesPublic) throws IOException
|
||||||
{
|
{
|
||||||
File f = null;
|
File f = null;
|
||||||
Iterator<String> it = names.iterator();
|
Iterator<String> it = names.iterator();
|
||||||
@@ -595,7 +600,10 @@ public class Storage
|
|||||||
if (it.hasNext())
|
if (it.hasNext())
|
||||||
{
|
{
|
||||||
// Another dir in the hierarchy.
|
// Another dir in the hierarchy.
|
||||||
f = new File(base, name);
|
if (areFilesPublic)
|
||||||
|
f = new File(base, name);
|
||||||
|
else
|
||||||
|
f = new SecureFile(base, name);
|
||||||
if (!f.mkdir() && !f.isDirectory())
|
if (!f.mkdir() && !f.isDirectory())
|
||||||
throw new IOException("Could not create directory " + f);
|
throw new IOException("Could not create directory " + f);
|
||||||
base = f;
|
base = f;
|
||||||
@@ -603,7 +611,10 @@ public class Storage
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The final element (file) in the hierarchy.
|
// The final element (file) in the hierarchy.
|
||||||
f = new SecureFile(base, name);
|
if (areFilesPublic)
|
||||||
|
f = new File(base, name);
|
||||||
|
else
|
||||||
|
f = new SecureFile(base, name);
|
||||||
if (!f.createNewFile() && !f.exists())
|
if (!f.createNewFile() && !f.exists())
|
||||||
throw new IOException("Could not create file " + f);
|
throw new IOException("Could not create file " + f);
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,6 @@ import net.i2p.data.DataHelper;
|
|||||||
import net.i2p.util.FileUtil;
|
import net.i2p.util.FileUtil;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.SecureFileOutputStream;
|
|
||||||
|
|
||||||
import org.klomp.snark.I2PSnarkUtil;
|
import org.klomp.snark.I2PSnarkUtil;
|
||||||
import org.klomp.snark.MetaInfo;
|
import org.klomp.snark.MetaInfo;
|
||||||
@@ -208,8 +207,11 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write("</title>\n");
|
out.write("</title>\n");
|
||||||
|
|
||||||
// we want it to go to the base URI so we don't refresh with some funky action= value
|
// we want it to go to the base URI so we don't refresh with some funky action= value
|
||||||
if (!isConfigure)
|
if (!isConfigure) {
|
||||||
out.write("<meta http-equiv=\"refresh\" content=\"60;/i2psnark/" + peerString + "\">\n");
|
int delay = _manager.getRefreshDelaySeconds();
|
||||||
|
if (delay > 0)
|
||||||
|
out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
|
||||||
|
}
|
||||||
out.write(HEADER_A + _themePath + HEADER_B);
|
out.write(HEADER_A + _themePath + HEADER_B);
|
||||||
out.write("</head><body>");
|
out.write("</head><body>");
|
||||||
out.write("<center>");
|
out.write("<center>");
|
||||||
@@ -611,6 +613,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
}
|
}
|
||||||
} else if ("Save".equals(action)) {
|
} else if ("Save".equals(action)) {
|
||||||
String dataDir = req.getParameter("dataDir");
|
String dataDir = req.getParameter("dataDir");
|
||||||
|
boolean filesPublic = req.getParameter("filesPublic") != null;
|
||||||
boolean autoStart = req.getParameter("autoStart") != null;
|
boolean autoStart = req.getParameter("autoStart") != null;
|
||||||
String seedPct = req.getParameter("seedPct");
|
String seedPct = req.getParameter("seedPct");
|
||||||
String eepHost = req.getParameter("eepHost");
|
String eepHost = req.getParameter("eepHost");
|
||||||
@@ -620,11 +623,14 @@ public class I2PSnarkServlet extends Default {
|
|||||||
String i2cpOpts = buildI2CPOpts(req);
|
String i2cpOpts = buildI2CPOpts(req);
|
||||||
String upLimit = req.getParameter("upLimit");
|
String upLimit = req.getParameter("upLimit");
|
||||||
String upBW = req.getParameter("upBW");
|
String upBW = req.getParameter("upBW");
|
||||||
|
String refreshDel = req.getParameter("refreshDelay");
|
||||||
String startupDel = req.getParameter("startupDelay");
|
String startupDel = req.getParameter("startupDelay");
|
||||||
boolean useOpenTrackers = req.getParameter("useOpenTrackers") != null;
|
boolean useOpenTrackers = req.getParameter("useOpenTrackers") != null;
|
||||||
String openTrackers = req.getParameter("openTrackers");
|
String openTrackers = req.getParameter("openTrackers");
|
||||||
String theme = req.getParameter("theme");
|
String theme = req.getParameter("theme");
|
||||||
_manager.updateConfig(dataDir, autoStart, startupDel, seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts, upLimit, upBW, useOpenTrackers, openTrackers, theme);
|
_manager.updateConfig(dataDir, filesPublic, autoStart, refreshDel, startupDel,
|
||||||
|
seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts,
|
||||||
|
upLimit, upBW, useOpenTrackers, openTrackers, theme);
|
||||||
} else if ("Create".equals(action)) {
|
} else if ("Create".equals(action)) {
|
||||||
String baseData = req.getParameter("baseFile");
|
String baseData = req.getParameter("baseFile");
|
||||||
if (baseData != null && baseData.trim().length() > 0) {
|
if (baseData != null && baseData.trim().length() > 0) {
|
||||||
@@ -1259,44 +1265,55 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write(" <input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
|
out.write(" <input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
|
||||||
"title=\"");
|
"title=\"");
|
||||||
out.write(_("Specify custom tracker announce URL"));
|
out.write(_("Specify custom tracker announce URL"));
|
||||||
out.write("\" > ");
|
out.write("\" > " +
|
||||||
out.write("<input type=\"submit\" value=\"");
|
"<input type=\"submit\" value=\"");
|
||||||
out.write(_("Create torrent"));
|
out.write(_("Create torrent"));
|
||||||
out.write("\" name=\"foo\" ></table>\n");
|
out.write("\" name=\"foo\" ></table>\n" +
|
||||||
out.write("</form></div></div>");
|
"</form></div></div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final int[] times = { 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
|
||||||
|
|
||||||
private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
|
private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
|
||||||
String dataDir = _manager.getDataDir().getAbsolutePath();
|
String dataDir = _manager.getDataDir().getAbsolutePath();
|
||||||
|
boolean filesPublic = _manager.areFilesPublic();
|
||||||
boolean autoStart = _manager.shouldAutoStart();
|
boolean autoStart = _manager.shouldAutoStart();
|
||||||
boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers();
|
boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers();
|
||||||
String openTrackers = _manager.util().getOpenTrackerString();
|
String openTrackers = _manager.util().getOpenTrackerString();
|
||||||
//int seedPct = 0;
|
//int seedPct = 0;
|
||||||
|
|
||||||
out.write("<form action=\"/i2psnark/configure\" method=\"POST\">\n");
|
out.write("<form action=\"/i2psnark/configure\" method=\"POST\">\n" +
|
||||||
out.write("<div class=\"configsectionpanel\"><div class=\"snarkConfig\">\n");
|
"<div class=\"configsectionpanel\"><div class=\"snarkConfig\">\n" +
|
||||||
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
|
"<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n" +
|
||||||
out.write("<input type=\"hidden\" name=\"action\" value=\"Save\" >\n");
|
"<input type=\"hidden\" name=\"action\" value=\"Save\" >\n" +
|
||||||
out.write("<span class=\"snarkConfigTitle\">");
|
"<span class=\"snarkConfigTitle\">" +
|
||||||
out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
|
"<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
|
||||||
out.write(_("Configuration"));
|
out.write(_("Configuration"));
|
||||||
out.write("</span><hr>\n");
|
out.write("</span><hr>\n" +
|
||||||
out.write("<table border=\"0\"><tr><td>");
|
"<table border=\"0\"><tr><td>");
|
||||||
|
|
||||||
out.write(_("Data directory"));
|
out.write(_("Data directory"));
|
||||||
out.write(": <td><code>" + dataDir + "</code> <i>(");
|
out.write(": <td><code>" + dataDir + "</code> <i>(");
|
||||||
out.write(_("Edit i2psnark.config and restart to change"));
|
out.write(_("Edit i2psnark.config and restart to change"));
|
||||||
out.write(")</i><br>\n");
|
out.write(")</i><br>\n" +
|
||||||
|
|
||||||
out.write("<tr><td>");
|
"<tr><td>");
|
||||||
|
out.write(_("Files readable by all"));
|
||||||
|
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"filesPublic\" value=\"true\" "
|
||||||
|
+ (filesPublic ? "checked " : "")
|
||||||
|
+ "title=\"");
|
||||||
|
out.write(_("If checked, other users may access the downloaded files"));
|
||||||
|
out.write("\" >" +
|
||||||
|
|
||||||
|
"<tr><td>");
|
||||||
out.write(_("Auto start"));
|
out.write(_("Auto start"));
|
||||||
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"autoStart\" value=\"true\" "
|
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"autoStart\" value=\"true\" "
|
||||||
+ (autoStart ? "checked " : "")
|
+ (autoStart ? "checked " : "")
|
||||||
+ "title=\"");
|
+ "title=\"");
|
||||||
out.write(_("If checked, automatically start torrents that are added"));
|
out.write(_("If checked, automatically start torrents that are added"));
|
||||||
out.write("\" >");
|
out.write("\" >" +
|
||||||
|
|
||||||
out.write("<tr><td>");
|
"<tr><td>");
|
||||||
out.write(_("Theme"));
|
out.write(_("Theme"));
|
||||||
out.write(": <td><select name='theme'>");
|
out.write(": <td><select name='theme'>");
|
||||||
String theme = _manager.getTheme();
|
String theme = _manager.getTheme();
|
||||||
@@ -1307,9 +1324,28 @@ public class I2PSnarkServlet extends Default {
|
|||||||
else
|
else
|
||||||
out.write("\n<OPTION value=\"" + themes[i] + "\">" + themes[i]);
|
out.write("\n<OPTION value=\"" + themes[i] + "\">" + themes[i]);
|
||||||
}
|
}
|
||||||
out.write("</select>\n");
|
out.write("</select>\n" +
|
||||||
|
|
||||||
out.write("<tr><td>");
|
"<tr><td>");
|
||||||
|
out.write(_("Refresh time"));
|
||||||
|
out.write(": <td><select name=\"refreshDelay\">");
|
||||||
|
int delay = _manager.getRefreshDelaySeconds();
|
||||||
|
for (int i = 0; i < times.length; i++) {
|
||||||
|
out.write("<option value=\"");
|
||||||
|
out.write(Integer.toString(times[i]));
|
||||||
|
out.write("\"");
|
||||||
|
if (times[i] == delay)
|
||||||
|
out.write(" selected=\"true\"");
|
||||||
|
out.write(">");
|
||||||
|
if (times[i] > 0)
|
||||||
|
out.write(DataHelper.formatDuration2(times[i] * 1000));
|
||||||
|
else
|
||||||
|
out.write(_("Never"));
|
||||||
|
out.write("</option>\n");
|
||||||
|
}
|
||||||
|
out.write("</select><br>" +
|
||||||
|
|
||||||
|
"<tr><td>");
|
||||||
out.write(_("Startup delay"));
|
out.write(_("Startup delay"));
|
||||||
out.write(": <td><input name=\"startupDelay\" size=\"3\" class=\"r\" value=\"" + _manager.util().getStartupDelay() + "\"> ");
|
out.write(": <td><input name=\"startupDelay\" size=\"3\" class=\"r\" value=\"" + _manager.util().getStartupDelay() + "\"> ");
|
||||||
out.write(_("minutes"));
|
out.write(_("minutes"));
|
||||||
@@ -1340,26 +1376,26 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write(": <td><input type=\"text\" name=\"upLimit\" class=\"r\" value=\""
|
out.write(": <td><input type=\"text\" name=\"upLimit\" class=\"r\" value=\""
|
||||||
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" > ");
|
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" > ");
|
||||||
out.write(_("peers"));
|
out.write(_("peers"));
|
||||||
out.write("<br>\n");
|
out.write("<br>\n" +
|
||||||
|
|
||||||
out.write("<tr><td>");
|
"<tr><td>");
|
||||||
out.write(_("Up bandwidth limit"));
|
out.write(_("Up bandwidth limit"));
|
||||||
out.write(": <td><input type=\"text\" name=\"upBW\" class=\"r\" value=\""
|
out.write(": <td><input type=\"text\" name=\"upBW\" class=\"r\" value=\""
|
||||||
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" > KBps <i>(");
|
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" > KBps <i>(");
|
||||||
out.write(_("Half available bandwidth recommended."));
|
out.write(_("Half available bandwidth recommended."));
|
||||||
out.write(" <a href=\"/config.jsp\" target=\"blank\">");
|
out.write(" <a href=\"/config.jsp\" target=\"blank\">");
|
||||||
out.write(_("View or change router bandwidth"));
|
out.write(_("View or change router bandwidth"));
|
||||||
out.write("</a>)</i><br>\n");
|
out.write("</a>)</i><br>\n" +
|
||||||
|
|
||||||
out.write("<tr><td>");
|
"<tr><td>");
|
||||||
out.write(_("Use open trackers also"));
|
out.write(_("Use open trackers also"));
|
||||||
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"useOpenTrackers\" value=\"true\" "
|
out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"useOpenTrackers\" value=\"true\" "
|
||||||
+ (useOpenTrackers ? "checked " : "")
|
+ (useOpenTrackers ? "checked " : "")
|
||||||
+ "title=\"");
|
+ "title=\"");
|
||||||
out.write(_("If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"));
|
out.write(_("If checked, announce torrents to open trackers as well as the tracker listed in the torrent file"));
|
||||||
out.write("\" > ");
|
out.write("\" > " +
|
||||||
|
|
||||||
out.write("<tr><td>");
|
"<tr><td>");
|
||||||
out.write(_("Open tracker announce URLs"));
|
out.write(_("Open tracker announce URLs"));
|
||||||
out.write(": <td><input type=\"text\" name=\"openTrackers\" value=\""
|
out.write(": <td><input type=\"text\" name=\"openTrackers\" value=\""
|
||||||
+ openTrackers + "\" size=\"50\" ><br>\n");
|
+ openTrackers + "\" size=\"50\" ><br>\n");
|
||||||
@@ -1388,36 +1424,38 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write("<tr><td>");
|
out.write("<tr><td>");
|
||||||
out.write(_("I2CP host"));
|
out.write(_("I2CP host"));
|
||||||
out.write(": <td><input type=\"text\" name=\"i2cpHost\" value=\""
|
out.write(": <td><input type=\"text\" name=\"i2cpHost\" value=\""
|
||||||
+ _manager.util().getI2CPHost() + "\" size=\"15\" > ");
|
+ _manager.util().getI2CPHost() + "\" size=\"15\" > " +
|
||||||
|
|
||||||
out.write("<tr><td>");
|
"<tr><td>");
|
||||||
out.write(_("I2CP port"));
|
out.write(_("I2CP port"));
|
||||||
out.write(": <td><input type=\"text\" name=\"i2cpPort\" class=\"r\" value=\"" +
|
out.write(": <td><input type=\"text\" name=\"i2cpPort\" class=\"r\" value=\"" +
|
||||||
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" > <br>\n");
|
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" > <br>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.remove(I2PSnarkUtil.PROP_MAX_BW);
|
||||||
|
// was accidentally in the I2CP options prior to 0.8.9 so it will be in old config files
|
||||||
|
options.remove(SnarkManager.PROP_OPENTRACKERS);
|
||||||
StringBuilder opts = new StringBuilder(64);
|
StringBuilder opts = new StringBuilder(64);
|
||||||
for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) {
|
for (Map.Entry<String, String> e : options.entrySet()) {
|
||||||
Map.Entry entry = (Map.Entry)iter.next();
|
String key = e.getKey();
|
||||||
String key = (String)entry.getKey();
|
String val = e.getValue();
|
||||||
String val = (String)entry.getValue();
|
|
||||||
opts.append(key).append('=').append(val).append(' ');
|
opts.append(key).append('=').append(val).append(' ');
|
||||||
}
|
}
|
||||||
out.write("<tr><td>");
|
out.write("<tr><td>");
|
||||||
out.write(_("I2CP options"));
|
out.write(_("I2CP options"));
|
||||||
out.write(": <td><textarea name=\"i2cpOpts\" cols=\"60\" rows=\"1\" wrap=\"off\" spellcheck=\"false\" >"
|
out.write(": <td><textarea name=\"i2cpOpts\" cols=\"60\" rows=\"1\" wrap=\"off\" spellcheck=\"false\" >"
|
||||||
+ opts.toString() + "</textarea><br>\n");
|
+ opts.toString() + "</textarea><br>\n" +
|
||||||
|
|
||||||
out.write("<tr><td> <td><input type=\"submit\" value=\"");
|
"<tr><td> <td><input type=\"submit\" value=\"");
|
||||||
out.write(_("Save configuration"));
|
out.write(_("Save configuration"));
|
||||||
out.write("\" name=\"foo\" >\n");
|
out.write("\" name=\"foo\" >\n" +
|
||||||
out.write("</table></div></div></form>");
|
"</table></div></div></form>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeConfigLink(PrintWriter out) throws IOException {
|
private void writeConfigLink(PrintWriter out) throws IOException {
|
||||||
out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n");
|
out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n" +
|
||||||
out.write("<span class=\"snarkConfigTitle\"><a href=\"configure\">");
|
"<span class=\"snarkConfigTitle\"><a href=\"configure\">" +
|
||||||
out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
|
"<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
|
||||||
out.write(_("Configuration"));
|
out.write(_("Configuration"));
|
||||||
out.write("</a></span></span></div>\n");
|
out.write("</a></span></span></div>\n");
|
||||||
}
|
}
|
||||||
|
12
history.txt
12
history.txt
@@ -1,3 +1,15 @@
|
|||||||
|
2011-09-14 zzz
|
||||||
|
* Console: Verify valid host/IP before saving on net config form
|
||||||
|
* i2psnark:
|
||||||
|
- Add refresh time option
|
||||||
|
- Add public file permissions option (ticket #501)
|
||||||
|
- Fix configuration of tunnel parameters (ticket #524)
|
||||||
|
- Allow changing I2CP parameters while tunnel is open
|
||||||
|
- Remove duplicated options in I2CP options string
|
||||||
|
- Don't open tunnel when saving config
|
||||||
|
* IRC DCC: Fix conn limit options
|
||||||
|
* Router: Set permissions on router.ping file
|
||||||
|
|
||||||
2011-09-13 kytv
|
2011-09-13 kytv
|
||||||
* Update i2prouter script
|
* Update i2prouter script
|
||||||
|
|
||||||
|
@@ -18,7 +18,7 @@ public class RouterVersion {
|
|||||||
/** deprecated */
|
/** deprecated */
|
||||||
public final static String ID = "Monotone";
|
public final static String ID = "Monotone";
|
||||||
public final static String VERSION = CoreVersion.VERSION;
|
public final static String VERSION = CoreVersion.VERSION;
|
||||||
public final static long BUILD = 17;
|
public final static long BUILD = 18;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
Reference in New Issue
Block a user