From 3602eb14f5081074c24415376166f92dcacfedfd Mon Sep 17 00:00:00 2001 From: zzz Date: Thu, 20 Aug 2009 14:35:07 +0000 Subject: [PATCH 1/8] kill deprecation warnings --- apps/ministreaming/java/build.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/ministreaming/java/build.xml b/apps/ministreaming/java/build.xml index 1f83b640dd..ca0889042c 100644 --- a/apps/ministreaming/java/build.xml +++ b/apps/ministreaming/java/build.xml @@ -23,7 +23,8 @@ - + + From 327102a254014ed212c7ee5b6f2892f9f532fce6 Mon Sep 17 00:00:00 2001 From: zzz Date: Thu, 20 Aug 2009 14:35:32 +0000 Subject: [PATCH 2/8] * Console: - Put favicon on every page - Make every page UTF-8 --- apps/routerconsole/jsp/css.jsp | 6 +++++- apps/routerconsole/jsp/error.jsp | 1 - apps/routerconsole/jsp/index.jsp | 2 -- apps/routerconsole/jsp/summaryframe.jsp | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/routerconsole/jsp/css.jsp b/apps/routerconsole/jsp/css.jsp index affe83099f..209cab2b64 100644 --- a/apps/routerconsole/jsp/css.jsp +++ b/apps/routerconsole/jsp/css.jsp @@ -2,6 +2,8 @@ /* * This should be included inside ..., * as it sets the stylesheet. + * + * This is included almost 30 times, so keep whitespace etc. to a minimum. */ response.setHeader("Pragma", "no-cache"); @@ -15,7 +17,9 @@ session.setAttribute("i2p.contextId", request.getParameter("i2p.contextId")); } %> + + " /> console.css" rel="stylesheet" type="text/css"> - \ No newline at end of file + diff --git a/apps/routerconsole/jsp/error.jsp b/apps/routerconsole/jsp/error.jsp index 92da24f4d3..017efaa340 100644 --- a/apps/routerconsole/jsp/error.jsp +++ b/apps/routerconsole/jsp/error.jsp @@ -13,7 +13,6 @@ // 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" %> <% diff --git a/apps/routerconsole/jsp/index.jsp b/apps/routerconsole/jsp/index.jsp index 2bef637521..b14f8e3525 100644 --- a/apps/routerconsole/jsp/index.jsp +++ b/apps/routerconsole/jsp/index.jsp @@ -5,8 +5,6 @@ <%@include file="css.jsp" %> I2P Router Console - home - - <% if (System.getProperty("router.consoleNonce") == null) { diff --git a/apps/routerconsole/jsp/summaryframe.jsp b/apps/routerconsole/jsp/summaryframe.jsp index 05ad49ad7d..5d1d9eb2b9 100644 --- a/apps/routerconsole/jsp/summaryframe.jsp +++ b/apps/routerconsole/jsp/summaryframe.jsp @@ -10,7 +10,6 @@ <%@include file="css.jsp" %> Summary Bar - <% // try hard to avoid an error page in the iframe after shutdown String action = request.getParameter("action"); From 6d3a5856b4e11503b8c78ace3398b78f479ceaa2 Mon Sep 17 00:00:00 2001 From: zzz Date: Thu, 20 Aug 2009 15:43:27 +0000 Subject: [PATCH 3/8] options cleanup on configtunnels.jsp --- .../i2p/router/web/ConfigTunnelsHelper.java | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java index 0a7bc1b0a8..393476f061 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java @@ -154,28 +154,35 @@ buf.append("\n"); // custom options - buf.append("Inbound options:\n"); - buf.append(" 0) { + buf.append("Inbound options:\n" + + "\n"); } - buf.append("\"/>\n"); - buf.append("Outbound options:\n"); - buf.append(" 0) { + buf.append("Outbound options:\n" + + "\n"); } - buf.append("\"/>\n"); // buf.append("
\n"); } From 37437da34dda79ff8f4708be556a310bd87aad80 Mon Sep 17 00:00:00 2001 From: zzz Date: Thu, 20 Aug 2009 22:22:07 +0000 Subject: [PATCH 4/8] * I2CP: Fix the SessionConfig serializer in DataHelper, so that UTF-8 tunnel names are not corrupted by I2CP and can be displayed on the console * Fix UTF-8 form submission on console and i2ptunnel --- apps/i2ptunnel/jsp/edit.jsp | 1 + apps/i2ptunnel/jsp/index.jsp | 13 ++-- apps/routerconsole/jsp/css.jsp | 4 ++ core/java/src/net/i2p/data/DataHelper.java | 61 +++++++++++++++++-- .../src/net/i2p/data/i2cp/SessionConfig.java | 6 +- 5 files changed, 72 insertions(+), 13 deletions(-) diff --git a/apps/i2ptunnel/jsp/edit.jsp b/apps/i2ptunnel/jsp/edit.jsp index b58798b202..2da356e9cd 100644 --- a/apps/i2ptunnel/jsp/edit.jsp +++ b/apps/i2ptunnel/jsp/edit.jsp @@ -1,3 +1,4 @@ +<%@page pageEncoding="UTF-8"%> <%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean" %><% String tun = request.getParameter("tunnel"); if (tun != null) { diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp index 45a3da56a5..87a006f6db 100644 --- a/apps/i2ptunnel/jsp/index.jsp +++ b/apps/i2ptunnel/jsp/index.jsp @@ -1,3 +1,9 @@ +<% + // http://www.crazysquirrel.com/computing/general/form-encoding.jspx + if (request.getCharacterEncoding() == null) + request.setCharacterEncoding("UTF-8"); +%> +<%@page pageEncoding="UTF-8"%> <%@page contentType="text/html" import="net.i2p.i2ptunnel.web.IndexBean"%> @@ -6,13 +12,12 @@ I2P Tunnel Manager - List - + + <% if (indexBean.allowCSS()) { - %> - + %> <% } %> diff --git a/apps/routerconsole/jsp/css.jsp b/apps/routerconsole/jsp/css.jsp index 209cab2b64..422d1329ce 100644 --- a/apps/routerconsole/jsp/css.jsp +++ b/apps/routerconsole/jsp/css.jsp @@ -6,6 +6,10 @@ * This is included almost 30 times, so keep whitespace etc. to a minimum. */ + // http://www.crazysquirrel.com/computing/general/form-encoding.jspx + if (request.getCharacterEncoding() == null) + request.setCharacterEncoding("UTF-8"); + response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires", 0); diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index 0f48efef2d..f97811d376 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -105,6 +105,19 @@ public class DataHelper { */ public static void writeProperties(OutputStream rawStream, Properties props) throws DataFormatException, IOException { + writeProperties(rawStream, props, false); + } + + /** + * jrandom disabled UTF-8 in mid-2004, for performance reasons, + * i.e. slow foo.getBytes("UTF-8") + * Re-enable it so we can pass UTF-8 tunnel names through the I2CP SessionConfig. + * + * Use utf8 = false for RouterAddress (fast, non UTF-8) + * Use utf8 = true for SessionConfig (slow, UTF-8) + */ + public static void writeProperties(OutputStream rawStream, Properties props, boolean utf8) + throws DataFormatException, IOException { if (props != null) { OrderedProperties p = new OrderedProperties(); p.putAll(props); @@ -112,12 +125,15 @@ public class DataHelper { for (Iterator iter = p.keySet().iterator(); iter.hasNext();) { String key = (String) iter.next(); String val = p.getProperty(key); - // now make sure they're in UTF-8 - //key = new String(key.getBytes(), "UTF-8"); - //val = new String(val.getBytes(), "UTF-8"); - writeString(baos, key); + if (utf8) + writeStringUTF8(baos, key); + else + writeString(baos, key); baos.write(_equalBytes); - writeString(baos, val); + if (utf8) + writeStringUTF8(baos, val); + else + writeString(baos, val); baos.write(_semicolonBytes); } baos.close(); @@ -486,6 +502,7 @@ public class DataHelper { /** Read in a string from the stream as specified by the I2P data structure spec. * A string is 1 or more bytes where the first byte is the number of bytes (not characters!) * in the string and the remaining 0-255 bytes are the non-null terminated UTF-8 encoded character array. + * * @param in stream to read from * @throws DataFormatException if the stream doesn't contain a validly formatted string * @throws IOException if there is an IO error reading the string @@ -496,12 +513,16 @@ public class DataHelper { byte raw[] = new byte[size]; int read = read(in, raw); if (read != size) throw new DataFormatException("Not enough bytes to read the string"); - return new String(raw); + // the following constructor throws an UnsupportedEncodingException which is an IOException, + // but that's only if UTF-8 is not supported. Other encoding errors are not thrown. + return new String(raw, "UTF-8"); } /** Write out a string to the stream as specified by the I2P data structure spec. Note that the max * size for a string allowed by the spec is 255 bytes. * + * WARNING - this method destroys the encoding + * * @param out stream to write string * @param string string to write out: null strings are perfectly valid, but strings of excess length will * cause a DataFormatException to be thrown @@ -523,6 +544,34 @@ public class DataHelper { } } + /** Write out a string to the stream as specified by the I2P data structure spec. Note that the max + * size for a string allowed by the spec is 255 bytes. + * + * This method correctly uses UTF-8 + * + * @param out stream to write string + * @param string UTF-8 string to write out: null strings are perfectly valid, but strings of excess length will + * cause a DataFormatException to be thrown + * @throws DataFormatException if the string is not valid + * @throws IOException if there is an IO error writing the string + */ + private static void writeStringUTF8(OutputStream out, String string) + throws DataFormatException, IOException { + if (string == null) { + writeLong(out, 1, 0); + } else { + // the following method throws an UnsupportedEncodingException which is an IOException, + // but that's only if UTF-8 is not supported. Other encoding errors are not thrown. + byte[] raw = string.getBytes("UTF-8"); + int len = raw.length; + if (len > 255) + throw new DataFormatException("The I2P data spec limits strings to 255 bytes or less, but this is " + + string.length() + " [" + string + "]"); + writeLong(out, 1, len); + out.write(raw); + } + } + /** Read in a boolean as specified by the I2P data structure spec. * A boolean is 1 byte that is either 0 (false), 1 (true), or 2 (null) * @param in stream to read from diff --git a/core/java/src/net/i2p/data/i2cp/SessionConfig.java b/core/java/src/net/i2p/data/i2cp/SessionConfig.java index 5b1eb6b164..520413620d 100644 --- a/core/java/src/net/i2p/data/i2cp/SessionConfig.java +++ b/core/java/src/net/i2p/data/i2cp/SessionConfig.java @@ -173,7 +173,7 @@ public class SessionConfig extends DataStructureImpl { _log.debug("PubKey size for destination: " + _destination.getPublicKey().getData().length); _log.debug("SigningKey size for destination: " + _destination.getSigningPublicKey().getData().length); _destination.writeBytes(out); - DataHelper.writeProperties(out, _options); + DataHelper.writeProperties(out, _options, true); // UTF-8 DataHelper.writeDate(out, _creationDate); } catch (IOException ioe) { _log.error("IOError signing", ioe); @@ -198,7 +198,7 @@ public class SessionConfig extends DataStructureImpl { if ((_destination == null) || (_options == null) || (_signature == null) || (_creationDate == null)) throw new DataFormatException("Not enough data to create the session config"); _destination.writeBytes(out); - DataHelper.writeProperties(out, _options); + DataHelper.writeProperties(out, _options, true); // UTF-8 DataHelper.writeDate(out, _creationDate); _signature.writeBytes(out); } @@ -232,4 +232,4 @@ public class SessionConfig extends DataStructureImpl { buf.append("]"); return buf.toString(); } -} \ No newline at end of file +} From cdc184c5e50602d75473304f63c7239dcfd25046 Mon Sep 17 00:00:00 2001 From: zzz Date: Fri, 21 Aug 2009 15:37:13 +0000 Subject: [PATCH 5/8] * HTTP Proxy: Get mime type right for .ico * DataHelper: Cleanup --- .../java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java | 2 ++ core/java/src/net/i2p/data/DataHelper.java | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 075483529b..fc428bc265 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -843,6 +843,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable String type; if (filename.endsWith(".css")) type = "text/css"; + else if (filename.endsWith(".ico")) + type = "image/x-icon"; else if (filename.endsWith(".png")) type = "image/png"; else if (filename.endsWith(".jpg")) diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index f97811d376..fdd560243f 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -521,7 +521,8 @@ public class DataHelper { /** Write out a string to the stream as specified by the I2P data structure spec. Note that the max * size for a string allowed by the spec is 255 bytes. * - * WARNING - this method destroys the encoding + * WARNING - this method destroys the encoding, and therefore violates + * the data structure spec. * * @param out stream to write string * @param string string to write out: null strings are perfectly valid, but strings of excess length will @@ -537,7 +538,7 @@ public class DataHelper { int len = string.length(); if (len > 255) throw new DataFormatException("The I2P data spec limits strings to 255 bytes or less, but this is " - + string.length() + " [" + string + "]"); + + len + " [" + string + "]"); writeLong(out, 1, len); for (int i = 0; i < len; i++) out.write((byte)(string.charAt(i) & 0xFF)); @@ -566,7 +567,7 @@ public class DataHelper { int len = raw.length; if (len > 255) throw new DataFormatException("The I2P data spec limits strings to 255 bytes or less, but this is " - + string.length() + " [" + string + "]"); + + len + " [" + string + "]"); writeLong(out, 1, len); out.write(raw); } From 22c0b8e5243eb670121a0d06a1b12ac3bfa0e95c Mon Sep 17 00:00:00 2001 From: zzz Date: Fri, 21 Aug 2009 23:36:21 +0000 Subject: [PATCH 6/8] * profiles.jsp: Bulletproofing, less memory usage * Updates: Verify zip at startup before extracting * Wrapper: Take a couple fields out of the log so it's narrower --- installer/resources/wrapper.config | 8 ++++++-- router/java/src/net/i2p/router/Router.java | 7 ++++++- .../router/peermanager/ProfileOrganizerRenderer.java | 10 +++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/installer/resources/wrapper.config b/installer/resources/wrapper.config index 3f07e7c858..3fbe0375e8 100644 --- a/installer/resources/wrapper.config +++ b/installer/resources/wrapper.config @@ -117,8 +117,12 @@ wrapper.logfile=$SYSTEM_java_io_tmpdir/wrapper.log # no need for a wrapper.java.additional line too. #wrapper.logfile=$INSTALL_PATH/wrapper.log -# Format of output for the log file. (See docs for formats) -wrapper.logfile.format=LPTM +# Format of output for the log file. +# The format consists of the tokens 'L' for log level, 'P' for prefix, 'D' for thread, +# 'T' for time, 'Z' for millisecond time, and 'M' for message +# Unfortunately the log timezone cannot be changed, see +# http://www.nabble.com/Log-message-timezone-td23651317.html +wrapper.logfile.format=TM # Log Level for log file output. (See docs for log levels) wrapper.logfile.loglevel=INFO diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index f49a381463..1b20bda9d5 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -1109,7 +1109,11 @@ public class Router { return; } System.out.println("INFO: Update file exists [" + UPDATE_FILE + "] - installing"); - boolean ok = FileUtil.extractZip(updateFile, _context.getBaseDir()); + // verify the whole thing first + // we could remember this fails, and not bother restarting, but who cares... + boolean ok = FileUtil.verifyZip(updateFile); + if (ok) + ok = FileUtil.extractZip(updateFile, _context.getBaseDir()); if (ok) System.out.println("INFO: Update installed"); else @@ -1132,6 +1136,7 @@ public class Router { updateFile.deleteOnExit(); } } + // exit whether ok or not if (System.getProperty("wrapper.version") != null) System.out.println("INFO: Restarting after update"); else diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java index 1e3d71fc87..870e647c9a 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java @@ -111,10 +111,11 @@ class ProfileOrganizerRenderer { if (isIntegrated) buf.append(", Integrated"); RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer); if (info != null) { - buf.append(" (").append(info.getCapabilities()); + // prevent HTML injection in the caps and version + buf.append(" (").append(DataHelper.stripHTML(info.getCapabilities())); String v = info.getOption("router.version"); if (v != null) - buf.append(' ').append(v); + buf.append(' ').append(DataHelper.stripHTML(v)); buf.append(')'); } @@ -153,6 +154,9 @@ class ProfileOrganizerRenderer { buf.append("profile"); buf.append(" +-\n"); buf.append(""); + // let's not build the whole page in memory (~500 bytes per peer) + out.write(buf.toString()); + buf.setLength(0); } buf.append(""); @@ -189,7 +193,7 @@ class ProfileOrganizerRenderer { buf.append(""); RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer); if (info != null) - buf.append("" + info.getCapabilities() + ""); + buf.append("").append(DataHelper.stripHTML(info.getCapabilities())).append(""); else buf.append(" "); buf.append(""); From 35c9e999142c6aaff72d28b66c499587052c3b6a Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 22 Aug 2009 16:23:15 +0000 Subject: [PATCH 7/8] - Throw 403 instead of 404 from flags.jsp and viewstat.jsp so we don't render error.jsp --- apps/routerconsole/jsp/flags.jsp | 8 +++++++- apps/routerconsole/jsp/viewstat.jsp | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/routerconsole/jsp/flags.jsp b/apps/routerconsole/jsp/flags.jsp index fc93fcea7b..00ce370fb6 100644 --- a/apps/routerconsole/jsp/flags.jsp +++ b/apps/routerconsole/jsp/flags.jsp @@ -25,6 +25,12 @@ if (c != null && c.length() > 0) { if (rendered) cout.close(); } +/* + * Send a 403 instead of a 404, because the server sends error.jsp + * for 404 errors, complete with the summary bar, which would be + * a huge load for a page full of flags if the user didn't have the + * flags directory for some reason. + */ if (!rendered) - response.sendError(404, "Not found"); + response.sendError(403, "Flag not found"); %> \ No newline at end of file diff --git a/apps/routerconsole/jsp/viewstat.jsp b/apps/routerconsole/jsp/viewstat.jsp index aee42b9585..392a37b89c 100644 --- a/apps/routerconsole/jsp/viewstat.jsp +++ b/apps/routerconsole/jsp/viewstat.jsp @@ -63,7 +63,12 @@ if ( !rendered && ((rs != null) || fakeBw) ) { } } catch (NumberFormatException nfe) {} } +/* + * Send a 403 instead of a 404, because the server sends error.jsp + * for 404 errors, complete with the summary bar, which would be + * a huge load for a page full of graphs if there's a problem + */ if (!rendered) { - response.sendError(404, "That stat is not available"); + response.sendError(403, "That stat is not available"); } %> \ No newline at end of file From 51fd4d70dac35911783937492e5f94e0e8cde35e Mon Sep 17 00:00:00 2001 From: zzz Date: Mon, 24 Aug 2009 00:08:19 +0000 Subject: [PATCH 8/8] cleanup --- .../router/transport/ntcp/NTCPTransport.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java index ade88566a2..c991830d7a 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java +++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java @@ -645,20 +645,20 @@ public class NTCPTransport extends TransportImpl { buf.append("

NTCP connections: ").append(peers.size()); buf.append(". Limit: ").append(getMaxConnections()); buf.append(". Timeout: ").append(DataHelper.formatDuration(_pumper.getIdleTimeout())); - buf.append(".

\n"); - buf.append("
\n"); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(""); - buf.append(" \n"); + buf.append(".\n" + + "
PeerDirIdleIn/OutUpSkewTXRXOut queueBacklogged?Reading?
\n" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + " \n"); out.write(buf.toString()); buf.setLength(0); for (Iterator iter = peers.iterator(); iter.hasNext(); ) { @@ -726,8 +726,8 @@ public class NTCPTransport extends TransportImpl { buf.append("\n"); + buf.append("\n"); } buf.append("
PeerDirIdleIn/OutUpSkewTXRXOut queueBacklogged?Reading?
").append(DataHelper.formatDuration(totalUptime/peers.size())); buf.append(" ").append(peers.size() > 0 ? DataHelper.formatDuration(offsetTotal*1000/peers.size()) : "0ms"); buf.append(" ").append(totalSend).append(" ").append(totalRecv); - buf.append("      "); - buf.append("
     " + + "

\n");