diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index 6f35f66bdf..254f74c44b 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -44,34 +44,34 @@ import org.klomp.snark.dht.DHT; * (but not multiple SnarkManagers, it is still static) */ public class I2PSnarkUtil { - private I2PAppContext _context; - private Log _log; + private final I2PAppContext _context; + private final Log _log; private boolean _shouldProxy; private String _proxyHost; private int _proxyPort; private String _i2cpHost; private int _i2cpPort; - private Map _opts; + private final Map _opts; private I2PSocketManager _manager; private boolean _configured; private final Set _shitlist; private int _maxUploaders; private int _maxUpBW; private int _maxConnections; - private File _tmpDir; + private final File _tmpDir; private int _startupDelay; private boolean _shouldUseOT; + private boolean _areFilesPublic; + private String _openTrackerString; private DHT _dht; 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 String PROP_OPENTRACKERS = "i2psnark.opentrackers"; public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a"; public static final int DEFAULT_MAX_UP_BW = 8; //KBps public static final int MAX_CONNECTIONS = 16; // per torrent - 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; public I2PSnarkUtil(I2PAppContext ctx) { @@ -125,6 +125,8 @@ public class I2PSnarkUtil { // can't remove any options this way... if (opts != null) _opts.putAll(opts); + // this updates the session options and tells the router + setMaxUpBW(_maxUpBW); _configured = true; } @@ -134,6 +136,7 @@ public class I2PSnarkUtil { } /** + * This updates the session options and tells the router * @param limit KBps */ public void setMaxUpBW(int limit) { @@ -175,6 +178,12 @@ public class I2PSnarkUtil { public int getMaxConnections() { return _maxConnections; } 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 */ @@ -433,14 +442,13 @@ public class I2PSnarkUtil { /** @param ot non-null */ public void setOpenTrackerString(String ot) { - _opts.put(PROP_OPENTRACKERS, ot); + _openTrackerString = ot; } public String getOpenTrackerString() { - String rv = (String) _opts.get(PROP_OPENTRACKERS); - if (rv == null) + if (_openTrackerString == null) return DEFAULT_OPENTRACKERS; - return rv; + return _openTrackerString; } /** comma delimited list open trackers to use as backups */ diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 3080b58275..6222d9b14f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -3,6 +3,7 @@ package org.klomp.snark; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.OutputStream; @@ -71,17 +72,23 @@ public class SnarkManager implements Snark.CompleteListener { public static final String PROP_META_MAGNET_PREFIX = "i2psnark.magnet."; 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 DEFAULT_AUTO_START = "false"; - public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix"; - public static final String DEFAULT_LINK_PREFIX = "file:///"; + //public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix"; + //public static final String DEFAULT_LINK_PREFIX = "file:///"; 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 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 DEFAULT_MAX_UP_BW = 10; public static final int DEFAULT_STARTUP_DELAY = 3; + public static final int DEFAULT_REFRESH_DELAY_SECS = 60; + private SnarkManager() { _snarks = new ConcurrentHashMap(); _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() { 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() { String dir = _config.getProperty(PROP_DIR, "i2psnark"); - File f = new SecureDirectory(dir); - if (!f.isAbsolute()) - f = new SecureDirectory(_context.getAppDir(), dir); + File f; + if (areFilesPublic()) + 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; } @@ -187,8 +231,10 @@ public class SnarkManager implements Snark.CompleteListener { _config.setProperty(PROP_DIR, "i2psnark"); if (!_config.containsKey(PROP_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)) - _config.setProperty(PROP_STARTUP_DELAY, "" + DEFAULT_STARTUP_DELAY); + _config.setProperty(PROP_STARTUP_DELAY, Integer.toString(DEFAULT_STARTUP_DELAY)); if (!_config.containsKey(PROP_THEME)) _config.setProperty(PROP_THEME, DEFAULT_THEME); updateConfig(); @@ -258,10 +304,11 @@ public class SnarkManager implements Snark.CompleteListener { _util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS)); _util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW)); _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) _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(); _util.setUseOpenTrackers(bOT); getDataDir().mkdirs(); @@ -278,7 +325,8 @@ public class SnarkManager implements Snark.CompleteListener { 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 upLimit, String upBW, boolean useOpenTrackers, String openTrackers, String theme) { boolean changed = false; @@ -333,19 +381,34 @@ public class SnarkManager implements Snark.CompleteListener { changed = true; _config.setProperty(PROP_STARTUP_DELAY, "" + minutes); 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(); String oldI2CPHost = _util.getI2CPHost(); int port = oldI2CPPort; if (i2cpPort != null) { try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {} } - String host = oldI2CPHost; - Map opts = new HashMap(); + + Map opts = new HashMap(); if (i2cpOpts == null) i2cpOpts = ""; StringTokenizer tok = new StringTokenizer(i2cpOpts, " \t\n"); while (tok.hasMoreTokens()) { @@ -354,7 +417,7 @@ public class SnarkManager implements Snark.CompleteListener { if (split > 0) opts.put(pair.substring(0, split), pair.substring(split+1)); } - Map oldOpts = new HashMap(); + Map oldOpts = new HashMap(); String oldI2CPOpts = _config.getProperty(PROP_I2CP_OPTS); if (oldI2CPOpts == null) oldI2CPOpts = ""; 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)); } - if ( (i2cpHost.trim().length() > 0) && (port > 0) && - ((!host.equals(i2cpHost) || - (port != _util.getI2CPPort()) || - (!oldOpts.equals(opts)))) ) { + boolean reconnect = i2cpHost != null && i2cpHost.trim().length() > 0 && port > 0 && + (port != _util.getI2CPPort() || !oldI2CPHost.equals(i2cpHost)); + if (reconnect || !oldOpts.equals(opts)) { boolean snarksActive = false; - Set names = listTorrentFiles(); - for (Iterator iter = names.iterator(); iter.hasNext(); ) { - Snark snark = getTorrent((String)iter.next()); - if ( (snark != null) && (!snark.isStopped()) ) { - snarksActive = true; - break; + if (reconnect) { + for (Snark snark : _snarks.values()) { + if (!snark.isStopped()) { + snarksActive = true; + break; + } } } + if (_log.shouldLog(Log.DEBUG)) + _log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts + + "] oldOpts [" + oldOpts + "]"); if (snarksActive) { Properties p = new Properties(); p.putAll(opts); _util.setI2CPConfig(i2cpHost, port, p); _util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW)); addMessage(_("I2CP and tunnel changes will take effect after stopping all torrents")); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts - + "] oldOpts [" + oldOpts + "]"); + } else if (!reconnect) { + // The usual case, the other two are if not in router context + _config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim()); + addMessage(_("I2CP options changed to {0}", i2cpOpts)); + _util.setI2CPConfig(oldI2CPHost, oldI2CPPort, opts); } else { if (_util.connected()) { _util.disconnect(); addMessage(_("Disconnecting old I2CP destination")); } - Properties p = new Properties(); - p.putAll(opts); - addMessage(_("I2CP settings changed to {0}", i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")")); - _util.setI2CPConfig(i2cpHost, port, p); + addMessage(_("I2CP settings changed to {0}", i2cpHost + ':' + port + ' ' + i2cpOpts)); + _util.setI2CPConfig(i2cpHost, port, opts); _util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW)); boolean ok = _util.connect(); if (!ok) { @@ -409,22 +474,29 @@ public class SnarkManager implements Snark.CompleteListener { _config.setProperty(PROP_I2CP_HOST, i2cpHost.trim()); _config.setProperty(PROP_I2CP_PORT, "" + port); _config.setProperty(PROP_I2CP_OPTS, i2cpOpts.trim()); - changed = true; // no PeerAcceptors/I2PServerSockets to deal with, since all snarks are inactive - for (Iterator iter = names.iterator(); iter.hasNext(); ) { - String name = (String)iter.next(); - Snark snark = getTorrent(name); - if (snark != null && snark.restartAcceptor()) { + for (Snark snark : _snarks.values()) { + if (snark.restartAcceptor()) { addMessage(_("I2CP listener restarted for \"{0}\"", snark.getBaseName())); } } } } 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) { - _config.setProperty(PROP_AUTO_START, autoStart + ""); + _config.setProperty(PROP_AUTO_START, Boolean.toString(autoStart)); if (autoStart) addMessage(_("Enabled autostart")); else @@ -432,7 +504,7 @@ public class SnarkManager implements Snark.CompleteListener { changed = true; } if (_util.shouldUseOpenTrackers() != useOpenTrackers) { - _config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + ""); + _config.setProperty(PROP_USE_OPENTRACKERS, useOpenTrackers + ""); if (useOpenTrackers) addMessage(_("Enabled open trackers - torrent restart required to take effect.")); else @@ -442,7 +514,7 @@ public class SnarkManager implements Snark.CompleteListener { } if (openTrackers != null) { 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); addMessage(_("Open Tracker list changed - torrent restart required to take effect.")); changed = true; @@ -489,7 +561,7 @@ public class SnarkManager implements Snark.CompleteListener { * Grab the torrent given the (canonical) filename of the .torrent file * @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 @@ -723,7 +795,7 @@ public class SnarkManager implements Snark.CompleteListener { // so addTorrent won't recheck saveTorrentStatus(metainfo, bitfield, null); // no file priorities try { - locked_writeMetaInfo(metainfo, filename); + locked_writeMetaInfo(metainfo, filename, areFilesPublic()); // hold the lock for a long time addTorrent(filename, dontAutoStart); } catch (IOException ioe) { @@ -754,7 +826,8 @@ public class SnarkManager implements Snark.CompleteListener { _log.error("Failed to write torrent file to " + filename); return; } - SecureFileOutputStream.setPerms(new File(filename)); + if (!areFilesPublic()) + SecureFileOutputStream.setPerms(new File(filename)); // hold the lock for a long time addTorrent(filename); } @@ -769,13 +842,16 @@ public class SnarkManager implements Snark.CompleteListener { * Must be a filesystem-safe name. * @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); if (file.exists()) throw new IOException("Cannot overwrite an existing .torrent file: " + file.getPath()); OutputStream out = null; try { - out = new SecureFileOutputStream(filename); + if (areFilesPublic) + out = new FileOutputStream(filename); + else + out = new SecureFileOutputStream(filename); out.write(metainfo.getTorrentData()); } catch (IOException ioe) { // remove any partial @@ -1170,7 +1246,7 @@ public class SnarkManager implements Snark.CompleteListener { if (announce != null) meta = meta.reannounce(announce); synchronized (_snarks) { - locked_writeMetaInfo(meta, name); + locked_writeMetaInfo(meta, name, areFilesPublic()); // put it in the list under the new name _snarks.remove(snark.getName()); _snarks.put(name, snark); diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 30118e9585..0f1547b15f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -48,7 +48,7 @@ public class Storage private int[] priorities; private final StorageListener listener; - private I2PSnarkUtil _util; + private final I2PSnarkUtil _util; private /* FIXME final FIXME */ BitField bitfield; // BitField to represent the pieces private int needed; // Number of pieces needed @@ -433,7 +433,12 @@ public class Storage /** use a saved bitfield and timestamp from a config file */ 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; List> files = metainfo.getFiles(); @@ -479,7 +484,7 @@ public class Storage for (int i = 0; i < size; i++) { List path = files.get(i); - File f = createFileFromNames(base, path); + File f = createFileFromNames(base, path, areFilesPublic); // dup file name check after filtering for (int j = 0; j < i; j++) { if (f.equals(RAFfile[j])) { @@ -495,7 +500,7 @@ public class Storage else lastPath = '_' + lastPath; path.set(last, lastPath); - f = createFileFromNames(base, path); + f = createFileFromNames(base, path, areFilesPublic); j = 0; } } @@ -585,7 +590,7 @@ public class Storage * things going in the wrong place if there are duplicates * in intermediate path elements after filtering. */ - private static File createFileFromNames(File base, List names) throws IOException + private static File createFileFromNames(File base, List names, boolean areFilesPublic) throws IOException { File f = null; Iterator it = names.iterator(); @@ -595,7 +600,10 @@ public class Storage if (it.hasNext()) { // 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()) throw new IOException("Could not create directory " + f); base = f; @@ -603,7 +611,10 @@ public class Storage else { // 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()) throw new IOException("Could not create file " + f); } 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 21dab96cb2..255e65e695 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -33,7 +33,6 @@ import net.i2p.data.DataHelper; import net.i2p.util.FileUtil; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; -import net.i2p.util.SecureFileOutputStream; import org.klomp.snark.I2PSnarkUtil; import org.klomp.snark.MetaInfo; @@ -208,8 +207,11 @@ public class I2PSnarkServlet extends Default { out.write("\n"); // we want it to go to the base URI so we don't refresh with some funky action= value - if (!isConfigure) - out.write("\n"); + if (!isConfigure) { + int delay = _manager.getRefreshDelaySeconds(); + if (delay > 0) + out.write("\n"); + } out.write(HEADER_A + _themePath + HEADER_B); out.write(""); out.write("
"); @@ -611,6 +613,7 @@ public class I2PSnarkServlet extends Default { } } else if ("Save".equals(action)) { String dataDir = req.getParameter("dataDir"); + boolean filesPublic = req.getParameter("filesPublic") != null; boolean autoStart = req.getParameter("autoStart") != null; String seedPct = req.getParameter("seedPct"); String eepHost = req.getParameter("eepHost"); @@ -620,11 +623,14 @@ public class I2PSnarkServlet extends Default { String i2cpOpts = buildI2CPOpts(req); String upLimit = req.getParameter("upLimit"); String upBW = req.getParameter("upBW"); + String refreshDel = req.getParameter("refreshDelay"); String startupDel = req.getParameter("startupDelay"); boolean useOpenTrackers = req.getParameter("useOpenTrackers") != null; String openTrackers = req.getParameter("openTrackers"); 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)) { String baseData = req.getParameter("baseFile"); if (baseData != null && baseData.trim().length() > 0) { @@ -1259,44 +1265,55 @@ public class I2PSnarkServlet extends Default { out.write("  "); - out.write(" " + + "\n"); - out.write(""); + out.write("\" name=\"foo\" >\n" + + ""); } + 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 { String dataDir = _manager.getDataDir().getAbsolutePath(); + boolean filesPublic = _manager.areFilesPublic(); boolean autoStart = _manager.shouldAutoStart(); boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers(); String openTrackers = _manager.util().getOpenTrackerString(); //int seedPct = 0; - out.write("
\n"); - out.write("
\n"); - out.write("\n"); - out.write("\n"); - out.write(""); - out.write("\"\" "); + out.write("\n" + + "
\n" + + "\n" + + "\n" + + "" + + "\"\" "); out.write(_("Configuration")); - out.write("
\n"); - out.write("
"); + out.write("
\n" + + "
"); out.write(_("Data directory")); out.write(": " + dataDir + " ("); out.write(_("Edit i2psnark.config and restart to change")); - out.write(")
\n"); + out.write(")
\n" + - out.write("
"); + "
"); + out.write(_("Files readable by all")); + out.write(": " + + + "
"); out.write(_("Auto start")); out.write(": "); + out.write("\" >" + - out.write("
"); + "
"); out.write(_("Theme")); out.write(": \n"); + out.write("\n" + - out.write("
"); + "
"); + out.write(_("Refresh time")); + out.write(":
" + + + "
"); out.write(_("Startup delay")); out.write(": "); out.write(_("minutes")); @@ -1340,26 +1376,26 @@ public class I2PSnarkServlet extends Default { out.write(": "); out.write(_("peers")); - out.write("
\n"); + out.write("
\n" + - out.write("
"); + "
"); out.write(_("Up bandwidth limit")); out.write(": KBps ("); out.write(_("Half available bandwidth recommended.")); out.write(" "); out.write(_("View or change router bandwidth")); - out.write(")
\n"); + out.write(")
\n" + - out.write("
"); + "
"); out.write(_("Use open trackers also")); out.write(": "); + out.write("\" > " + - out.write("
"); + "
"); out.write(_("Open tracker announce URLs")); out.write(":
\n"); @@ -1388,36 +1424,38 @@ public class I2PSnarkServlet extends Default { out.write("
"); out.write(_("I2CP host")); out.write(": "); + + _manager.util().getI2CPHost() + "\" size=\"15\" > " + - out.write("
"); + "
"); out.write(_("I2CP port")); out.write(":
\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); - for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry entry = (Map.Entry)iter.next(); - String key = (String)entry.getKey(); - String val = (String)entry.getValue(); + for (Map.Entry e : options.entrySet()) { + String key = e.getKey(); + String val = e.getValue(); opts.append(key).append('=').append(val).append(' '); } out.write("
"); out.write(_("I2CP options")); out.write(":
\n"); + + opts.toString() + "
\n" + - out.write("
  \n"); - out.write("
"); + out.write("\" name=\"foo\" >\n" + + "
"); } private void writeConfigLink(PrintWriter out) throws IOException { - out.write("
\n"); - out.write(""); - out.write("\"\" "); + out.write("\n"); } diff --git a/history.txt b/history.txt index 65aeb9ce03..79483016f3 100644 --- a/history.txt +++ b/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 * Update i2prouter script diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 8ab24107c9..80cfb9c849 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 = 17; + public final static long BUILD = 18; /** for example "-test" */ public final static String EXTRA = "";