diff --git a/apps/jetty/build.xml b/apps/jetty/build.xml index 991bab7bda..43b9bec264 100644 --- a/apps/jetty/build.xml +++ b/apps/jetty/build.xml @@ -277,8 +277,6 @@ - - diff --git a/apps/jetty/java/src/net/i2p/jetty/package.html b/apps/jetty/java/src/net/i2p/jetty/package.html new file mode 100644 index 0000000000..f0d02d8f87 --- /dev/null +++ b/apps/jetty/java/src/net/i2p/jetty/package.html @@ -0,0 +1,7 @@ + + +

+Classes for starting Jetty, logging requests, and debug logging to the I2P router log. +

+ + diff --git a/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java b/apps/jetty/java/src/net/i2p/servlet/RequestWrapper.java similarity index 90% rename from apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java rename to apps/jetty/java/src/net/i2p/servlet/RequestWrapper.java index 1e3cdb70b1..4ec622f204 100644 --- a/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java +++ b/apps/jetty/java/src/net/i2p/servlet/RequestWrapper.java @@ -21,7 +21,7 @@ * * $Revision: 1.3 $ */ -package i2p.susi.webmail; +package net.i2p.servlet; import java.io.IOException; import java.io.InputStream; @@ -48,13 +48,15 @@ import org.mortbay.servlet.MultiPartRequest; * * The filter would have been added in web.xml, * see that file, where it's commented out. + * Filter isn't supported until Tomcat 7 (Servlet 3.0) * - * @author user + * @author user + * @since 0.9.19 moved from susimail so it may be used by routerconsole too */ -class RequestWrapper { +public class RequestWrapper { private final HttpServletRequest httpRequest; - private MultiPartRequest multiPartRequest; + private final MultiPartRequest multiPartRequest; private final Hashtable cache; private Hashtable cachedParameterNames; @@ -65,14 +67,16 @@ class RequestWrapper { cache = new Hashtable(); this.httpRequest = httpRequest; String contentType = httpRequest.getContentType(); + MultiPartRequest mpr = null; if( contentType != null && contentType.toLowerCase(Locale.US).startsWith( "multipart/form-data" ) ) { try { - multiPartRequest = new MultiPartRequest( httpRequest ); + mpr = new MultiPartRequest( httpRequest ); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } + multiPartRequest = mpr; } /** diff --git a/apps/jetty/java/src/net/i2p/servlet/filters/package.html b/apps/jetty/java/src/net/i2p/servlet/filters/package.html new file mode 100644 index 0000000000..3b34aa9e8d --- /dev/null +++ b/apps/jetty/java/src/net/i2p/servlet/filters/package.html @@ -0,0 +1,7 @@ + + +

+XSS filter, since 0.9.14. +

+ + diff --git a/apps/jetty/java/src/net/i2p/servlet/package.html b/apps/jetty/java/src/net/i2p/servlet/package.html new file mode 100644 index 0000000000..689f508ab4 --- /dev/null +++ b/apps/jetty/java/src/net/i2p/servlet/package.html @@ -0,0 +1,11 @@ + + +

+RequestWrapper was a susimail class, +moved from susimail to jetty-i2p.jar when we needed them in the router console also. +As of 0.9.19. +Requires org.mortbay classes also in this jar. +Will be maintained as a public API until we move to Tomcat 7 (servlet 3.0). +

+ + diff --git a/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java b/apps/jetty/java/src/org/mortbay/servlet/MultiPartRequest.java similarity index 99% rename from apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java rename to apps/jetty/java/src/org/mortbay/servlet/MultiPartRequest.java index 88bc0296dc..1c964b8f19 100644 --- a/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java +++ b/apps/jetty/java/src/org/mortbay/servlet/MultiPartRequest.java @@ -263,7 +263,7 @@ public class MultiPartRequest { // Get first boundary String line = _in.readLine(); - if (!line.equals(_boundary)) + if (line == null || !line.equals(_boundary)) { //log.warn(line); throw new IOException("Missing initial multi part boundary"); diff --git a/apps/jetty/java/src/org/mortbay/servlet/package.html b/apps/jetty/java/src/org/mortbay/servlet/package.html new file mode 100644 index 0000000000..452eab1dd2 --- /dev/null +++ b/apps/jetty/java/src/org/mortbay/servlet/package.html @@ -0,0 +1,11 @@ + + +

+Old Jetty 5 classes for multipart form requests, moved to susimail and modded when we moved to Jetty 6, +then moved from susimail to jetty-i2p.jar when we needed them in the router console also. +As of 0.9.19. +Not a public API, not for direct use. +These are requirements for net.i2p.servlet.RequestWrapper. +

+ + diff --git a/apps/susimail/src/src/org/mortbay/util/ByteArrayPool.java b/apps/jetty/java/src/org/mortbay/util/ByteArrayPool.java similarity index 100% rename from apps/susimail/src/src/org/mortbay/util/ByteArrayPool.java rename to apps/jetty/java/src/org/mortbay/util/ByteArrayPool.java diff --git a/apps/susimail/src/src/org/mortbay/util/LineInput.java b/apps/jetty/java/src/org/mortbay/util/LineInput.java similarity index 100% rename from apps/susimail/src/src/org/mortbay/util/LineInput.java rename to apps/jetty/java/src/org/mortbay/util/LineInput.java diff --git a/apps/susimail/src/src/org/mortbay/util/MultiMap.java b/apps/jetty/java/src/org/mortbay/util/MultiMap.java similarity index 100% rename from apps/susimail/src/src/org/mortbay/util/MultiMap.java rename to apps/jetty/java/src/org/mortbay/util/MultiMap.java diff --git a/apps/jetty/java/src/org/mortbay/util/package.html b/apps/jetty/java/src/org/mortbay/util/package.html new file mode 100644 index 0000000000..452eab1dd2 --- /dev/null +++ b/apps/jetty/java/src/org/mortbay/util/package.html @@ -0,0 +1,11 @@ + + +

+Old Jetty 5 classes for multipart form requests, moved to susimail and modded when we moved to Jetty 6, +then moved from susimail to jetty-i2p.jar when we needed them in the router console also. +As of 0.9.19. +Not a public API, not for direct use. +These are requirements for net.i2p.servlet.RequestWrapper. +

+ + diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHandler.java index 2a5dea144d..df7a7983a7 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHandler.java @@ -1,6 +1,5 @@ package net.i2p.router.web; -import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.IOException; import java.net.URL; @@ -10,7 +9,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import net.i2p.data.DataHelper; import net.i2p.router.networkdb.reseed.Reseeder; /** @@ -76,15 +74,14 @@ public class ConfigReseedHandler extends FormHandler { addFormError(_("Bad URL {0}", val) + " - " + iae.getMessage()); } } else if (_action.equals(_("Reseed from file"))) { - //////// FIXME multipart - String val = getJettyString("file"); - if (val == null || val.length() == 0) { - addFormError(_("You must enter a file")); - return; - } - ByteArrayInputStream bais = new ByteArrayInputStream(DataHelper.getASCII(val)); + InputStream in = _requestWrapper.getInputStream("file"); try { - int count = _context.netDb().reseedChecker().requestReseed(bais); + // non-null but zero bytes if no file entered, don't know why + if (in == null || in.available() <= 0) { + addFormError(_("You must enter a file")); + return; + } + int count = _context.netDb().reseedChecker().requestReseed(in); if (count <= 0) { addFormError(_("Reseed from file failed")); } else { @@ -94,6 +91,10 @@ public class ConfigReseedHandler extends FormHandler { } } catch (IOException ioe) { addFormError(_("Reseed from file failed") + " - " + ioe); + } finally { + // it's really a ByteArrayInputStream but we'll play along... + if (in != null) + try { in.close(); } catch (IOException ioe) {} } } else if (_action.equals(_("Save changes"))) { saveChanges(); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java index 5d66bd5a10..ec22ae8b6d 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java @@ -7,6 +7,7 @@ import java.util.Map; import net.i2p.data.DataHelper; import net.i2p.router.RouterContext; +import net.i2p.servlet.RequestWrapper; import net.i2p.util.Log; /** @@ -21,7 +22,10 @@ import net.i2p.util.Log; public abstract class FormHandler { protected RouterContext _context; protected Log _log; + /** Not for multipart/form-data, will be null */ protected Map _settings; + /** Only for multipart/form-data. Warning, parameters are NOT XSS filtered */ + protected RequestWrapper _requestWrapper; private String _nonce, _nonce1, _nonce2; protected String _action; protected String _method; @@ -61,6 +65,15 @@ public abstract class FormHandler { */ public void setSettings(Map settings) { _settings = new HashMap(settings); } + /** + * Only set by formhandler.jsi for multipart/form-data + * + * @since 0.9.19 + */ + public void setRequestWrapper(RequestWrapper rw) { + _requestWrapper = rw; + } + /** * Same as HelperBase * @since 0.9.14.1 diff --git a/apps/routerconsole/jsp/formhandler.jsi b/apps/routerconsole/jsp/formhandler.jsi index e00bf6f436..b6091e80f8 100644 --- a/apps/routerconsole/jsp/formhandler.jsi +++ b/apps/routerconsole/jsp/formhandler.jsi @@ -29,12 +29,31 @@ // nonce1 will be null, removed in setAttibute below } - // Put all the params in the map, some handlers use this instead of individual setters - // We also call all of the setters below. - formhandler.setSettings(request.getParameterMap()); + String contentType = request.getContentType(); + if (contentType != null && contentType.toLowerCase(java.util.Locale.US).startsWith( "multipart/form-data")) { + // For multipart/form-data, we must decode things enough to get the action and nonce + // so FormHandler will validate. + // The handler must get everything else through the wrapper. No other properties will be set. + // All parameters other than nonce and action must be retrieved through the wrapper. + // Warning, parameters are NOT XSS filtered. + net.i2p.servlet.RequestWrapper requestWrapper = new net.i2p.servlet.RequestWrapper(request); + String action = requestWrapper.getParameter("action"); + if (action != null) + formhandler.setAction(action); + String nonce = requestWrapper.getParameter("nonce"); + if (nonce != null) + formhandler.setNonce(nonce); + formhandler.setRequestWrapper(requestWrapper); + } else { + // Put all the params in the map, some handlers use this instead of individual setters + // We also call all of the setters below. + formhandler.setSettings(request.getParameterMap()); %> +<% + } +%> <% diff --git a/apps/susimail/build.xml b/apps/susimail/build.xml index c4016a600e..192a90ca39 100644 --- a/apps/susimail/build.xml +++ b/apps/susimail/build.xml @@ -24,6 +24,8 @@ + +
@@ -38,6 +40,7 @@ + diff --git a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java index c5eb1236cc..ada36171b3 100644 --- a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java +++ b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java @@ -69,6 +69,7 @@ import javax.servlet.http.HttpSessionBindingListener; import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; +import net.i2p.servlet.RequestWrapper; /** * @author susi23 diff --git a/build.xml b/build.xml index 34b99b9761..16fd386910 100644 --- a/build.xml +++ b/build.xml @@ -690,11 +690,11 @@ - + - + diff --git a/history.txt b/history.txt index 2e73c43708..66513665cf 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,9 @@ +2015-03-20 zzz + * Reseed: + - Move multipart form support from susimail to jetty-i2p.jar + so console can use it + - Finish manual reseed from local file + 2015-03-19 zzz * Reseed: - Add form to manually reseed from zip or su3 URL diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index fecba78d69..a6204817e3 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 = 7; + public final static long BUILD = 8; /** for example "-test" */ public final static String EXTRA = "";