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 9e1bf8f07..99b4c22ca 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -401,7 +401,7 @@ public class I2PSnarkServlet extends HttpServlet { if (i > 0) filename = filename.substring(0, i); if (filename.length() > MAX_DISPLAYED_FILENAME_LENGTH) - filename = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH) + "..."; + filename = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH) + "…"; long total = snark.meta.getTotalLength(); // Early typecast, avoid possibly overflowing a temp integer long remaining = (long) snark.storage.needed() * (long) snark.meta.getPieceLength(0); @@ -453,7 +453,7 @@ public class I2PSnarkServlet extends HttpServlet { statusString = "TrackerErr (" + curPeers + "/" + knownPeers + " peers)"; else { if (err.length() > MAX_DISPLAYED_ERROR_LENGTH) - err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "..."; + err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "…"; statusString = "TrackerErr
(" + err + ")"; } } else if (remaining <= 0) { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java index e4f8453bc..0b2d2d7c0 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java @@ -373,7 +373,7 @@ public class I2PTunnel implements Logging, EventDispatcher { privKeyFile = new File(args[2]); if (!privKeyFile.isAbsolute()) - privKeyFile = new File(_context.getAppDir(), args[2]); + privKeyFile = new File(_context.getConfigDir(), args[2]); if (!privKeyFile.canRead()) { l.log("private key file does not exist"); _log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]); @@ -422,7 +422,7 @@ public class I2PTunnel implements Logging, EventDispatcher { privKeyFile = new File(args[2]); if (!privKeyFile.isAbsolute()) - privKeyFile = new File(_context.getAppDir(), args[2]); + privKeyFile = new File(_context.getConfigDir(), args[2]); if (!privKeyFile.canRead()) { l.log("private key file does not exist"); _log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]); @@ -481,7 +481,7 @@ public class I2PTunnel implements Logging, EventDispatcher { privKeyFile = new File(args[3]); if (!privKeyFile.isAbsolute()) - privKeyFile = new File(_context.getAppDir(), args[3]); + privKeyFile = new File(_context.getConfigDir(), args[3]); if (!privKeyFile.canRead()) { l.log("private key file does not exist"); _log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]); @@ -877,7 +877,7 @@ public class I2PTunnel implements Logging, EventDispatcher { File privKeyFile = new File(args[1]); if (!privKeyFile.isAbsolute()) - privKeyFile = new File(_context.getAppDir(), args[1]); + privKeyFile = new File(_context.getConfigDir(), args[1]); if (!privKeyFile.canRead()) { l.log("private key file does not exist"); _log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 8fbba7ff3..fc8d5b76a 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -404,6 +404,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable } line = method + " " + request.substring(pos); + } else if (host.toLowerCase().equals("localhost") || host.equals("127.0.0.1")) { + if (out != null) { + out.write(ERR_LOCALHOST); + out.write("

