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 e24306b3bf1293add1d546040216980f5c5bde12..7a1c84b9541554b3c5a8b3733889eae1b7109eb5 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHandler.java @@ -43,13 +43,32 @@ public class ConfigReseedHandler extends FormHandler { return arr[0].trim(); } + /** @since 0.8.9 */ + private void saveString(String config, String param) { + String val = getJettyString(param); + if (val != null && val.length() > 0) + _context.router().setConfigSetting(config, val); + else + _context.router().removeConfigSetting(config); + } + + /** @since 0.8.9 */ + private void saveBoolean(String config, String param) { + boolean val = getJettyString(param) != null; + _context.router().setConfigSetting(config, Boolean.toString(val)); + } + private void saveChanges() { - String port = getJettyString("port"); - if (port != null) - _context.router().setConfigSetting(Reseeder.PROP_PROXY_PORT, port); - String host = getJettyString("host"); - if (host != null) - _context.router().setConfigSetting(Reseeder.PROP_PROXY_HOST, host); + saveString(Reseeder.PROP_PROXY_PORT, "port"); + saveString(Reseeder.PROP_PROXY_HOST, "host"); + saveString(Reseeder.PROP_PROXY_USERNAME, "username"); + saveString(Reseeder.PROP_PROXY_PASSWORD, "password"); + saveBoolean(Reseeder.PROP_PROXY_AUTH_ENABLE, "auth"); + saveString(Reseeder.PROP_SPROXY_PORT, "sport"); + saveString(Reseeder.PROP_SPROXY_HOST, "shost"); + saveString(Reseeder.PROP_SPROXY_USERNAME, "susername"); + saveString(Reseeder.PROP_SPROXY_PASSWORD, "spassword"); + saveBoolean(Reseeder.PROP_SPROXY_AUTH_ENABLE, "sauth"); String url = getJettyString("reseedURL"); if (url != null) _context.router().setConfigSetting(Reseeder.PROP_RESEED_URL, url.trim().replace("\r\n", ",").replace("\n", ",")); @@ -60,8 +79,8 @@ public class ConfigReseedHandler extends FormHandler { Boolean.toString(req)); _context.router().setConfigSetting(Reseeder.PROP_SSL_DISABLE, Boolean.toString(disabled)); - boolean proxy = getJettyString("enable") != null; - _context.router().setConfigSetting(Reseeder.PROP_PROXY_ENABLE, Boolean.toString(proxy)); + saveBoolean(Reseeder.PROP_PROXY_ENABLE, "enable"); + saveBoolean(Reseeder.PROP_SPROXY_ENABLE, "senable"); _context.router().saveConfig(); addFormNotice(_("Configuration saved successfully.")); } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java index 249f5de59bb1a981bb0e3820ee7f5868138c73a7..db0a93edfccdb50f49ed85b10a365d011327cc06 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java @@ -20,6 +20,36 @@ public class ConfigReseedHelper extends HelperBase { return _context.getProperty(Reseeder.PROP_PROXY_HOST, ""); } + /** @since 0.8.9 */ + public String getUsername() { + return _context.getProperty(Reseeder.PROP_PROXY_USERNAME, ""); + } + + /** @since 0.8.9 */ + public String getPassword() { + return _context.getProperty(Reseeder.PROP_PROXY_PASSWORD, ""); + } + + /** @since 0.8.9 */ + public String getSport() { + return _context.getProperty(Reseeder.PROP_SPROXY_PORT, ""); + } + + /** @since 0.8.9 */ + public String getShost() { + return _context.getProperty(Reseeder.PROP_SPROXY_HOST, ""); + } + + /** @since 0.8.9 */ + public String getSusername() { + return _context.getProperty(Reseeder.PROP_SPROXY_USERNAME, ""); + } + + /** @since 0.8.9 */ + public String getSpassword() { + return _context.getProperty(Reseeder.PROP_SPROXY_PASSWORD, ""); + } + public String modeChecked(int mode) { boolean required = _context.getBooleanProperty(Reseeder.PROP_SSL_REQUIRED); boolean disabled = _context.getBooleanPropertyDefaultTrue(Reseeder.PROP_SSL_DISABLE); @@ -31,7 +61,26 @@ public class ConfigReseedHelper extends HelperBase { } public String getEnable() { - boolean enabled = _context.getBooleanProperty(Reseeder.PROP_PROXY_ENABLE); + return checked(Reseeder.PROP_PROXY_ENABLE); + } + + /** @since 0.8.9 */ + public String getAuth() { + return checked(Reseeder.PROP_PROXY_AUTH_ENABLE); + } + + public String getSenable() { + return checked(Reseeder.PROP_SPROXY_ENABLE); + } + + /** @since 0.8.9 */ + public String getSauth() { + return checked(Reseeder.PROP_SPROXY_AUTH_ENABLE); + } + + /** @since 0.8.9 */ + private String checked(String prop) { + boolean enabled = _context.getBooleanProperty(prop); if (enabled) return "checked=\"true\""; return ""; diff --git a/apps/routerconsole/jsp/configreseed.jsp b/apps/routerconsole/jsp/configreseed.jsp index 87707444a25861655ff980cda45e9184efbee155..6c94b78a22c430436b26f7c293b1e0a3008b2479 100644 --- a/apps/routerconsole/jsp/configreseed.jsp +++ b/apps/routerconsole/jsp/configreseed.jsp @@ -33,21 +33,46 @@ </p> <div class="wideload"> <table border="0" cellspacing="5"> -<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URL Selection")%></b></td> +<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URL Selection")%>:</b></td> <td><input type="radio" class="optbox" name="mode" value="0" <%=reseedHelper.modeChecked(0) %> > -<%=intl._("Try SSL first then non-SSL")%> +<b><%=intl._("Try SSL first then non-SSL")%></b><br> <input type="radio" class="optbox" name="mode" value="1" <%=reseedHelper.modeChecked(1) %> > -<%=intl._("Use SSL only")%> +<b><%=intl._("Use SSL only")%></b><br> <input type="radio" class="optbox" name="mode" value="2" <%=reseedHelper.modeChecked(2) %> > -<%=intl._("Use non-SSL only")%></td></tr> -<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URLs")%></b></td> +<b><%=intl._("Use non-SSL only")%></b></td></tr> +<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URLs")%>:</b></td> <td><textarea name="reseedURL" wrap="off" spellcheck="false"><jsp:getProperty name="reseedHelper" property="reseedURL" /></textarea></td></tr> -<tr><td class="mediumtags" align="right"><b><%=intl._("Enable HTTP proxy (not used for SSL)")%></b></td> + +<tr><td class="mediumtags" align="right"><b><%=intl._("Enable HTTP Proxy?")%></b></td> <td><input type="checkbox" class="optbox" name="enable" value="true" <jsp:getProperty name="reseedHelper" property="enable" /> ></td></tr> <tr><td class="mediumtags" align="right"><b><%=intl._("HTTP Proxy Host")%>:</b></td> <td><input name="host" type="text" value="<jsp:getProperty name="reseedHelper" property="host" />" ></td></tr> <tr><td class="mediumtags" align="right"><b><%=intl._("HTTP Proxy Port")%>:</b></td> -<td><input name="port" type="text" value="<jsp:getProperty name="reseedHelper" property="port" />" ></td></tr> +<td><input name="port" type="text" size="5" maxlength="5" value="<jsp:getProperty name="reseedHelper" property="port" />" ></td></tr> + +<tr><td class="mediumtags" align="right"><b><%=intl._("Use HTTP Proxy Authorization?")%></b></td> +<td><input type="checkbox" class="optbox" name="auth" value="true" <jsp:getProperty name="reseedHelper" property="auth" /> ></td></tr> +<tr><td class="mediumtags" align="right"><b><%=intl._("HTTP Proxy Username")%>:</b></td> +<td><input name="username" type="text" value="<jsp:getProperty name="reseedHelper" property="username" />" ></td></tr> +<tr><td class="mediumtags" align="right"><b><%=intl._("HTTP Proxy Password")%>:</b></td> +<td><input name="password" type="password" value="<jsp:getProperty name="reseedHelper" property="password" />" ></td></tr> + +<!-- TODO Need SSLEepGet support +<tr><td class="mediumtags" align="right"><b><%=intl._("Enable HTTPS Proxy?")%></b></td> +<td><input type="checkbox" class="optbox" name="senable" value="true" <jsp:getProperty name="reseedHelper" property="senable" /> ></td></tr> +<tr><td class="mediumtags" align="right"><b><%=intl._("HTTPS Proxy Host")%>:</b></td> +<td><input name="shost" type="text" value="<jsp:getProperty name="reseedHelper" property="shost" />" ></td></tr> +<tr><td class="mediumtags" align="right"><b><%=intl._("HTTPS Proxy Port")%>:</b></td> +<td><input name="sport" type="text" size="5" maxlength="5" value="<jsp:getProperty name="reseedHelper" property="sport" />" ></td></tr> + +<tr><td class="mediumtags" align="right"><b><%=intl._("Use HTTPS Proxy Authorization?")%></b></td> +<td><input type="checkbox" class="optbox" name="sauth" value="true" <jsp:getProperty name="reseedHelper" property="sauth" /> ></td></tr> +<tr><td class="mediumtags" align="right"><b><%=intl._("HTTPS Proxy Username")%>:</b></td> +<td><input name="susername" type="text" value="<jsp:getProperty name="reseedHelper" property="susername" />" ></td></tr> +<tr><td class="mediumtags" align="right"><b><%=intl._("HTTPS Proxy Password")%>:</b></td> +<td><input name="spassword" type="password" value="<jsp:getProperty name="reseedHelper" property="spassword" />" ></td></tr> +--> + </table></div> <hr><div class="formaction"> <input type="submit" name="foo" value="<%=intl._("Cancel")%>" /> diff --git a/core/java/src/net/i2p/util/EepGet.java b/core/java/src/net/i2p/util/EepGet.java index 27c0fd2ad3745cedcefac5dd7b0d55dcbfa37541..c5d3861aef3bd566c28aa5beca96c05a5d872fc3 100644 --- a/core/java/src/net/i2p/util/EepGet.java +++ b/core/java/src/net/i2p/util/EepGet.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.StringTokenizer; import net.i2p.I2PAppContext; +import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.util.InternalSocket; @@ -142,6 +143,9 @@ public class EepGet { String etag = null; String saveAs = null; String url = null; + List<String> extra = null; + String username = null; + String password = null; try { for (int i = 0; i < args.length; i++) { if (args[i].equals("-p")) { @@ -162,9 +166,16 @@ public class EepGet { saveAs = args[i+1]; i++; } else if (args[i].equals("-m")) { - markSize = Integer.parseInt(args[i+1]); - lineLen = Integer.parseInt(args[i+2]); - i += 2; + markSize = Integer.parseInt(args[++i]); + lineLen = Integer.parseInt(args[++i]); + } else if (args[i].equals("-h")) { + if (extra == null) + extra = new ArrayList(2); + extra.add(args[++i]); + extra.add(args[++i]); + } else if (args[i].equals("-u")) { + username = args[++i]; + password = args[++i]; } else if (args[i].startsWith("-")) { usage(); return; @@ -186,6 +197,13 @@ public class EepGet { saveAs = suggestName(url); EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true, proxyHost, proxyPort, numRetries, saveAs, url, true, etag); + if (extra != null) { + for (int i = 0; i < extra.size(); i += 2) { + get.addHeader(extra.get(i), extra.get(i + 1)); + } + } + if (username != null && password != null) + get.addAuthorization(username, password); get.addStatusListener(get.new CLIStatusListener(markSize, lineLen)); get.fetch(CONNECT_TIMEOUT, -1, inactivityTimeout); } @@ -221,7 +239,9 @@ public class EepGet { } private static void usage() { - System.err.println("EepGet [-p 127.0.0.1:4444] [-n #retries] [-o outputFile] [-m markSize lineLen] [-t timeout] url"); + System.err.println("EepGet [-p 127.0.0.1:4444] [-n #retries] [-o outputFile] " + + "[-m markSize lineLen] [-t timeout] [-h headerKey headerValue] " + + "[-u username password] url"); } public static interface StatusListener { @@ -1094,4 +1114,17 @@ public class EepGet { _extraHeaders = new ArrayList(); _extraHeaders.add(name + ": " + value); } + + /** + * Add basic authorization header for the proxy. + * Only added if the request is going through a proxy. + * Must be called before fetch(). + * + * @since 0.8.9 + */ + public void addAuthorization(String userName, String password) { + if (_shouldProxy) + addHeader("Proxy-Authorization", + "Basic " + Base64.encode((userName + ':' + password).getBytes(), true)); // true = use standard alphabet + } } diff --git a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java index 75dcff2c119442732ce8961442bc0558a674dfd9..39c025bdbd835a15736445a70b66a610f0ae5a28 100644 --- a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java +++ b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java @@ -60,7 +60,7 @@ public class Reseeder { "http://c.netdb.i2p2.de/," + "http://reseed.i2p-projekt.de/," + "http://forum.i2p2.de/netdb/," + - "http://www.i2pbote.net/netDb/," + + /* "http://www.i2pbote.net/netDb/," + NO DATA */ "http://r31453.ovh.net/static_media/files/netDb/," + "http://cowpuncher.drollette.com/netdb/"; @@ -69,7 +69,7 @@ public class Reseeder { /* "https://a.netdb.i2p2.de/," + bad cert */ /* "https://c.netdb.i2p2.de/," + no data */ "https://forum.i2p2.de/netdb/," + - "https://www.i2pbote.net/netDb/," + + /* "https://www.i2pbote.net/netDb/," + NO DATA */ "https://reseed.i2p-projekt.de/," + "https://r31453.ovh.net/static_media/files/netDb/," + "https://cowpuncher.drollette.com/netdb/"; @@ -89,6 +89,16 @@ public class Reseeder { public static final String PROP_SSL_REQUIRED = "router.reseedSSLRequired"; /** @since 0.8.3 */ public static final String PROP_RESEED_URL = "i2p.reseedURL"; + /** all these @since 0.8.9 */ + public static final String PROP_PROXY_USERNAME = "router.reseedProxy.username"; + public static final String PROP_PROXY_PASSWORD = "router.reseedProxy.password"; + public static final String PROP_PROXY_AUTH_ENABLE = "router.reseedProxy.authEnable"; + public static final String PROP_SPROXY_HOST = "router.reseedSSLProxyHost"; + public static final String PROP_SPROXY_PORT = "router.reseedSSLProxyPort"; + public static final String PROP_SPROXY_ENABLE = "router.reseedSSLProxyEnable"; + public static final String PROP_SPROXY_USERNAME = "router.reseedSSLProxy.username"; + public static final String PROP_SPROXY_PASSWORD = "router.reseedSSLProxy.password"; + public static final String PROP_SPROXY_AUTH_ENABLE = "router.reseedSSLProxy.authEnable"; public Reseeder(RouterContext ctx) { _context = ctx; @@ -393,6 +403,7 @@ public class Reseeder { boolean ssl = url.toString().startsWith("https"); if (ssl) { SSLEepGet sslget; + // TODO SSL PROXY if (_sslState == null) { sslget = new SSLEepGet(I2PAppContext.getGlobalContext(), baos, url.toString()); // save state for next time @@ -401,11 +412,19 @@ public class Reseeder { sslget = new SSLEepGet(I2PAppContext.getGlobalContext(), baos, url.toString(), _sslState); } get = sslget; + // TODO SSL PROXY AUTH } else { // Do a (probably) non-proxied eepget into our ByteArrayOutputStream with 0 retries boolean shouldProxy = _proxyHost != null && _proxyHost.length() > 0 && _proxyPort > 0; get = new EepGet(I2PAppContext.getGlobalContext(), shouldProxy, _proxyHost, _proxyPort, 0, 0, MAX_RESEED_RESPONSE_SIZE, null, baos, url.toString(), false, null, null); + if (shouldProxy && _context.getBooleanProperty(PROP_PROXY_AUTH_ENABLE)) { + String user = _context.getProperty(PROP_PROXY_USERNAME); + String pass = _context.getProperty(PROP_PROXY_PASSWORD); + if (user != null && user.length() > 0 && + pass != null && pass.length() > 0) + get.addAuthorization(user, pass); + } } get.addStatusListener(ReseedRunner.this); if (get.fetch())