Generated on: ".getBytes()); + out.write(new Date().toString().getBytes()); + out.write("\n".getBytes()); + out.flush(); + } + s.close(); + return; } else if (host.indexOf(".") != -1) { // rebuild host host = host + ":" + port; @@ -431,16 +441,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable usingWWWProxy = true; if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix(requestId) + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!"); - } else if (host.toLowerCase().startsWith("localhost:")) { - if (out != null) { - out.write(ERR_LOCALHOST); - out.write("

Generated on: ".getBytes()); - out.write(new Date().toString().getBytes()); - out.write("\n".getBytes()); - out.flush(); - } - s.close(); - return; } else { request = request.substring(pos + 1); pos = request.indexOf("/"); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java index 6efff96e5..b5ca6c3a1 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java @@ -73,7 +73,7 @@ public class TunnelController implements Logging { File keyFile = new File(getPrivKeyFile()); if (!keyFile.isAbsolute()) - keyFile = new File(I2PAppContext.getGlobalContext().getAppDir(), getPrivKeyFile()); + keyFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), getPrivKeyFile()); if (keyFile.exists()) { //log("Not overwriting existing private keys in " + keyFile.getAbsolutePath()); return; diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketOptionsImpl.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketOptionsImpl.java index 334c86af0..4ecf34d6a 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketOptionsImpl.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketOptionsImpl.java @@ -53,7 +53,7 @@ public class I2PSocketOptionsImpl implements I2PSocketOptions { _writeTimeout = getInt(opts, PROP_WRITE_TIMEOUT, DEFAULT_WRITE_TIMEOUT); } - protected int getInt(Properties opts, String name, int defaultVal) { + protected static int getInt(Properties opts, String name, int defaultVal) { if (opts == null) return defaultVal; String val = opts.getProperty(name); if (val == null) { diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/TestSwarm.java b/apps/ministreaming/java/test/net/i2p/client/streaming/TestSwarm.java similarity index 100% rename from apps/ministreaming/java/src/net/i2p/client/streaming/TestSwarm.java rename to apps/ministreaming/java/test/net/i2p/client/streaming/TestSwarm.java diff --git a/apps/routerconsole/java/build.xml b/apps/routerconsole/java/build.xml index d571e4809..f77a14387 100644 --- a/apps/routerconsole/java/build.xml +++ b/apps/routerconsole/java/build.xml @@ -123,6 +123,7 @@ + diff --git a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java index 037ca17af..e9749750c 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java @@ -115,7 +115,7 @@ public class GraphHelper extends HelperBase { + "\" /> pixels, height:
\n"); _out.write("Refresh delay:
\n"); - _out.write("


"); + _out.write("
"); } catch (IOException ioe) { ioe.printStackTrace(); } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java index f5bdd7342..10169ac9f 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -64,24 +64,15 @@ public class SummaryHelper extends HelperBase { return DataHelper.formatDuration(router.getUptime()); } - private static final DateFormat _fmt = new java.text.SimpleDateFormat("HH:mm:ss", Locale.UK); - public String getTime() { + private String timeSkew() { if (_context == null) return ""; - - String now = null; - synchronized (_fmt) { - now = _fmt.format(new Date(_context.clock().now())); - } - - if (!_context.clock().getUpdatedSuccessfully()) - return now + " (Unknown skew)"; - + //if (!_context.clock().getUpdatedSuccessfully()) + // return " (Unknown skew)"; long ms = _context.clock().getOffset(); - long diff = Math.abs(ms); - if (diff < 100) - return now; - return now + " (" + DataHelper.formatDuration(diff) + " skew)"; + if (diff < 3000) + return ""; + return " (" + DataHelper.formatDuration(diff) + " skew)"; } public boolean allowReseed() { @@ -90,9 +81,14 @@ public class SummaryHelper extends HelperBase { Boolean.valueOf(_context.getProperty("i2p.alwaysAllowReseed")).booleanValue()); } - public int getAllPeers() { return _context.netDb().getKnownRouters(); } + /** subtract one for ourselves, so if we know no other peers it displays zero */ + public int getAllPeers() { return Math.max(_context.netDb().getKnownRouters() - 1, 0); } public String getReachability() { + return reachability() + timeSkew(); + } + + private String reachability() { if (_context.router().getUptime() > 60*1000 && (!_context.router().gracefulShutdownInProgress()) && !_context.clientManager().isAlive()) return "ERR-Client Manager I2CP Error - check logs"; // not a router problem but the user should know @@ -354,7 +350,11 @@ public class SummaryHelper extends HelperBase { buf.append("* "); buf.append("
"); - buf.append(name).append("
\n"); + if (name.length() < 16) + buf.append(name); + else + buf.append(name.substring(0,15)).append("…"); + buf.append("
\n"); LeaseSet ls = _context.netDb().lookupLeaseSetLocally(client.calculateHash()); if (ls != null) { long timeToExpire = ls.getEarliestLeaseDate() - _context.clock().now(); diff --git a/apps/routerconsole/jsp/error.jsp b/apps/routerconsole/jsp/error.jsp new file mode 100644 index 000000000..da2dfeac8 --- /dev/null +++ b/apps/routerconsole/jsp/error.jsp @@ -0,0 +1,32 @@ +<%@page contentType="text/html"%> +<%@page pageEncoding="UTF-8"%> + +<% + // Let's make this easy... + final Integer ERROR_CODE = (Integer) request.getAttribute(org.mortbay.jetty.servlet.ServletHandler.__J_S_ERROR_STATUS_CODE); + final String ERROR_URI = (String) request.getAttribute(org.mortbay.jetty.servlet.ServletHandler.__J_S_ERROR_REQUEST_URI); + final String ERROR_MESSAGE = (String) request.getAttribute(org.mortbay.jetty.servlet.ServletHandler.__J_S_ERROR_MESSAGE); + if (ERROR_CODE != null && ERROR_MESSAGE != null) { + // this is deprecated but we don't want sendError() + response.setStatus(ERROR_CODE.intValue(), ERROR_MESSAGE); + } + // If it can't find the iframe or viewtheme.jsp I wonder if the whole thing blows up... +%> + +I2P Router Console + +<%@include file="css.jsp" %> + + +<% +if (System.getProperty("router.consoleNonce") == null) { + System.setProperty("router.consoleNonce", new java.util.Random().nextLong() + ""); +} +%> +<%@include file="summary.jsp" %> +

<%=ERROR_CODE%> <%=ERROR_MESSAGE%>

+
+The Router Console page <%=ERROR_URI%> was not found. +
+ + diff --git a/apps/routerconsole/jsp/index.jsp b/apps/routerconsole/jsp/index.jsp index e389bb15b..3056741e6 100644 --- a/apps/routerconsole/jsp/index.jsp +++ b/apps/routerconsole/jsp/index.jsp @@ -3,9 +3,9 @@ +<%@include file="css.jsp" %> I2P Router Console - home -<%@include file="css.jsp" %> <% diff --git a/apps/routerconsole/jsp/summarynoframe.jsp b/apps/routerconsole/jsp/summarynoframe.jsp index 655741b83..1713a6336 100644 --- a/apps/routerconsole/jsp/summarynoframe.jsp +++ b/apps/routerconsole/jsp/summarynoframe.jsp @@ -26,9 +26,9 @@ <% } else { %> I2P Services
-Susimail -SusiDNS -Torrents +Addressbook +Torrents +Webmail Webserver
I2P Internals
I2PTunnel @@ -48,14 +48,16 @@ Ident: (, never reveal it to anyone" href="netdb.jsp?r=." target="_top">view)
Version:
Uptime:
-Now:
Reachability: <% if (helper.updateAvailable()) { // display all the time so we display the final failure message out.print("
" + update.getStatus()); - if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false"))) { - } else if(!update.isDone()) { + if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress"))) { + } else if((!update.isDone()) && + request.getParameter("action") == null && + request.getParameter("updateNonce") == null && + net.i2p.router.web.ConfigRestartBean.getRestartTimeRemaining() > 12*60*1000) { long nonce = new java.util.Random().nextLong(); String prev = System.getProperty("net.i2p.router.web.UpdateHandler.nonce"); if (prev != null) System.setProperty("net.i2p.router.web.UpdateHandler.noncePrev", prev); diff --git a/apps/routerconsole/jsp/web.xml b/apps/routerconsole/jsp/web.xml index 7a8e431ce..a0436d305 100644 --- a/apps/routerconsole/jsp/web.xml +++ b/apps/routerconsole/jsp/web.xml @@ -21,4 +21,8 @@ index.html index.jsp + + 404 + /error.jsp + diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java index b978ff3be..7efc6cc40 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java @@ -284,6 +284,8 @@ public class ConnectionManager { // exporting non-public type through public API, this is a potential bug. public ConnectionHandler getConnectionHandler() { return _connectionHandler; } public PacketQueue getPacketQueue() { return _outboundQueue; } + /** do we respond to pings that aren't on an existing connection? */ + public boolean answerPings() { return _defaultOptions.getAnswerPings(); } /** * Something b0rked hard, so kill all of our connections without mercy. diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java index c7084b4e7..13e18baff 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionOptions.java @@ -9,6 +9,7 @@ import java.util.Properties; public class ConnectionOptions extends I2PSocketOptionsImpl { private int _connectDelay; private boolean _fullySigned; + private boolean _answerPings; private volatile int _windowSize; private int _receiveWindow; private int _profile; @@ -51,12 +52,15 @@ public class ConnectionOptions extends I2PSocketOptionsImpl { public static final String PROP_MAX_WINDOW_SIZE = "i2p.streaming.maxWindowSize"; public static final String PROP_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR = "i2p.streaming.congestionAvoidanceGrowthRateFactor"; public static final String PROP_SLOW_START_GROWTH_RATE_FACTOR = "i2p.streaming.slowStartGrowthRateFactor"; + public static final String PROP_ANSWER_PINGS = "i2p.streaming.answerPings"; private static final int TREND_COUNT = 3; static final int INITIAL_WINDOW_SIZE = 6; static final int DEFAULT_MAX_SENDS = 8; public static final int DEFAULT_INITIAL_RTT = 8*1000; static final int MIN_WINDOW_SIZE = 1; + private static final boolean DEFAULT_ANSWER_PINGS = true; + // Syncronization fix, but doing it this way causes NPE... // private final int _trend[] = new int[TREND_COUNT]; private int _trend[]; @@ -198,6 +202,7 @@ public class ConnectionOptions extends I2PSocketOptionsImpl { setSlowStartGrowthRateFactor(opts.getSlowStartGrowthRateFactor()); setWriteTimeout(opts.getWriteTimeout()); setReadTimeout(opts.getReadTimeout()); + setAnswerPings(opts.getAnswerPings()); } } @@ -221,8 +226,8 @@ public class ConnectionOptions extends I2PSocketOptionsImpl { setInboundBufferSize(getMaxMessageSize() * (Connection.MAX_WINDOW_SIZE + 2)); setCongestionAvoidanceGrowthRateFactor(getInt(opts, PROP_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR, 1)); setSlowStartGrowthRateFactor(getInt(opts, PROP_SLOW_START_GROWTH_RATE_FACTOR, 1)); - setConnectTimeout(getInt(opts, PROP_CONNECT_TIMEOUT, Connection.DISCONNECT_TIMEOUT)); + setAnswerPings(getBool(opts, PROP_ANSWER_PINGS, DEFAULT_ANSWER_PINGS)); } @Override @@ -260,9 +265,10 @@ public class ConnectionOptions extends I2PSocketOptionsImpl { setCongestionAvoidanceGrowthRateFactor(getInt(opts, PROP_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR, 2)); if (opts.contains(PROP_SLOW_START_GROWTH_RATE_FACTOR)) setSlowStartGrowthRateFactor(getInt(opts, PROP_SLOW_START_GROWTH_RATE_FACTOR, 2)); - if (opts.containsKey(PROP_CONNECT_TIMEOUT)) setConnectTimeout(getInt(opts, PROP_CONNECT_TIMEOUT, Connection.DISCONNECT_TIMEOUT)); + if (opts.containsKey(PROP_ANSWER_PINGS)) + setAnswerPings(getBool(opts, PROP_ANSWER_PINGS, DEFAULT_ANSWER_PINGS)); } /** @@ -282,11 +288,22 @@ public class ConnectionOptions extends I2PSocketOptionsImpl { * or can we deal with signatures on the SYN and FIN packets * only? * + * There is no property name defined for this, so it's safe to + * say this is unused and always false. + * * @return if we want signatures on all packets. */ public boolean getRequireFullySigned() { return _fullySigned; } public void setRequireFullySigned(boolean sign) { _fullySigned = sign; } + /** + * Do we respond to a ping? + * + * @return if we do + */ + public boolean getAnswerPings() { return _answerPings; } + public void setAnswerPings(boolean yes) { _answerPings = yes; } + /** * How many messages will we send before waiting for an ACK? * @@ -492,6 +509,13 @@ public class ConnectionOptions extends I2PSocketOptionsImpl { return buf.toString(); } + private static boolean getBool(Properties opts, String name, boolean defaultVal) { + if (opts == null) return defaultVal; + String val = opts.getProperty(name); + if (val == null) return defaultVal; + return Boolean.valueOf(val).booleanValue(); + } + public static void main(String args[]) { Properties p = new Properties(); diff --git a/apps/streaming/java/src/net/i2p/client/streaming/PacketHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/PacketHandler.java index bbb5a9536..19e62db0c 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/PacketHandler.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/PacketHandler.java @@ -129,7 +129,10 @@ public class PacketHandler { private void receiveKnownCon(Connection con, Packet packet) { if (packet.isFlagSet(Packet.FLAG_ECHO)) { if (packet.getSendStreamId() > 0) { - receivePing(packet); + if (con.getOptions().getAnswerPings()) + receivePing(packet); + else if (_log.shouldLog(Log.WARN)) + _log.warn("Dropping Echo packet on existing con: " + packet); } else if (packet.getReceiveStreamId() > 0) { receivePong(packet); } else { @@ -230,7 +233,10 @@ public class PacketHandler { private void receiveUnknownCon(Packet packet, long sendId, boolean queueIfNoConn) { if (packet.isFlagSet(Packet.FLAG_ECHO)) { if (packet.getSendStreamId() > 0) { - receivePing(packet); + if (_manager.answerPings()) + receivePing(packet); + else if (_log.shouldLog(Log.WARN)) + _log.warn("Dropping Echo packet on unknown con: " + packet); } else if (packet.getReceiveStreamId() > 0) { receivePong(packet); } else { diff --git a/build.xml b/build.xml index a831938ed..c77cfe0ac 100644 --- a/build.xml +++ b/build.xml @@ -205,7 +205,7 @@ - + @@ -571,4 +571,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index b3806d1b9..56528a46b 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -871,7 +871,7 @@ public class DataHelper { public static String formatDuration(long ms) { if (ms < 5 * 1000) { return ms + "ms"; - } else if (ms < 5 * 60 * 1000) { + } else if (ms < 3 * 60 * 1000) { return (ms / 1000) + "s"; } else if (ms < 120 * 60 * 1000) { return (ms / (60 * 1000)) + "m"; diff --git a/core/java/src/net/i2p/time/Timestamper.java b/core/java/src/net/i2p/time/Timestamper.java index c452f110a..4692c8d53 100644 --- a/core/java/src/net/i2p/time/Timestamper.java +++ b/core/java/src/net/i2p/time/Timestamper.java @@ -52,6 +52,15 @@ public class Timestamper implements Runnable { this(ctx, lsnr, true); } public Timestamper(I2PAppContext ctx, UpdateListener lsnr, boolean daemon) { + // Don't bother starting a thread if we are disabled. + // This means we no longer check every 5 minutes to see if we got enabled, + // so the property must be set at startup. + // We still need to be instantiated since the router calls clock().getTimestamper().waitForInitialization() + String disabled = ctx.getProperty(PROP_DISABLED, DEFAULT_DISABLED); + if (Boolean.valueOf(disabled).booleanValue()) { + _initialized = true; + return; + } _context = ctx; _daemon = daemon; _initialized = false; diff --git a/core/java/src/net/i2p/util/FileUtil.java b/core/java/src/net/i2p/util/FileUtil.java index 2946cd09e..38073fd60 100644 --- a/core/java/src/net/i2p/util/FileUtil.java +++ b/core/java/src/net/i2p/util/FileUtil.java @@ -76,9 +76,10 @@ public class FileUtil { } public static boolean extractZip(File zipfile, File targetDir) { + ZipFile zip = null; try { byte buf[] = new byte[16*1024]; - ZipFile zip = new ZipFile(zipfile); + zip = new ZipFile(zipfile); Enumeration entries = zip.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry)entries.nextElement(); @@ -124,13 +125,16 @@ public class FileUtil { } } } - zip.close(); return true; } catch (IOException ioe) { System.err.println("ERROR: Unable to extract the zip file"); ioe.printStackTrace(); return false; - } + } finally { + if (zip != null) { + try { zip.close(); } catch (IOException ioe) {} + } + } } /** diff --git a/core/java/src/net/i2p/crypto/SHA1Test.java b/core/java/test/net/i2p/crypto/SHA1Test.java similarity index 100% rename from core/java/src/net/i2p/crypto/SHA1Test.java rename to core/java/test/net/i2p/crypto/SHA1Test.java diff --git a/core/java/src/net/i2p/stat/SizeTest.java b/core/java/test/net/i2p/stat/SizeTest.java similarity index 100% rename from core/java/src/net/i2p/stat/SizeTest.java rename to core/java/test/net/i2p/stat/SizeTest.java diff --git a/history.txt b/history.txt index 890f0cd80..8fbb6eebd 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,41 @@ +2009-08-07 zzz + * build.xml: + - Try to automate the release process + - Take jetty back out of the updater after 4 releases + * Console: + - Add a custom error page + - Don't count ourselves in known peers + - Hide update button when shutting down + - Increase skew warning threshold to 3s (was 100ms) + - Remove UTC time from summary bar + - Truncate long dest names + - Try to reduce servlet problems on index page + * Core: + - Catch unzip fd leaks on error + - Move 2 test classes out of the lib + * Eepsite: + - Quote the jetty.xml path in clients.config, + and adjust the migration function, to fix the + eepsite-won't-start bug on windows + * HTTP Proxy: + - Restore the localhost error message + - Catch 127.0.0.1:xxxx addresses too + * I2PTunnel: + - Move the privkey files from the app dir to the + config dir, in preparation for splitting the two + dirs by default + * Ministreaming: + - Make getInt() static + - Move the big TestSwarm class out of the lib + * NetDb stats: Post-release cleanup + * PersistentKeyRing: Fix broken storage of keys in config file + * Router: Move the WorkingDir class from i2p.jar to router.jar + * Streaming: New option i2p.streaming.answerPings (default true) + * Timestamper: Don't start thread if not enabled + * Wrapper: + - Extend timeout to 20s (was 5s) + - Shorten ping interval to 5m (was 10m) + 2009-08-03 dr|z3d * Extensive update to the Classic theme; custom css hacks for IE. diff --git a/installer/resources/clients.config b/installer/resources/clients.config index 88bba5f9a..daa698908 100644 --- a/installer/resources/clients.config +++ b/installer/resources/clients.config @@ -20,7 +20,7 @@ clientApp.2.startOnLoad=true # run our own eepsite with a seperate jetty instance clientApp.3.main=org.mortbay.jetty.Server clientApp.3.name=My eepsite web server -clientApp.3.args=eepsite/jetty.xml +clientApp.3.args="eepsite/jetty.xml" clientApp.3.delay=30 clientApp.3.startOnLoad=true diff --git a/installer/resources/themes/console/classic/console.css b/installer/resources/themes/console/classic/console.css index 7b79f2860..3231ef874 100644 --- a/installer/resources/themes/console/classic/console.css +++ b/installer/resources/themes/console/classic/console.css @@ -132,6 +132,10 @@ div.routersummary a:hover { color: #f60; } +div.routersummary input[type=text] { + text-align: right !important; +} + div.warning { margin: 20px 20px 10px 260px; padding: 0px 20px 20px 75px; @@ -176,6 +180,7 @@ div.main { div.main li { padding-bottom: 10px; + list-style: square; } div.main li:first-child { @@ -223,6 +228,11 @@ div.news a:link { text-shadow: 0px 0px 1px rgba(128, 128, 48, 0.3); } +div.news a:visited { + color: #f00 !important; + text-shadow: 0px 0px 1px rgba(128, 128, 48, 0.3); +} + div.news hr { color: #cc7; background: #cc7; @@ -331,11 +341,20 @@ table { } table hr { - padding: 1px 0; + padding: 0px 0; + color: #bbf; + background: #bbf; + border: 0px solid #bbf; + margin: 0px -5px; + height: 1px; +} + +table tt { + font-size: 7.5pt; } th { - background-color: #def; + background-color: #fff; padding: 8px 2px; text-align: center; border-bottom: 1px solid #88f; @@ -345,6 +364,10 @@ tt { font-size: 8pt; } +tt, pre { + font: 8pt "Lucida Console", "DejaVu Sans Mono", Courier, mono; +} + td { padding: 4px; } diff --git a/installer/resources/themes/console/classic/ieshim.css b/installer/resources/themes/console/classic/ieshim.css index 3e897a7af..9fff032b1 100644 --- a/installer/resources/themes/console/classic/ieshim.css +++ b/installer/resources/themes/console/classic/ieshim.css @@ -36,8 +36,10 @@ div.configure table { } h1 { - padding: 15px 10px 16px 10px !important; + padding: 15px 10px 16px -10px !important; margin: 0 0px 0 175px !important; + background-color: #bbf !important; + color: #001; } h2 { @@ -97,6 +99,11 @@ div.routersummary { border-left: 5px solid #bbf; } +div.routersummary submit { + padding: 0; + margin-bottom: 5px; +} + div.news li { padding-top: 0px 0px !important; margin-bottom: -23px !important; @@ -131,4 +138,15 @@ div.configure hr{ input { padding: 0; +} + +div.graphspanel img { + border: 1px solid #99f; + margin: 6px 0 !important; + background: #ddf; + -moz-box-shadow: inset 0px 0px 1px 1px #99f; +} + +div.graphspanel hr { + margin: 20px 0; } \ No newline at end of file diff --git a/installer/resources/themes/console/dark/console.css b/installer/resources/themes/console/dark/console.css index 8e0d75d60..5c561e94a 100644 --- a/installer/resources/themes/console/dark/console.css +++ b/installer/resources/themes/console/dark/console.css @@ -89,7 +89,7 @@ div.routersummary { width: 175px; padding: 10px; text-align: center; - border: 1px solid #9999ff; + border: 1px solid #99f; background: #003; background: url(images/darkbluebg.png); color: #eef; @@ -102,6 +102,28 @@ div.routersummary { -moz-box-shadow: inset 0px 0px 1px 0px #eef; } +div.routersummary input[type=text] { + text-align: right !important; + -moz-box-shadow: inset 1px 1px 1px 0px #000; +} + +div.routersummary hr { + color: #99f; + background: #99f; + height: 1px; + border-bottom: 1px outset #bbf; + margin: 5px -10px 4px -10px; +} + +div.routersummary hr { + color: #bbf; + background: #bbf; + height: 2px; + border-bottom: 1px outset #bbf; + margin: 8px -10px 7px -10px; + -moz-box-shadow: inset 0px -4px 2px 1px #001; +} + div.warning { margin: 5px 20px 10px 240px; padding: 0px 25px 20px 75px; @@ -254,6 +276,16 @@ table { background: #003; } +table hr { + padding: 0px 0; + color: #99f; + background: #99f; + border: 0px solid #99f; + margin: 0px 0px; + height: 1px; + display: none; +} + th { padding: 6px 2px; color: #eef; @@ -392,7 +424,7 @@ h2 { color: #fff; text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.5); letter-spacing: 0.05em; - background: #003 url('images/darkbluebg.png'); + background: #003 url('images/titletile.png'); padding: 5px 10px 8px 10px; wordwrap: none; border: 1px solid #99f; @@ -435,9 +467,9 @@ h4 { font-size: 11pt; } -button { +button, button:visited { font: bold 9pt "Lucida Sans Unicode", "Bitstream Vera Sans", Verdana, Tahoma, Helvetica, sans-serif; - border: 1px outset #ddddc0; + border: 1px outset #77f; padding: 1px 3px; background: #bbf; text-decoration: none; @@ -450,12 +482,23 @@ button { text-align: center; vertical-align: middle; min-width: 76px; + -moz-box-shadow: inset 0px 1px 1px 0px #55f; + background: #003; + color: #99f; } +button:hover { + border: 1px solid #f60; + -moz-box-shadow: inset 0px 1px 1px 0px #eef; + background: #001; + color: #f60; +} + button:active { border: 1px inset #f60; background: #f60; color: #fff; + -moz-box-shadow: inset 0px 0px 0px 0px #f60; } .underline { @@ -488,9 +531,10 @@ sidebarlogo { } input { - border: 1px outset #bbf; - background: #bbf; - color: #002; + border: 1px outset #55f; + -moz-box-shadow: inset 0px 1px 1px 0px #55f; + background: #003; + color: #99f; margin: 5px; font: bold 8pt "Lucida Sans Unicode", "Bitstream Vera Sans", Verdana, Tahoma, Helvetica, sans-serif; padding: 1px 2px; @@ -502,9 +546,10 @@ input { } input:hover { - background: #003; + background: #001; color: #f60; border: 1px solid #f60; + -moz-box-shadow: inset 0px 1px 1px 0px #eef; } input:active { @@ -530,6 +575,7 @@ input[type=text] { border-radius: 4px; -moz-border-radius: 4px; -khtml-border-radius: 4px; + -moz-box-shadow: inset 1px 1px 1px 0px #000; } input[type=text]:active, input[type=text]:hover { diff --git a/installer/resources/themes/console/dark/images/titletile.png b/installer/resources/themes/console/dark/images/titletile.png new file mode 100644 index 000000000..945acc5b9 Binary files /dev/null and b/installer/resources/themes/console/dark/images/titletile.png differ diff --git a/installer/resources/themes/console/light/console.css b/installer/resources/themes/console/light/console.css index 20d8c28cf..26f8b40c5 100644 --- a/installer/resources/themes/console/light/console.css +++ b/installer/resources/themes/console/light/console.css @@ -105,6 +105,19 @@ div.routersummary { -moz-box-shadow: inset 0px 0px 1px 0px #002; } +div.routersummary input[type=text] { + text-align: right !important; +} + +div.routersummary hr { + color: #eef; + background: #eef; + height: 2px; + border-bottom: 1px solid #eef; + margin: 8px -10px 7px -10px; + -moz-box-shadow: inset 0px 1px 1px 1px #001; +} + div.warning { margin: 5px 20px 10px 240px; padding: 0px 25px 20px 75px; @@ -226,6 +239,7 @@ div.configure { border-radius: 4px; border: 1px solid #000022; -moz-box-shadow: inset 0px 0px 1px 0px #002; + min-width: 400px; } div.graphspanel { @@ -237,9 +251,9 @@ div.graphspanel { border-radius: 4px; border: 1px solid #000022; -moz-box-shadow: inset 0px 0px 1px 0px #002; + text-align: center !important; } - div.graphspanel img { border: 1px solid #003; padding: 2px; @@ -247,7 +261,7 @@ div.graphspanel img { text-align: center !important; background: #001; -moz-box-shadow: inset 0px 0px 1px 1px #99f; - opacity: 0.9; + opacity: 0.8; } div.graphspanel img:hover { @@ -260,6 +274,10 @@ div.graphspanel img:hover { opacity: 1; } +div.graphspanel form { + text-align: left; +} + div.messages { padding: 10px; margin: 10px 0 20px 0; @@ -301,6 +319,16 @@ table { font: 7pt/130% "Lucida Sans Unicode", Verdana, Bitstream Vera Sans", Tahoma, Helvetica, sans-serif; } +table hr { + padding: 0px 0; + color: #99f; + background: #99f; + border: 0px solid #99f; + margin: 0px 0px; + height: 1px; + display: none; +} + th { padding: 6px 2px; color: #000; @@ -433,7 +461,7 @@ h2 { font-size: 12pt; color: #001; letter-spacing: 0.05em; - background: #ddf url('images/lightbluetile.png'); + background: #ddf url('images/titletile.png'); text-shadow: 0px 0px 1px rgba(0, 0, 64, 0.5); padding: 7px 10px; wordwrap: none; @@ -476,9 +504,9 @@ h4 { button, button:visited { font: bold 9pt "Lucida Sans Unicode", "Bitstream Vera Sans", Verdana, Tahoma, Helvetica, sans-serif; - border: 1px outset #ddddc0; + border: 1px outset #999; padding: 1px 3px; - background: #bbf !important; + background: #ddf !important; text-decoration: none; border-radius: 4px; -moz-border-radius: 4px; @@ -488,18 +516,22 @@ button, button:visited { margin: 0 1px; text-align: center; min-width: 80px; + -moz-box-shadow: inset 0px 2px 8px 0px #fff; + color: #006; } button:hover{ border: 1px solid #f60; background: #f60 !important; color: #fff; + -moz-box-shadow: inset 0px 0px 0px 1px #fff; } button:active{ border: 1px solid #f60; background: #001 !important; color: #f60; + -moz-box-shadow: inset 0px 0px 0px 1px #f60; } .underline { @@ -531,8 +563,8 @@ input { } input, input:visited { - border: 1px outset #bbf; - background: #bbf; + border: 1px outset #999; + background: #ddf; color: #001; margin: 5px; font: bold 8pt "Lucida Sans Unicode", "Bitstream Vera Sans", Verdana, Tahoma, Helvetica, sans-serif; @@ -542,6 +574,9 @@ input, input:visited { border-radius: 4px; -moz-border-radius: 4px; -khtml-border-radius: 4px; + -moz-box-shadow: inset 0px 2px 8px 0px #fff; + color: #006; + opacity: 0.9; } @@ -549,7 +584,9 @@ input:hover { background: #f60; color: #fff; border: 1px solid #f60; - opacity: 0.9; + opacity: 1.0; + -moz-box-shadow: inset 0px 0px 0px 1px #fff; + } input:active { @@ -557,6 +594,7 @@ input:active { color: #f60; border: 1px solid #f60; opacity: 1.0; + -moz-box-shadow: inset 0px 0px 0px 1px #f60; } input[type=text] { @@ -595,6 +633,7 @@ select { border-radius: 4px; -moz-border-radius: 4px; -khtml-border-radius: 4px; + text-align: left !important; } textarea { diff --git a/installer/resources/themes/console/light/images/lightbluetile.png b/installer/resources/themes/console/light/images/lightbluetile.png index e7fc6c1f1..53f9d54de 100644 Binary files a/installer/resources/themes/console/light/images/lightbluetile.png and b/installer/resources/themes/console/light/images/lightbluetile.png differ diff --git a/installer/resources/themes/console/light/images/titletile.png b/installer/resources/themes/console/light/images/titletile.png new file mode 100644 index 000000000..beb9552ba Binary files /dev/null and b/installer/resources/themes/console/light/images/titletile.png differ diff --git a/installer/resources/themes/console/snark.css b/installer/resources/themes/console/snark.css index 4b6fbb2c3..a5551156f 100644 --- a/installer/resources/themes/console/snark.css +++ b/installer/resources/themes/console/snark.css @@ -56,8 +56,8 @@ body { font-size: 9pt; font-weight: bold; text-align: left; - margin: 0 0 15px 0; - padding: 0px; + margin: 0 0px 10px 0px; + padding: 0; border-spacing: 0px; -moz-border-radius: 4px 0 0 0; -khtml-border-radius: 4px; @@ -68,7 +68,7 @@ body { background: #f40 url('../console/images/orangetile.png'); color: #531; height: 64px; - width: 100%; + width: auto; } pre { @@ -95,7 +95,7 @@ th { border-top: 1px outset #001; border-bottom: 1px inset #001; background: #f60 url('/themes/console/images/tabletitleorange.png') repeat-x; - text-align: left; + text-align: right; whitespace: nowrap; } @@ -107,7 +107,7 @@ th { td { padding: 5px; - text-align: left; + text-align: right; } .snarkTorrentEven { background-color: #fb1; @@ -176,7 +176,7 @@ hr { } a:link{ - color: #830; + color: #930; text-decoration: none; font-weight: bold; word-wrap: break-word; @@ -189,7 +189,7 @@ a:visited{ } a:hover{ - color: #f40; + color: #900; font-weight: bold; } diff --git a/installer/resources/wrapper.config b/installer/resources/wrapper.config index 295811d9e..3f07e7c85 100644 --- a/installer/resources/wrapper.config +++ b/installer/resources/wrapper.config @@ -158,8 +158,10 @@ wrapper.jvm_exit.timeout=30 # Let's change the default from 60 to 15 seconds and see if anyone moans.. wrapper.restart.delay=15 -wrapper.ping.interval=600 -wrapper.ping.timeout=605 +wrapper.ping.interval=300 +# The ping timeout must be at least 5 seconds longer than the value of wrapper.ping.interval. +# Extend this if you are getting 'JVM appears hung' shutdowns. +wrapper.ping.timeout=320 # use the wrapper's internal timer thread. otherwise this would # force a restart of the router during daylight savings time as well diff --git a/router/java/src/net/i2p/router/PersistentKeyRing.java b/router/java/src/net/i2p/router/PersistentKeyRing.java index f9b24ce9f..c92437111 100644 --- a/router/java/src/net/i2p/router/PersistentKeyRing.java +++ b/router/java/src/net/i2p/router/PersistentKeyRing.java @@ -53,7 +53,7 @@ public class PersistentKeyRing extends KeyRing { if (key == null || key.length() != 44) continue; String hb = prop.substring(PROP_PFX.length()); - hb.replace("$", "="); + hb = hb.replace("$", "="); Hash dest = new Hash(); SessionKey sk = new SessionKey(); try { @@ -71,7 +71,7 @@ public class PersistentKeyRing extends KeyRing { for (Entry e : entrySet()) { buf.append("\n"); Hash h = e.getKey(); - buf.append(h.toBase64().substring(0, 6)).append("..."); + buf.append(h.toBase64().substring(0, 6)).append("…"); buf.append(""); LeaseSet ls = _ctx.netDb().lookupLeaseSetLocally(h); if (ls != null) { @@ -81,13 +81,13 @@ public class PersistentKeyRing extends KeyRing { if (in != null && in.getDestinationNickname() != null) buf.append(in.getDestinationNickname()); else - buf.append(dest.toBase64().substring(0, 6)).append("..."); + buf.append(dest.toBase64().substring(0, 6)).append("…"); } else { String host = _ctx.namingService().reverseLookup(dest); if (host != null) buf.append(host); else - buf.append(dest.toBase64().substring(0, 6)).append("..."); + buf.append(dest.toBase64().substring(0, 6)).append("…"); } } buf.append(""); diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index 5f7512958..0729211bf 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -35,6 +35,7 @@ import net.i2p.data.i2np.GarlicMessage; import net.i2p.router.message.GarlicMessageHandler; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; import net.i2p.router.startup.StartupJob; +import net.i2p.router.startup.WorkingDir; import net.i2p.router.transport.FIFOBandwidthLimiter; import net.i2p.stat.Rate; import net.i2p.stat.RateStat; @@ -44,7 +45,6 @@ import net.i2p.util.I2PThread; import net.i2p.util.Log; import net.i2p.util.SimpleScheduler; import net.i2p.util.SimpleTimer; -import net.i2p.util.WorkingDir; /** * Main driver for the router. diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 0226e038b..0116da736 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 = 07; + public final static long BUILD = 8; /** for example "-test" */ public final static String EXTRA = ""; public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA; diff --git a/router/java/src/net/i2p/router/StatisticsManager.java b/router/java/src/net/i2p/router/StatisticsManager.java index a3c54458a..eb49ae002 100644 --- a/router/java/src/net/i2p/router/StatisticsManager.java +++ b/router/java/src/net/i2p/router/StatisticsManager.java @@ -139,18 +139,8 @@ public class StatisticsManager implements Service { //includeRate("tunnel.buildRequestTime", stats, new long[] { 10*60*1000 }); long rate = 60*60*1000; - boolean commentOutIn076 = RouterVersion.VERSION.equals("0.7.5"); - if (commentOutIn076) { - includeRate("tunnel.buildClientExpire", stats, new long[] { rate }); - includeRate("tunnel.buildClientReject", stats, new long[] { rate }); - includeRate("tunnel.buildClientSuccess", stats, new long[] { rate }); - includeRate("tunnel.buildExploratoryExpire", stats, new long[] { rate }); - includeRate("tunnel.buildExploratoryReject", stats, new long[] { rate }); - includeRate("tunnel.buildExploratorySuccess", stats, new long[] { rate }); - } else { - includeTunnelRates("Client", stats, rate); - includeTunnelRates("Exploratory", stats, rate); - } + includeTunnelRates("Client", stats, rate); + includeTunnelRates("Exploratory", stats, rate); //includeRate("tunnel.rejectTimeout", stats, new long[] { 10*60*1000 }); //includeRate("tunnel.rejectOverloaded", stats, new long[] { 10*60*1000 }); //includeRate("tunnel.acceptLoad", stats, new long[] { 10*60*1000 }); diff --git a/core/java/src/net/i2p/util/WorkingDir.java b/router/java/src/net/i2p/router/startup/WorkingDir.java similarity index 97% rename from core/java/src/net/i2p/util/WorkingDir.java rename to router/java/src/net/i2p/router/startup/WorkingDir.java index 1f5960d2f..e124727d9 100644 --- a/core/java/src/net/i2p/util/WorkingDir.java +++ b/router/java/src/net/i2p/router/startup/WorkingDir.java @@ -1,4 +1,4 @@ -package net.i2p.util; +package net.i2p.router.startup; import java.io.BufferedWriter; import java.io.File; @@ -195,8 +195,10 @@ public class WorkingDir { out.println("# Modified by I2P User dir migration script"); String s = null; while ((s = DataHelper.readLine(in)) != null) { - if (s.endsWith("=eepsite/jetty.xml")) { - s = s.replace("=eepsite", '=' + todir.getAbsolutePath() + File.separatorChar + "eepsite"); + if (s.endsWith("=\"eepsite/jetty.xml\"")) { + s = s.replace("=\"eepsite/jetty.xml\"", "=\"" + todir.getAbsolutePath() + + File.separatorChar + "eepsite" + + File.separatorChar + "jetty.xml\""); } out.println(s); }