forked from I2P_Developers/i2p.i2p
merge of '4d8cced5819f256dd03cd1a845bcb08fe8de9319'
and '76cdc242b9b68e5fef39dfe67cf27baf29872f2f'
This commit is contained in:
@@ -202,7 +202,6 @@
|
||||
<fileset dir="build/obj" includes="**/standalone/*.class" />
|
||||
<zipfileset src="build/i2psnark.jar" />
|
||||
<zipfileset src="../../../core/java/build/i2p.jar" />
|
||||
<zipfileset src="../../jetty/jettylib/commons-logging.jar" />
|
||||
<!-- without this we get a warning about 'no JSP support' but that's it
|
||||
<zipfileset src="../../jetty/jettylib/jasper-runtime.jar" />
|
||||
-->
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
|
||||
destdir="./build/obj"
|
||||
includeAntRuntime="false"
|
||||
classpath="../../../core/java/build/i2p.jar:build/i2ptunnel.jar:../../jetty/jettylib/jetty-i2p.jar:../../jetty/jettylib/jetty-xml.jar" >
|
||||
classpath="../../../core/java/build/i2p.jar:build/i2ptunnel.jar:../../jetty/jettylib/jetty-i2p.jar:../../jetty/jettylib/jetty-util.jar:../../jetty/jettylib/jetty-xml.jar" >
|
||||
<compilerarg line="${javac.compilerargs}" />
|
||||
</javac>
|
||||
</target>
|
||||
@@ -318,7 +318,6 @@
|
||||
<pathelement location="../../jetty/jettylib/tomcat-util-scan.jar" />
|
||||
|
||||
<pathelement location="../../jetty/jettylib/jasper-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
|
||||
<pathelement location="${ant.home}/lib/ant.jar" />
|
||||
@@ -353,8 +352,8 @@
|
||||
<pathelement location="../../jetty/jettylib/tomcat-util.jar" />
|
||||
<pathelement location="../../jetty/jettylib/tomcat-util-scan.jar" />
|
||||
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
|
||||
<pathelement location="build/i2ptunnel.jar" />
|
||||
<pathelement location="build/temp-beans.jar" />
|
||||
<pathelement location="../../../core/java/build/i2p.jar" />
|
||||
|
||||
@@ -774,7 +774,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
||||
"<a href=\"" + conflictURL + "\">").getBytes("UTF-8"));
|
||||
out.write(_t("Conflicting address helper destination").getBytes("UTF-8"));
|
||||
out.write(("</a></th></tr>\n").getBytes("UTF-8"));
|
||||
if (_context.portMapper().getPort(PortMapper.SVC_IMAGEGEN) > 0) {
|
||||
if (_context.portMapper().isRegistered(PortMapper.SVC_IMAGEGEN)) {
|
||||
out.write(("<tr><td align=\"center\">" +
|
||||
"<a href=\"" + trustedURL + "\">" +
|
||||
"<img src=\"" +
|
||||
|
||||
@@ -544,8 +544,8 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
|
||||
char[] buf = new char[512];
|
||||
StringBuilder out = new StringBuilder(2048);
|
||||
try {
|
||||
boolean hasSusiDNS = ctx.portMapper().getPort(PortMapper.SVC_SUSIDNS) > 0;
|
||||
boolean hasI2PTunnel = ctx.portMapper().getPort(PortMapper.SVC_I2PTUNNEL) > 0;
|
||||
boolean hasSusiDNS = ctx.portMapper().isRegistered(PortMapper.SVC_SUSIDNS);
|
||||
boolean hasI2PTunnel = ctx.portMapper().isRegistered(PortMapper.SVC_I2PTUNNEL);
|
||||
if (hasSusiDNS && hasI2PTunnel) {
|
||||
reader = new TranslateReader(ctx, BUNDLE_NAME, new FileInputStream(file));
|
||||
} else {
|
||||
@@ -821,11 +821,12 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
|
||||
private static String getFooter() {
|
||||
// The css is hiding this div for now, but we'll keep it here anyway
|
||||
// Tag the strings below for translation if we unhide it.
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
buf.append("<div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ")
|
||||
.append(new Date().toString())
|
||||
.append("</i></div>\n</body>\n</html>\n");
|
||||
return buf.toString();
|
||||
//StringBuilder buf = new StringBuilder(128);
|
||||
//buf.append("<div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ")
|
||||
// .append(new Date().toString())
|
||||
// .append("</i></div>\n</body>\n</html>\n");
|
||||
//return buf.toString();
|
||||
return "</body>\n</html>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,8 +45,8 @@ public class TunnelControllerGroup implements ClientApp {
|
||||
|
||||
private final List<TunnelController> _controllers;
|
||||
private final ReadWriteLock _controllersLock;
|
||||
// locking: this
|
||||
private boolean _controllersLoaded;
|
||||
private final Object _controllersLoadedLock = new Object();
|
||||
private final String _configFile;
|
||||
|
||||
private static final String REGISTERED_NAME = "i2ptunnel";
|
||||
@@ -155,7 +155,7 @@ public class TunnelControllerGroup implements ClientApp {
|
||||
} catch (IllegalArgumentException iae) {
|
||||
if (DEFAULT_CONFIG_FILE.equals(_configFile) && !_context.isRouterContext()) {
|
||||
// for i2ptunnel command line
|
||||
synchronized (_controllersLoadedLock) {
|
||||
synchronized (this) {
|
||||
_controllersLoaded = true;
|
||||
}
|
||||
_log.logAlways(Log.WARN, "Not in router context and no preconfigured tunnels");
|
||||
@@ -263,10 +263,8 @@ public class TunnelControllerGroup implements ClientApp {
|
||||
* @throws IllegalArgumentException if unable to load from file
|
||||
*/
|
||||
public synchronized void loadControllers(String configFile) {
|
||||
synchronized (_controllersLoadedLock) {
|
||||
if (_controllersLoaded)
|
||||
return;
|
||||
}
|
||||
if (_controllersLoaded)
|
||||
return;
|
||||
|
||||
Properties cfg = loadConfig(configFile);
|
||||
int i = 0;
|
||||
@@ -284,9 +282,7 @@ public class TunnelControllerGroup implements ClientApp {
|
||||
_controllersLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
synchronized (_controllersLoadedLock) {
|
||||
_controllersLoaded = true;
|
||||
}
|
||||
_controllersLoaded = true;
|
||||
if (i > 0) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(i + " controllers loaded from " + configFile);
|
||||
@@ -346,10 +342,8 @@ public class TunnelControllerGroup implements ClientApp {
|
||||
*
|
||||
*/
|
||||
public synchronized void unloadControllers() {
|
||||
synchronized (_controllersLoadedLock) {
|
||||
if (!_controllersLoaded)
|
||||
return;
|
||||
}
|
||||
if (!_controllersLoaded)
|
||||
return;
|
||||
|
||||
_controllersLock.writeLock().lock();
|
||||
try {
|
||||
@@ -359,9 +353,7 @@ public class TunnelControllerGroup implements ClientApp {
|
||||
_controllersLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
synchronized (_controllersLoadedLock) {
|
||||
_controllersLoaded = false;
|
||||
}
|
||||
_controllersLoaded = false;
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("All controllers stopped and unloaded");
|
||||
}
|
||||
@@ -577,7 +569,7 @@ public class TunnelControllerGroup implements ClientApp {
|
||||
* @throws IllegalArgumentException if unable to load config from file
|
||||
*/
|
||||
public List<TunnelController> getControllers() {
|
||||
synchronized (_controllersLoadedLock) {
|
||||
synchronized (this) {
|
||||
if (!_controllersLoaded)
|
||||
loadControllers(_configFile);
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ public abstract class LocalHTTPServer {
|
||||
"<div class=logo>\n" +
|
||||
"<a href=\"" + conURL + "\" title=\"" + _t("Router Console") + "\"><img src=\"http://proxy.i2p/themes/console/images/i2plogo.png\" alt=\"I2P Router Console\" border=\"0\"></a><hr>\n" +
|
||||
"<a href=\"" + conURL + "config\">" + _t("Configuration") + "</a> <a href=\"" + conURL + "help.jsp\">" + _t("Help") + "</a>").getBytes("UTF-8"));
|
||||
if (pm.getPort(PortMapper.SVC_SUSIDNS) > 0)
|
||||
if (pm.isRegistered(PortMapper.SVC_SUSIDNS))
|
||||
out.write((" <a href=\"" + conURL + "susidns/index\">" + _t("Addressbook") + "</a>\n").getBytes("UTF-8"));
|
||||
out.write(("</div>" +
|
||||
"<div class=warning id=warning>\n" +
|
||||
|
||||
@@ -134,8 +134,11 @@ public class IndexBean {
|
||||
}
|
||||
}
|
||||
|
||||
/** do we know this nonce? @since 0.8.1 */
|
||||
private static boolean haveNonce(String nonce) {
|
||||
/**
|
||||
* do we know this nonce?
|
||||
* @since 0.8.1 public since 0.9.35
|
||||
*/
|
||||
public static boolean haveNonce(String nonce) {
|
||||
synchronized (_nonces) {
|
||||
return _nonces.contains(nonce);
|
||||
}
|
||||
|
||||
60
apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/SSLHelper.java
Normal file
60
apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/SSLHelper.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package net.i2p.i2ptunnel.web;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Helper class for ssl.jsp
|
||||
*
|
||||
* @since 0.9.35
|
||||
*/
|
||||
public class SSLHelper {
|
||||
|
||||
/**
|
||||
* Adapted from LoadClientAppsJob
|
||||
* @return param args non-null
|
||||
* @return non-null
|
||||
*/
|
||||
public static List<String> parseArgs(String args) {
|
||||
List<String> argList = new ArrayList<String>(4);
|
||||
StringBuilder buf = new StringBuilder(32);
|
||||
boolean isQuoted = false;
|
||||
for (int j = 0; j < args.length(); j++) {
|
||||
char c = args.charAt(j);
|
||||
switch (c) {
|
||||
case '\'':
|
||||
case '"':
|
||||
if (isQuoted) {
|
||||
String str = buf.toString().trim();
|
||||
if (str.length() > 0)
|
||||
argList.add(str);
|
||||
buf.setLength(0);
|
||||
}
|
||||
isQuoted = !isQuoted;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
// whitespace - if we're in a quoted section, keep this as part of the quote,
|
||||
// otherwise use it as a delim
|
||||
if (isQuoted) {
|
||||
buf.append(c);
|
||||
} else {
|
||||
String str = buf.toString().trim();
|
||||
if (str.length() > 0)
|
||||
argList.add(str);
|
||||
buf.setLength(0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
buf.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
String str = buf.toString().trim();
|
||||
if (str.length() > 0)
|
||||
argList.add(str);
|
||||
}
|
||||
return argList;
|
||||
}
|
||||
}
|
||||
578
apps/i2ptunnel/jsp/ssl.jsp
Normal file
578
apps/i2ptunnel/jsp/ssl.jsp
Normal file
@@ -0,0 +1,578 @@
|
||||
<%
|
||||
// NOTE: Do the header carefully so there is no whitespace before the <?xml... line
|
||||
|
||||
response.setHeader("X-Frame-Options", "SAMEORIGIN");
|
||||
response.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'");
|
||||
response.setHeader("X-XSS-Protection", "1; mode=block");
|
||||
response.setHeader("X-Content-Type-Options", "nosniff");
|
||||
response.setHeader("Referrer-Policy", "no-referrer");
|
||||
response.setHeader("Accept-Ranges", "none");
|
||||
|
||||
%><%@page pageEncoding="UTF-8"
|
||||
%><%@page contentType="text/html" import="java.io.File,java.io.IOException,net.i2p.crypto.KeyStoreUtil,net.i2p.data.DataHelper,net.i2p.jetty.JettyXmlConfigurationParser"
|
||||
%><%@page
|
||||
%><?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<%
|
||||
/* right now using EditBean instead of IndexBean for getSpoofedHost() */
|
||||
/* but might want to POST to it anyway ??? */
|
||||
%>
|
||||
<jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
|
||||
<jsp:useBean class="net.i2p.i2ptunnel.ui.Messages" id="intl" scope="request" />
|
||||
<%
|
||||
String tun = request.getParameter("tunnel");
|
||||
int curTunnel = -1;
|
||||
if (tun != null) {
|
||||
try {
|
||||
curTunnel = Integer.parseInt(tun);
|
||||
} catch (NumberFormatException nfe) {
|
||||
curTunnel = -1;
|
||||
}
|
||||
}
|
||||
%>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title><%=intl._t("Hidden Services Manager")%> - <%=intl._t("SSL Helper")%></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<link href="/themes/console/images/favicon.ico" type="image/x-icon" rel="shortcut icon" />
|
||||
<% if (editBean.allowCSS()) {
|
||||
%><link rel="icon" href="<%=editBean.getTheme()%>images/favicon.ico" />
|
||||
<link href="<%=editBean.getTheme()%>i2ptunnel.css?<%=net.i2p.CoreVersion.VERSION%>" rel="stylesheet" type="text/css" />
|
||||
<% }
|
||||
%>
|
||||
<style type='text/css'>
|
||||
input.default { width: 1px; height: 1px; visibility: hidden; }
|
||||
</style>
|
||||
</head>
|
||||
<body id="tunnelSSL">
|
||||
<%
|
||||
|
||||
net.i2p.I2PAppContext ctx = net.i2p.I2PAppContext.getGlobalContext();
|
||||
if (!ctx.isRouterContext()) {
|
||||
%>Unsupported in app context<%
|
||||
} else if (editBean.isInitialized()) {
|
||||
|
||||
%>
|
||||
<div class="panel" id="ssl">
|
||||
<%
|
||||
String tunnelTypeName;
|
||||
String tunnelType;
|
||||
boolean valid = false;
|
||||
if (curTunnel >= 0) {
|
||||
tunnelTypeName = editBean.getTunnelType(curTunnel);
|
||||
tunnelType = editBean.getInternalType(curTunnel);
|
||||
%><h2><%=intl._t("SSL Wizard")%> (<%=editBean.getTunnelName(curTunnel)%>)</h2><%
|
||||
} else {
|
||||
tunnelTypeName = "new";
|
||||
tunnelType = "new";
|
||||
%><h2>Fail</h2><p>Tunnel not found</p><%
|
||||
}
|
||||
|
||||
// set a bunch of variables for the current configuration
|
||||
String b64 = editBean.getDestinationBase64(curTunnel);
|
||||
String b32 = editBean.getDestHashBase32(curTunnel);
|
||||
// todo
|
||||
String altb32 = editBean.getAltDestHashBase32(curTunnel);
|
||||
String name = editBean.getSpoofedHost(curTunnel);
|
||||
String targetHost = editBean.getTargetHost(curTunnel);
|
||||
if (targetHost != null && targetHost.indexOf(':') >= 0)
|
||||
targetHost = '[' + targetHost + ']';
|
||||
String targetPort = editBean.getTargetPort(curTunnel);
|
||||
int intPort = 0;
|
||||
try {
|
||||
intPort = Integer.parseInt(targetPort);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
String clientTgt = targetHost + ':' + targetPort;
|
||||
boolean sslToTarget = editBean.isSSLEnabled(curTunnel);
|
||||
String targetLink = clientTgt;
|
||||
boolean shouldLinkify = true;
|
||||
if (shouldLinkify) {
|
||||
String url = "://" + clientTgt + "\">" + clientTgt + "</a>";
|
||||
if (sslToTarget)
|
||||
targetLink = "<a href=\"https" + url;
|
||||
else
|
||||
targetLink = "<a href=\"http" + url;
|
||||
}
|
||||
net.i2p.util.PortMapper pm = ctx.portMapper();
|
||||
int jettyPort = pm.getPort(net.i2p.util.PortMapper.SVC_EEPSITE);
|
||||
int jettySSLPort = pm.getPort(net.i2p.util.PortMapper.SVC_HTTPS_EEPSITE);
|
||||
|
||||
if (name == null || name.equals(""))
|
||||
name = editBean.getTunnelName(curTunnel);
|
||||
if (!"new".equals(tunnelType)) {
|
||||
// POST handling
|
||||
String action = request.getParameter("action");
|
||||
if (action != null) {
|
||||
String nonce = request.getParameter("nonce");
|
||||
String newpw = request.getParameter("nofilter_keyPassword");
|
||||
String kspw = request.getParameter("nofilter_obfKeyStorePassword");
|
||||
String appNum = request.getParameter("clientAppNumber");
|
||||
String ksPath = request.getParameter("nofilter_ksPath");
|
||||
String jettySSLConfigPath = request.getParameter("nofilter_jettySSLFile");
|
||||
if (newpw != null) {
|
||||
newpw = newpw.trim();
|
||||
if (newpw.length() <= 0)
|
||||
newpw = null;
|
||||
}
|
||||
if (kspw != null) {
|
||||
kspw = JettyXmlConfigurationParser.deobfuscate(kspw);
|
||||
} else {
|
||||
kspw = net.i2p.crypto.KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD;
|
||||
}
|
||||
if (!editBean.haveNonce(nonce)) {
|
||||
out.println(intl._t("Invalid form submission, probably because you used the 'back' or 'reload' button on your browser. Please resubmit.")
|
||||
+ ' ' +
|
||||
intl._t("If the problem persists, verify that you have cookies enabled in your browser."));
|
||||
} else if (!action.equals("Generate")) {
|
||||
out.println("Unknown form action");
|
||||
} else if (newpw == null) {
|
||||
out.println("Password required");
|
||||
} else if (appNum == null || ksPath == null || jettySSLConfigPath == null) {
|
||||
out.println("Missing parameters");
|
||||
} else if (b32.length() <= 0) {
|
||||
out.println("No destination set - start tunnel first");
|
||||
} else if (name == null || !name.endsWith(".i2p")) {
|
||||
out.println("No hostname set - go back and configure");
|
||||
} else {
|
||||
boolean ok = true;
|
||||
|
||||
// generate selfsigned cert
|
||||
java.util.Set<String> altNames = new java.util.HashSet<String>(4);
|
||||
altNames.add(b32);
|
||||
altNames.add(name);
|
||||
if (!name.startsWith("www."))
|
||||
altNames.add("www." + name);
|
||||
if (altb32 != null && altb32.length() > 0)
|
||||
altNames.add(altb32);
|
||||
File ks = new File(ksPath);
|
||||
try {
|
||||
Object[] rv = net.i2p.crypto.KeyStoreUtil.createKeysAndCRL(ks, kspw, "eepsite", name, altNames, b32,
|
||||
3652, "EC", 256, newpw);
|
||||
out.println("Created selfsigned cert");
|
||||
// save cert
|
||||
java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) rv[2];
|
||||
File f = new net.i2p.util.SecureFile(ctx.getConfigDir(), "certificates");
|
||||
if (!f.exists())
|
||||
f.mkdir();
|
||||
f = new net.i2p.util.SecureFile(f, "eepsite");
|
||||
if (!f.exists())
|
||||
f.mkdir();
|
||||
f = new net.i2p.util.SecureFile(f, b32 + ".crt");
|
||||
if (f.exists()) {
|
||||
File fb = new File(f.getParentFile(), b32 + ".crt-" + System.currentTimeMillis() + ".bkup");
|
||||
net.i2p.util.FileUtil.copy(f, fb, false, true);
|
||||
}
|
||||
ok = net.i2p.crypto.CertUtil.saveCert(cert, f);
|
||||
out.println("selfsigned cert stored");
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
ok = false;
|
||||
} catch (java.security.GeneralSecurityException gse) {
|
||||
gse.printStackTrace();
|
||||
ok = false;
|
||||
}
|
||||
|
||||
// rewrite jetty-ssl.xml
|
||||
if (ok) {
|
||||
String obf = JettyXmlConfigurationParser.obfuscate(newpw);
|
||||
String obfkspw = JettyXmlConfigurationParser.obfuscate(kspw);
|
||||
File f = new File(jettySSLConfigPath);
|
||||
try {
|
||||
org.eclipse.jetty.xml.XmlParser.Node root;
|
||||
root = JettyXmlConfigurationParser.parse(f);
|
||||
JettyXmlConfigurationParser.setValue(root, "KeyStorePassword", obfkspw);
|
||||
JettyXmlConfigurationParser.setValue(root, "KeyManagerPassword", obf);
|
||||
JettyXmlConfigurationParser.setValue(root, "TrustStorePassword", obf);
|
||||
File fb = new File(jettySSLConfigPath + ".bkup");
|
||||
if (fb.exists())
|
||||
fb = new File(jettySSLConfigPath + '-' + System.currentTimeMillis() + ".bkup");
|
||||
ok = net.i2p.util.FileUtil.copy(f, fb, false, true);
|
||||
if (ok) {
|
||||
java.io.Writer w = null;
|
||||
try {
|
||||
w = new java.io.OutputStreamWriter(new net.i2p.util.SecureFileOutputStream(f), "UTF-8");
|
||||
w.write("<!-- Modified by SSL Wizard -->\n");
|
||||
JettyXmlConfigurationParser.write(root, w);
|
||||
out.println("Jetty configuration updated");
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
ok = false;
|
||||
} finally {
|
||||
if (w != null) try { w.close(); } catch (IOException ioe2) {}
|
||||
}
|
||||
}
|
||||
} catch (org.xml.sax.SAXException saxe) {
|
||||
saxe.printStackTrace();
|
||||
out.println(DataHelper.escapeHTML(saxe.getMessage()));
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
// rewrite clients.config
|
||||
boolean isSSLEnabled = Boolean.parseBoolean(request.getParameter("isSSLEnabled"));
|
||||
if (ok && !isSSLEnabled) {
|
||||
File f = new File(ctx.getConfigDir(), "clients.config");
|
||||
java.util.Properties p = new net.i2p.util.OrderedProperties();
|
||||
try {
|
||||
DataHelper.loadProps(p, f);
|
||||
String k = "clientApp." + appNum + ".args";
|
||||
String v = p.getProperty(k);
|
||||
if (v == null) {
|
||||
ok = false;
|
||||
} else {
|
||||
v += " \"" + jettySSLConfigPath + '"';
|
||||
p.setProperty(k, v);
|
||||
DataHelper.storeProps(p, f);
|
||||
out.println("Jetty SSL enabled");
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
// stop and restart jetty
|
||||
|
||||
// stop tunnel
|
||||
if (ok) {
|
||||
|
||||
}
|
||||
|
||||
// rewrite i2ptunnel.config
|
||||
if (ok) {
|
||||
|
||||
}
|
||||
|
||||
// restart tunnel
|
||||
if (ok) {
|
||||
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
out.println(intl. _t("Configuration changes saved"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%>
|
||||
|
||||
<form method="post" action="ssl" accept-charset="UTF-8">
|
||||
<input type="hidden" name="tunnel" value="<%=curTunnel%>" />
|
||||
<input type="hidden" name="nonce" value="<%=net.i2p.i2ptunnel.web.IndexBean.getNextNonce()%>" />
|
||||
<input type="hidden" name="type" value="<%=tunnelType%>" />
|
||||
<input type="submit" class="default" name="action" value="Save changes" />
|
||||
<table>
|
||||
<tr><td colspan="4" class="infohelp"><%=intl._t("Experts only!")%> Beta!</td></tr>
|
||||
<tr><td colspan="4"><b><%=intl._t("Tunnel name")%>:</b> <%=editBean.getTunnelName(curTunnel)%></td></tr>
|
||||
<%
|
||||
if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
|
||||
%>
|
||||
<tr><td colspan="4"><b><%=intl._t("Website name")%>:</b> <%=editBean.getSpoofedHost(curTunnel)%></td></tr>
|
||||
<%
|
||||
}
|
||||
if (b64 == null || b64.length() < 516) {
|
||||
%><tr><td class="infohelp"><%=intl._t("Local destination is not available. Start the tunnel.")%></td></tr><%
|
||||
} else if (name == null || name.equals("") || name.contains(" ") || !name.endsWith(".i2p")) {
|
||||
if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
|
||||
%><tr><td class="infohelp"><%=intl._t("To enable registration verification, edit tunnel and set name (or website name) to a valid host name ending in '.i2p'")%></td></tr><%
|
||||
} else {
|
||||
%><tr><td class="infohelp"><%=intl._t("To enable registration verification, edit tunnel and set name to a valid host name ending in '.i2p'")%></td></tr><%
|
||||
}
|
||||
} else {
|
||||
valid = true;
|
||||
%>
|
||||
<tr><td colspan="4"><b><%=intl._t("Base 32")%>:</b> <%=b32%></td></tr>
|
||||
<%
|
||||
if (altb32 != null && altb32.length() > 0) {
|
||||
%>
|
||||
<tr><td><%=intl._t("Alt Base 32")%>: <%=altb32%></td></tr>
|
||||
<%
|
||||
} // altb32
|
||||
%>
|
||||
<tr><th colspan="4"><%=intl._t("Incoming I2P Port Routing")%></th></tr>
|
||||
<tr><th><%=intl._t("Route From I2P Port")%></th><th><%=intl._t("With Virtual Host")%></th><th><%=intl._t("Via SSL?")%></th><th><%=intl._t("To Server Host:Port")%></th></tr>
|
||||
<tr><td><%=intl._t("Default")%></td><td><%=name%></td><td><%=sslToTarget%></td><td><%=targetLink%></td></tr>
|
||||
<%
|
||||
// build tables for vhost and targets
|
||||
java.util.TreeSet<Integer> ports = new java.util.TreeSet<Integer>();
|
||||
java.util.Map<Integer, String> tgts = new java.util.HashMap<Integer, String>(4);
|
||||
java.util.Map<Integer, String> spoofs = new java.util.HashMap<Integer, String>(4);
|
||||
String custom = editBean.getCustomOptions(curTunnel);
|
||||
String[] opts = DataHelper.split(custom, "[, ]");
|
||||
for (int i = 0; i < opts.length; i++) {
|
||||
String opt = opts[i];
|
||||
boolean isTgt = false;
|
||||
if (opt.startsWith("targetForPort.")) {
|
||||
opt = opt.substring("targetForPort.".length());
|
||||
isTgt = true;
|
||||
} else if (opt.startsWith("spoofedHost.")) {
|
||||
opt = opt.substring("spoofedHost.".length());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
int eq = opt.indexOf('=');
|
||||
if (eq <= 0)
|
||||
continue;
|
||||
int port;
|
||||
try {
|
||||
port = Integer.parseInt(opt.substring(0, eq));
|
||||
} catch (NumberFormatException nfe) {
|
||||
continue;
|
||||
}
|
||||
String tgt = opt.substring(eq + 1);
|
||||
Integer iport = Integer.valueOf(port);
|
||||
ports.add(iport);
|
||||
if (isTgt)
|
||||
tgts.put(iport, tgt);
|
||||
else
|
||||
spoofs.put(iport, tgt);
|
||||
}
|
||||
// output vhost and targets
|
||||
for (Integer port : ports) {
|
||||
boolean ssl = sslToTarget;
|
||||
String spoof = spoofs.get(port);
|
||||
if (spoof == null)
|
||||
spoof = name;
|
||||
// can't spoof for HTTPS
|
||||
if (port.intValue() == 443) {
|
||||
spoof = b32;
|
||||
if (altb32 != null && altb32.length() > 0)
|
||||
spoof += "<br />" + altb32;
|
||||
ssl = true;
|
||||
}
|
||||
String tgt = tgts.get(port);
|
||||
if (tgt != null) {
|
||||
if (shouldLinkify) {
|
||||
String url = "://" + tgt + "\">" + tgt + "</a>";
|
||||
if (ssl)
|
||||
tgt = "<a href=\"https" + url;
|
||||
else
|
||||
tgt = "<a href=\"http" + url;
|
||||
}
|
||||
} else {
|
||||
tgt = targetLink;
|
||||
}
|
||||
%>
|
||||
<tr><td><%=port%></td><td><%=spoof%></td><td><%=ssl%></td><td><%=tgt%></td></tr>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
<tr><th colspan="4"><%=intl._t("Add Port Routing")%></th></tr>
|
||||
<tr><td>
|
||||
<input type="text" size="6" maxlength="5" id="i2pPort" name="i2pPort" title="<%=intl._t("Specify the port the server is running on")%>" value="" class="freetext port" placeholder="required" />
|
||||
</td><td>
|
||||
<input type="text" size="20" id="websiteName" name="spoofedHost" title="<%=intl._t("Website Hostname e.g. mysite.i2p")%>" value="<%=name%>" class="freetext" />
|
||||
</td><td>
|
||||
<input value="1" type="checkbox" name="useSSL" class="tickbox" />
|
||||
</td><td>
|
||||
<input type="text" size="20" name="targetHost" title="<%=intl._t("Hostname or IP address of the target server")%>" value="<%=targetHost%>" class="freetext host" /> :
|
||||
<input type="text" size="6" maxlength="5" id="targetPort" name="targetPort" title="<%=intl._t("Specify the port the server is running on")%>" value="" class="freetext port" placeholder="required" />
|
||||
</td></tr>
|
||||
<tr><th colspan="4"><%=intl._t("Jetty Clients")%></th></tr>
|
||||
<tr><th><%=intl._t("Client")%></th><th><%=intl._t("Configuration Files")%></th><th><%=intl._t("Enabled?")%></th><th><%=intl._t("SSL Enabled?")%></th><th><%=intl._t("KS Exists?")%></th><th><%=intl._t("KS Dflt PW?")%></th><th><%=intl._t("Privkey Dflt PW?")%></th></tr>
|
||||
<%
|
||||
// Now try to find the Jetty server in clients.config
|
||||
File configDir = ctx.getConfigDir();
|
||||
File clientsConfig = new File(configDir, "clients.config");
|
||||
java.util.Properties clientProps = new java.util.Properties();
|
||||
try {
|
||||
DataHelper.loadProps(clientProps, clientsConfig);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String prop = "clientApp." + i + ".main";
|
||||
String cls = clientProps.getProperty(prop);
|
||||
if (cls == null)
|
||||
break;
|
||||
if (!cls.equals("net.i2p.jetty.JettyStart"))
|
||||
continue;
|
||||
prop = "clientApp." + i + ".args";
|
||||
String clArgs = clientProps.getProperty(prop);
|
||||
if (clArgs == null)
|
||||
continue;
|
||||
prop = "clientApp." + i + ".name";
|
||||
String clName = clientProps.getProperty(prop);
|
||||
if (clName == null)
|
||||
clName = intl._t("I2P webserver (eepsite)");
|
||||
prop = "clientApp." + i + ".startOnLoad";
|
||||
String clStart = clientProps.getProperty(prop);
|
||||
boolean start = true;
|
||||
if (clStart != null)
|
||||
start = Boolean.parseBoolean(clStart);
|
||||
// sample args
|
||||
// clientApp.3.args="/home/xxx/.i2p/eepsite/jetty.xml" "/home/xxx/.i2p/eepsite/jetty-ssl.xml" "/home/xxx/.i2p/eepsite/jetty-rewrite.xml"
|
||||
boolean ssl = clArgs.contains("jetty-ssl.xml");
|
||||
|
||||
boolean jettySSLFileInArgs = false;
|
||||
boolean jettySSLFileExists = false;
|
||||
boolean jettySSLFilePWSet = false;
|
||||
File jettyFile = null, jettySSLFile = null;
|
||||
String ksPW = null, kmPW = null, tsPW = null;
|
||||
String ksPath = null, tsPath = null;
|
||||
String host = null, port = null;
|
||||
String sslHost = null, sslPort = null;
|
||||
String error = "";
|
||||
java.util.List<String> argList = net.i2p.i2ptunnel.web.SSLHelper.parseArgs(clArgs);
|
||||
for (String arg : argList) {
|
||||
if (arg.endsWith("jetty.xml")) {
|
||||
jettyFile = new File(arg);
|
||||
if (!jettyFile.isAbsolute())
|
||||
jettyFile = new File(ctx.getConfigDir(), arg);
|
||||
} else if (arg.endsWith("jetty-ssl.xml")) {
|
||||
jettySSLFile = new File(arg);
|
||||
if (!jettySSLFile.isAbsolute())
|
||||
jettySSLFile = new File(ctx.getConfigDir(), arg);
|
||||
jettySSLFileInArgs = true;
|
||||
}
|
||||
} // for arg in argList
|
||||
if (jettySSLFile == null && !argList.isEmpty()) {
|
||||
String arg = argList.get(0);
|
||||
File f = new File(arg);
|
||||
if (!f.isAbsolute())
|
||||
f = new File(ctx.getConfigDir(), arg);
|
||||
File p = f.getParentFile();
|
||||
if (p != null)
|
||||
jettySSLFile = new File(p, "jetty-ssl.xml");
|
||||
}
|
||||
boolean ksDflt = false;
|
||||
boolean kmDflt = false;
|
||||
boolean tsDflt = false;
|
||||
boolean ksExists = false;
|
||||
if (jettyFile != null && jettyFile.exists()) {
|
||||
try {
|
||||
org.eclipse.jetty.xml.XmlParser.Node root;
|
||||
root = JettyXmlConfigurationParser.parse(jettyFile);
|
||||
host = JettyXmlConfigurationParser.getValue(root, "host");
|
||||
port = JettyXmlConfigurationParser.getValue(root, "port");
|
||||
} catch (org.xml.sax.SAXException saxe) {
|
||||
saxe.printStackTrace();
|
||||
error = DataHelper.escapeHTML(saxe.getMessage());
|
||||
}
|
||||
}
|
||||
if (jettySSLFile.exists()) {
|
||||
try {
|
||||
org.eclipse.jetty.xml.XmlParser.Node root;
|
||||
root = JettyXmlConfigurationParser.parse(jettySSLFile);
|
||||
ksPW = JettyXmlConfigurationParser.getValue(root, "KeyStorePassword");
|
||||
kmPW = JettyXmlConfigurationParser.getValue(root, "KeyManagerPassword");
|
||||
tsPW = JettyXmlConfigurationParser.getValue(root, "TrustStorePassword");
|
||||
ksPath = JettyXmlConfigurationParser.getValue(root, "KeyStorePath");
|
||||
tsPath = JettyXmlConfigurationParser.getValue(root, "TrustStorePath");
|
||||
sslHost = JettyXmlConfigurationParser.getValue(root, "host");
|
||||
sslPort = JettyXmlConfigurationParser.getValue(root, "port");
|
||||
// we can't proceed unless they are there
|
||||
// tsPW may be null
|
||||
File ksFile = null;
|
||||
boolean tsIsKs = true;
|
||||
boolean ksArgs = ksPW != null && kmPW != null && ksPath != null;
|
||||
/** 2015+ installs */
|
||||
final String DEFAULT_KSPW_1 = KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD;
|
||||
final String DEFAULT_KMPW_1 = "myKeyPassword";
|
||||
/** earlier */
|
||||
final String DEFAULT_KSPW_2 = "OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4";
|
||||
final String DEFAULT_KMPW_2 = "OBF:1u2u1wml1z7s1z7a1wnl1u2g";
|
||||
if (ksArgs) {
|
||||
jettySSLFileExists = true;
|
||||
ksDflt = ksPW.equals(DEFAULT_KSPW_1) || ksPW.equals(DEFAULT_KSPW_2);
|
||||
kmDflt = kmPW.equals(DEFAULT_KMPW_1) || kmPW.equals(DEFAULT_KMPW_2);
|
||||
ksFile = new File(ksPath);
|
||||
if (!ksFile.isAbsolute())
|
||||
ksFile = new File(ctx.getConfigDir(), ksPath);
|
||||
ksExists = ksFile.exists();
|
||||
tsIsKs = tsPath == null || ksPath.equals(tsPath);
|
||||
}
|
||||
if (tsPW != null) {
|
||||
tsDflt = tsPW.equals(DEFAULT_KSPW_1) || tsPW.equals(DEFAULT_KSPW_2);
|
||||
}
|
||||
} catch (org.xml.sax.SAXException saxe) {
|
||||
saxe.printStackTrace();
|
||||
error = DataHelper.escapeHTML(saxe.getMessage());
|
||||
}
|
||||
}
|
||||
boolean canConfigure = jettySSLFileExists;
|
||||
boolean isEnabled = canConfigure && jettySSLFileInArgs;
|
||||
boolean isPWDefault = kmDflt || !ksExists;
|
||||
|
||||
// now start the output for this client
|
||||
|
||||
%>
|
||||
<tr><td><%=DataHelper.escapeHTML(clName)%></td><td>
|
||||
<%
|
||||
for (String arg : argList) {
|
||||
%><%=DataHelper.escapeHTML(arg)%><br /><%
|
||||
}
|
||||
%>
|
||||
</td><td><%=start%></td><td><%=ssl%></td><td><%=ksExists%> <%=error%></td><td><%=ksDflt%></td><td><%=kmDflt%></td></tr>
|
||||
<%
|
||||
if (!canConfigure) {
|
||||
%>
|
||||
<tr><td colspan="7">Cannot configure, no Jetty SSL configuration template exists</td></tr>
|
||||
<%
|
||||
} else {
|
||||
if (isEnabled) {
|
||||
%>
|
||||
<tr><td colspan="7">Jetty SSL is enabled</td></tr>
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
<tr><td colspan="7">Jetty SSL is not enabled</td></tr>
|
||||
<%
|
||||
} // isEnabled
|
||||
if (isPWDefault) {
|
||||
%>
|
||||
<tr><td colspan="7">Jetty SSL cert passwords are the default</td></tr>
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
<tr><td colspan="7">Jetty SSL cert passwords are not the default</td></tr>
|
||||
<%
|
||||
} // isPWDefault
|
||||
%>
|
||||
<tr><td colspan="7"><b><%=intl._t("Password")%>:</b>
|
||||
<input type="hidden" name="clientAppNumber" value="<%=i%>" />
|
||||
<input type="hidden" name="isSSLEnabled" value="<%=isEnabled%>" />
|
||||
<input type="hidden" name="nofilter_ksPath" value="<%=ksPath%>" />
|
||||
<input type="hidden" name="nofilter_jettySSLFile" value="<%=jettySSLFile%>" />
|
||||
<input type="password" name="nofilter_keyPassword" title="<%=intl._t("Set password required to access this service")%>" value="" class="freetext password" />
|
||||
<%
|
||||
if (ksPW != null) {
|
||||
if (!ksPW.startsWith("OBF:"))
|
||||
ksPW = JettyXmlConfigurationParser.obfuscate(ksPW);
|
||||
%>
|
||||
<input type="hidden" name="nofilter_obfKeyStorePassword" value="<%=ksPW%>" />
|
||||
<%
|
||||
}
|
||||
%>
|
||||
</td></tr>
|
||||
<tr><td class="buttons" colspan="7">
|
||||
<button id="controlSave" class="control" type="submit" name="action" value="Generate"><%=intl._t("Generate certificate")%></button>
|
||||
</td></tr>
|
||||
<%
|
||||
} // canConfigure
|
||||
} // for client
|
||||
} catch (IOException ioe) { ioe.printStackTrace(); }
|
||||
%>
|
||||
<tr><td colspan="4">
|
||||
<div class="displayText" tabindex="0" title="<%=intl._t("yyy")%>"></div>
|
||||
</td></tr>
|
||||
</table>
|
||||
</form>
|
||||
<%
|
||||
} // valid b64 and name
|
||||
} // !"new".equals(tunnelType)
|
||||
if (!valid && curTunnel >= 0) {
|
||||
%>
|
||||
<table>
|
||||
<tr><td><a href="edit?tunnel=<%=curTunnel%>"><%=intl._t("Go back and edit the tunnel")%></a></td></tr>
|
||||
</table>
|
||||
<%
|
||||
} // !valid
|
||||
%>
|
||||
</div>
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
<div id="notReady"><%=intl._t("Tunnels are not initialized yet, please reload in two minutes.")%></div>
|
||||
<%
|
||||
} // isInitialized()
|
||||
%>
|
||||
</body>
|
||||
</html>
|
||||
@@ -67,6 +67,11 @@
|
||||
<url-pattern>/register</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>net.i2p.i2ptunnel.jsp.ssl_jsp</servlet-name>
|
||||
<url-pattern>/ssl</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>net.i2p.servlet.ErrorServlet</servlet-name>
|
||||
<url-pattern>/error</url-pattern>
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
was set individually in wrapper.config, we rename and combine the jars as follows:
|
||||
jasper.jar : jasper-runtime.jar
|
||||
jasper-el.jar + el-api.jar : commons-el.jar
|
||||
tomcat-juli.jar : Add to commons-logging.jar
|
||||
tomcat-juli.jar : Add to jasper-runtime.jar
|
||||
empty jar : jasper-compiler.jar
|
||||
Also, take NOTICE and LICENSE out of each one, we bundle those separately.
|
||||
|
||||
@@ -340,7 +340,6 @@
|
||||
destdir="./build/obj" >
|
||||
<classpath>
|
||||
<pathelement location="../../../core/java/build/i2p.jar" />
|
||||
<pathelement location="./jettylib/commons-logging.jar" />
|
||||
<pathelement location="./jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="./jettylib/javax.servlet.jar" />
|
||||
<pathelement location="./jettylib/jetty-http.jar" />
|
||||
@@ -361,7 +360,7 @@
|
||||
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
|
||||
destdir="./build/obj"
|
||||
includeAntRuntime="false"
|
||||
classpath="../../core/java/build/i2p.jar:./jettylib/commons-logging.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar:./jettylib/jetty-http.jar:./jettylib/jetty-io.jar:./jettylib/jetty-security.jar:./jettylib/jetty-servlet.jar:./jettylib/jetty-util.jar:./jettylib/jetty-xml.jar" >
|
||||
classpath="../../core/java/build/i2p.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar:./jettylib/jetty-http.jar:./jettylib/jetty-io.jar:./jettylib/jetty-security.jar:./jettylib/jetty-servlet.jar:./jettylib/jetty-util.jar:./jettylib/jetty-xml.jar" >
|
||||
<compilerarg line="${javac.compilerargs}" />
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
package net.i2p.jetty;
|
||||
|
||||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.Writer;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.security.Password;
|
||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
import org.eclipse.jetty.xml.XmlParser.Attribute;
|
||||
import org.eclipse.jetty.xml.XmlParser.Node;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Parses a Jetty XML configuration file.
|
||||
* Copied from Jetty XmlConfiguration.java, where the parser is private.
|
||||
*
|
||||
* @since 0.9.35
|
||||
*/
|
||||
public class JettyXmlConfigurationParser
|
||||
{
|
||||
private static XmlParser initParser()
|
||||
{
|
||||
XmlParser parser = new XmlParser();
|
||||
URL config60 = Loader.getResource(XmlConfiguration.class, "org/eclipse/jetty/xml/configure_6_0.dtd");
|
||||
URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd");
|
||||
URL config90 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_9_0.dtd");
|
||||
parser.redirectEntity("configure.dtd",config90);
|
||||
parser.redirectEntity("configure_1_0.dtd",config60);
|
||||
parser.redirectEntity("configure_1_1.dtd",config60);
|
||||
parser.redirectEntity("configure_1_2.dtd",config60);
|
||||
parser.redirectEntity("configure_1_3.dtd",config60);
|
||||
parser.redirectEntity("configure_6_0.dtd",config60);
|
||||
parser.redirectEntity("configure_7_6.dtd",config76);
|
||||
parser.redirectEntity("configure_9_0.dtd",config90);
|
||||
|
||||
parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config90);
|
||||
parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config90);
|
||||
parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config90);
|
||||
|
||||
parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config90);
|
||||
parser.redirectEntity("-//Jetty//Configure//EN",config90);
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and parses the XML configuration file.
|
||||
*
|
||||
* @param f an XML configuration file
|
||||
* @throws IOException if the configuration could not be read
|
||||
* @throws SAXException if the configuration could not be parsed
|
||||
*/
|
||||
public static XmlParser.Node parse(File f) throws SAXException, IOException {
|
||||
// we don't expect to need this very often,
|
||||
// so just make a new parser every time
|
||||
return initParser().parse(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively go through the entire tree starting at node.
|
||||
* Return the value for the first node with the name set,
|
||||
* e.g. [Set name="name"]value[/Set]
|
||||
* @param name case insensitive
|
||||
*/
|
||||
public static String getValue(Node node, String name) {
|
||||
String nameLC = name.toLowerCase(Locale.US);
|
||||
for (Object o : node) {
|
||||
if (!(o instanceof Node))
|
||||
continue;
|
||||
Node n = (Node) o;
|
||||
String tag = n.getTag();
|
||||
if (tag != null && "set".equals(tag.toLowerCase(Locale.US))) {
|
||||
String aname = n.getAttribute("name");
|
||||
if (aname != null && aname.toLowerCase(Locale.US).equals(nameLC))
|
||||
return n.toString(false);
|
||||
} else {
|
||||
String rv = getValue(n, name);
|
||||
if (rv != null)
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively go through the entire tree starting at node.
|
||||
* Return the value for the first node with the name set,
|
||||
* e.g. [Set name="name"]value[/Set]
|
||||
* @param name case insensitive
|
||||
* @return success
|
||||
*/
|
||||
public static boolean setValue(Node node, String name, String value) {
|
||||
String nameLC = name.toLowerCase(Locale.US);
|
||||
for (Object o : node) {
|
||||
if (!(o instanceof Node))
|
||||
continue;
|
||||
Node n = (Node) o;
|
||||
String tag = n.getTag();
|
||||
if (tag != null && "set".equals(tag.toLowerCase(Locale.US))) {
|
||||
String aname = n.getAttribute("name");
|
||||
if (aname != null && aname.toLowerCase(Locale.US).equals(nameLC)) {
|
||||
// Node doesn't support set() or remove() but it does have clear()
|
||||
n.clear();
|
||||
// work around bug in XmlParser.Node.add(int, Object)
|
||||
// where it will AIOOBE when calling add(String) after clear() after add(String)
|
||||
// because the _lastString field isn't reset to false
|
||||
// so we need to add a non-String object and then clear again.
|
||||
n.add(Integer.valueOf(0));
|
||||
n.clear();
|
||||
n.add(value);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
boolean rv = setValue(n, name, value);
|
||||
if (rv)
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write out the XML.
|
||||
* Adapted from Node.toString().
|
||||
* That synchronized method caused classpath issues when called from the webapp.
|
||||
* Also add newlines here for readability.
|
||||
*/
|
||||
public static void write(Node node, Writer out) throws IOException {
|
||||
out.write('<');
|
||||
String tag = node.getTag();
|
||||
out.write(tag);
|
||||
|
||||
Attribute[] attrs = node.getAttributes();
|
||||
if (attrs != null) {
|
||||
for (int i = 0; i < attrs.length; i++) {
|
||||
out.write(' ');
|
||||
out.write(attrs[i].getName());
|
||||
out.write("=\"");
|
||||
out.write(attrs[i].getValue());
|
||||
out.write('"');
|
||||
}
|
||||
}
|
||||
|
||||
int size = node.size();
|
||||
if (size > 0) {
|
||||
out.write(">");
|
||||
for (int i = 0; i < size; i++) {
|
||||
Object o = node.get(i);
|
||||
if (o == null)
|
||||
continue;
|
||||
if (o instanceof Node) {
|
||||
write((Node) o, out);
|
||||
} else {
|
||||
out.write(o.toString());
|
||||
}
|
||||
}
|
||||
out.write("</");
|
||||
out.write(tag);
|
||||
out.write(">\n");
|
||||
} else {
|
||||
out.write("/>\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obfuscate a password for storage in the XML
|
||||
* @return a string starting with "OBF:"
|
||||
*/
|
||||
public static String obfuscate(String s) {
|
||||
if (s.startsWith("OBF:"))
|
||||
return s;
|
||||
return Password.obfuscate(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* De-Obfuscate a password from the XML
|
||||
* @param s a string starting with "OBF:"
|
||||
*/
|
||||
public static String deobfuscate(String s) {
|
||||
if (!s.startsWith("OBF:"))
|
||||
return s;
|
||||
return Password.deobfuscate(s);
|
||||
}
|
||||
}
|
||||
@@ -149,6 +149,15 @@ public class ErrorServlet extends HttpServlet {
|
||||
out.println("</div></body></html>");
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed if the errored page was a POST
|
||||
* @since 0.9.35
|
||||
*/
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
doGet(req, resp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for specific cases.
|
||||
|
||||
@@ -214,7 +214,7 @@ public class I2PDefaultServlet extends DefaultServlet
|
||||
|
||||
String encodedBase = hrefEncodeURI(base);
|
||||
|
||||
DateFormat dfmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.UK);
|
||||
DateFormat dfmt = new SimpleDateFormat(FORMAT, Locale.UK);
|
||||
TimeZone utc = TimeZone.getTimeZone("GMT");
|
||||
dfmt.setTimeZone(utc);
|
||||
for (int i=0 ; i< ls.length ; i++)
|
||||
|
||||
@@ -396,7 +396,6 @@
|
||||
<pathelement location="../../jetty/jettylib/tomcat-util.jar" />
|
||||
<pathelement location="../../jetty/jettylib/tomcat-util-scan.jar" />
|
||||
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
|
||||
<pathelement location="${ant.home}/lib/ant.jar" />
|
||||
@@ -435,7 +434,6 @@
|
||||
<pathelement location="../../jetty/jettylib/tomcat-util.jar" />
|
||||
<pathelement location="../../jetty/jettylib/tomcat-util-scan.jar" />
|
||||
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
|
||||
|
||||
@@ -175,7 +175,7 @@ public class ConfigUpdateHandler extends FormHandler {
|
||||
int proxyPort = proxyPort(_context);
|
||||
if (shouldProxy && proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
|
||||
proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
|
||||
_context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
|
||||
!_context.portMapper().isRegistered(PortMapper.SVC_HTTP_PROXY)) {
|
||||
addFormError(_t("HTTP client proxy tunnel must be running"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ public class PluginStarter implements Runnable {
|
||||
int proxyPort = ConfigUpdateHandler.proxyPort(ctx);
|
||||
if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
|
||||
proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
|
||||
ctx.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
|
||||
!ctx.portMapper().isRegistered(PortMapper.SVC_HTTP_PROXY)) {
|
||||
mgr.notifyComplete(null, Messages.getString("Plugin update check failed", ctx) +
|
||||
" - " +
|
||||
Messages.getString("HTTP client proxy tunnel must be running", ctx));
|
||||
|
||||
@@ -53,6 +53,8 @@ public class WebAppStarter {
|
||||
* Prior to 0.9.28, was not guaranteed to throw on failure.
|
||||
* Not for routerconsole.war, it's started in RouterConsoleRunner.
|
||||
*
|
||||
* As of 0.9.34, the appName will be registered with the PortMapper.
|
||||
*
|
||||
* @throws Exception just about anything, caller would be wise to catch Throwable
|
||||
* @since public since 0.9.33, was package private
|
||||
*/
|
||||
@@ -165,7 +167,12 @@ public class WebAppStarter {
|
||||
} catch (IllegalStateException ise) {}
|
||||
}
|
||||
|
||||
/** @since public since 0.9.33; was package private */
|
||||
/**
|
||||
* As of 0.9.34, the appName will be registered with the PortMapper,
|
||||
* and PortMapper.isRegistered() will be more efficient than this.
|
||||
*
|
||||
* @since public since 0.9.33; was package private
|
||||
*/
|
||||
public static boolean isWebAppRunning(String appName) {
|
||||
ContextHandler wac = getWebApp(appName);
|
||||
if (wac == null)
|
||||
|
||||
@@ -22,7 +22,7 @@ public class CertHelper extends HelperBase {
|
||||
private static final String CONSOLE = "console/console.local.crt";
|
||||
private static final String I2PTUNNEL_DIR = "i2ptunnel";
|
||||
private static final String SAM_DIR = "sam";
|
||||
private static final String EEPSITE = "eepsite/etc/keystore.ks";
|
||||
private static final String EEPSITE_DIR = "eepsite";
|
||||
|
||||
public String getSummary() {
|
||||
File dir = new File(_context.getConfigDir(), DIR);
|
||||
@@ -31,9 +31,9 @@ public class CertHelper extends HelperBase {
|
||||
_out.write(_t("Local SSL Certificates"));
|
||||
_out.write("</h3>\n");
|
||||
// console
|
||||
output("Console", new File(dir, CONSOLE));
|
||||
output(_t("Router Console"), new File(dir, CONSOLE));
|
||||
// I2CP
|
||||
output("I2CP", new File(dir, I2CP));
|
||||
output(_t("I2CP"), new File(dir, I2CP));
|
||||
|
||||
// i2ptunnel clients
|
||||
File tunnelDir = new File(_context.getConfigDir(), I2PTUNNEL_DIR);
|
||||
@@ -58,13 +58,28 @@ public class CertHelper extends HelperBase {
|
||||
if (tunnels != null) {
|
||||
for (int i = 0; i < tunnels.length; i++) {
|
||||
File f = tunnels[i];
|
||||
output("SAM", f);
|
||||
output(_t("SAM"), f);
|
||||
hasTunnels = true;
|
||||
}
|
||||
}
|
||||
if (!hasTunnels)
|
||||
output(_t("SAM"), null);
|
||||
|
||||
// Eepsite
|
||||
tunnelDir = new File(dir, EEPSITE_DIR);
|
||||
hasTunnels = false;
|
||||
tunnels = tunnelDir.listFiles(new FileSuffixFilter(".crt"));
|
||||
if (tunnels != null) {
|
||||
for (int i = 0; i < tunnels.length; i++) {
|
||||
File f = tunnels[i];
|
||||
String name = f.getName();
|
||||
output(_t("Website") + ' ' + name.substring(0, name.length() - 4), f);
|
||||
hasTunnels = true;
|
||||
}
|
||||
}
|
||||
if (!hasTunnels)
|
||||
output(_t("Website"), null);
|
||||
|
||||
// Family
|
||||
_out.write("<h3>");
|
||||
_out.write(_t("Local Router Family Certificate"));
|
||||
@@ -80,19 +95,6 @@ public class CertHelper extends HelperBase {
|
||||
_out.write("</p>\n");
|
||||
}
|
||||
|
||||
// Eepsite
|
||||
_out.write("<h3>");
|
||||
_out.write(_t("Website"));
|
||||
_out.write("</h3>\n");
|
||||
File ks = new File(_context.getConfigDir(), EEPSITE);
|
||||
if (ks.exists()) {
|
||||
// TODO
|
||||
} else {
|
||||
_out.write("<p>");
|
||||
_out.write(_t("none"));
|
||||
_out.write("</p>\n");
|
||||
}
|
||||
|
||||
// anything else? plugins?
|
||||
|
||||
} catch (IOException ioe) {
|
||||
|
||||
@@ -577,7 +577,7 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
boolean rv = !
|
||||
(proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
|
||||
proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
|
||||
_context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0);
|
||||
!_context.portMapper().isRegistered(PortMapper.SVC_HTTP_PROXY));
|
||||
if (!rv)
|
||||
addFormError(_t("HTTP client proxy tunnel must be running"));
|
||||
return rv;
|
||||
|
||||
@@ -208,13 +208,13 @@ public class HomeHelper extends HelperBase {
|
||||
url = app.url;
|
||||
// check for disabled webapps and other things
|
||||
if (url.equals("/dns")) {
|
||||
if (pm.getPort("susidns") <= 0)
|
||||
if (!pm.isRegistered("susidns"))
|
||||
continue;
|
||||
} else if (url.equals("/webmail")) {
|
||||
if (pm.getPort("susimail") <= 0)
|
||||
if (!pm.isRegistered("susimail"))
|
||||
continue;
|
||||
} else if (url.equals("/torrents")) {
|
||||
if (pm.getPort("i2psnark") <= 0)
|
||||
if (!pm.isRegistered("i2psnark"))
|
||||
continue;
|
||||
} else if (url.equals("/configplugins")) {
|
||||
if (!PluginStarter.pluginsEnabled(_context))
|
||||
|
||||
@@ -290,7 +290,7 @@ class NetDbRenderer {
|
||||
medianCount = rapCount / 2;
|
||||
}
|
||||
|
||||
boolean linkSusi = WebAppStarter.isWebAppRunning("susidns");
|
||||
boolean linkSusi = _context.portMapper().isRegistered("susidns");
|
||||
long now = _context.clock().now();
|
||||
buf.append("<div class=\"leasesets_container\">");
|
||||
for (LeaseSet ls : leases) {
|
||||
|
||||
@@ -214,7 +214,7 @@ class SummaryBarRenderer {
|
||||
"<hr class=\"b\"><table id=\"sb_services\"><tr><td>");
|
||||
|
||||
PortMapper pm = _context.portMapper();
|
||||
if (pm.getPort(PortMapper.SVC_SUSIMAIL) > 0) {
|
||||
if (pm.isRegistered(PortMapper.SVC_SUSIMAIL)) {
|
||||
buf.append("<a href=\"/webmail\" target=\"_top\" title=\"")
|
||||
.append(_t("Anonymous webmail client"))
|
||||
.append("\">")
|
||||
@@ -222,7 +222,7 @@ class SummaryBarRenderer {
|
||||
.append("</a>\n");
|
||||
}
|
||||
|
||||
if (pm.getPort(PortMapper.SVC_I2PSNARK) > 0) {
|
||||
if (pm.isRegistered(PortMapper.SVC_I2PSNARK)) {
|
||||
buf.append("<a href=\"/torrents\" target=\"_top\" title=\"")
|
||||
.append(_t("Built-in anonymous BitTorrent Client"))
|
||||
.append("\">")
|
||||
@@ -269,7 +269,7 @@ class SummaryBarRenderer {
|
||||
"<table id=\"sb_internals\"><tr><td>\n");
|
||||
|
||||
PortMapper pm = _context.portMapper();
|
||||
if (pm.getPort(PortMapper.SVC_SUSIDNS) > 0) {
|
||||
if (pm.isRegistered(PortMapper.SVC_SUSIDNS)) {
|
||||
buf.append("<a href=\"/dns\" target=\"_top\" title=\"")
|
||||
.append(_t("Manage your I2P hosts file here (I2P domain name resolution)"))
|
||||
.append("\">")
|
||||
@@ -291,7 +291,7 @@ class SummaryBarRenderer {
|
||||
.append(nbsp(_t("Help")))
|
||||
.append("</a>\n");
|
||||
|
||||
if (pm.getPort(PortMapper.SVC_I2PTUNNEL) > 0) {
|
||||
if (pm.isRegistered(PortMapper.SVC_I2PTUNNEL)) {
|
||||
buf.append("<a href=\"/i2ptunnelmgr\" target=\"_top\" title=\"")
|
||||
.append(_t("Local Tunnels"))
|
||||
.append("\">")
|
||||
|
||||
@@ -558,7 +558,7 @@ public class SummaryHelper extends HelperBase {
|
||||
List<Destination> clients = new ArrayList<Destination>(_context.clientManager().listClients());
|
||||
|
||||
StringBuilder buf = new StringBuilder(512);
|
||||
boolean link = WebAppStarter.isWebAppRunning("i2ptunnel");
|
||||
boolean link = _context.portMapper().isRegistered("i2ptunnel");
|
||||
buf.append("<h3>");
|
||||
if (link) {
|
||||
buf.append("<a href=\"/i2ptunnelmgr\" target=\"_top\" title=\"")
|
||||
@@ -898,7 +898,7 @@ public class SummaryHelper extends HelperBase {
|
||||
if ((avail || unsignedAvail || devSU3Avail) &&
|
||||
!NewsHelper.isUpdateInProgress() &&
|
||||
!_context.router().gracefulShutdownInProgress() &&
|
||||
_context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) > 0 && // assume using proxy for now
|
||||
_context.portMapper().isRegistered(PortMapper.SVC_HTTP_PROXY) && // assume using proxy for now
|
||||
getAction() == null &&
|
||||
getUpdateNonce() == null) {
|
||||
if (needSpace)
|
||||
|
||||
@@ -814,7 +814,7 @@ class SybilRenderer {
|
||||
buf.append("<a title=\"View extended router info\" class=\"viewfullentry\" href=\"netdb?r=")
|
||||
.append(hash.substring(0, 6)).append("\" >[").append(_t("Full entry")).append("]</a></th><th>");
|
||||
}
|
||||
if (_context.portMapper().getPort("imagegen") > 0)
|
||||
if (_context.portMapper().isRegistered("imagegen"))
|
||||
buf.append("<img src=\"/imagegen/id?s=32&c=" + hash.replace("=", "%3d") + "\" height=\"32\" width=\"32\"> ");
|
||||
buf.append("</th></tr>\n<tr><td class=\"sybilinfo_params\" colspan=\"3\"><div class=\"sybilinfo_container\">");
|
||||
if (us != null) {
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
<pathelement location="lib/jstl.jar" />
|
||||
<pathelement location="lib/standard.jar" />
|
||||
<pathelement location="${lib}/jasper-runtime.jar" />
|
||||
<pathelement location="${lib}/commons-logging.jar" />
|
||||
<pathelement location="${lib}/jetty-util.jar" />
|
||||
<pathelement location="${ant.home}/lib/ant.jar" />
|
||||
<pathelement location="../../../core/java/build/i2p.jar" />
|
||||
|
||||
@@ -438,6 +438,6 @@ public class NamingServiceBean extends AddressbookBean
|
||||
* @since 0.9.34
|
||||
*/
|
||||
public boolean haveImagegen() {
|
||||
return _context.portMapper().getPort("imagegen") > 0;
|
||||
return _context.portMapper().isRegistered("imagegen");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ public class SubscriptionsBean extends BaseBean
|
||||
// config reload and fetch.
|
||||
*******/
|
||||
if (content != null && content.length() > 2 &&
|
||||
_context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) > 0) {
|
||||
_context.portMapper().isRegistered(PortMapper.SVC_HTTP_PROXY)) {
|
||||
message = _t("Subscriptions saved, updating addressbook from subscription sources now.");
|
||||
// + "<img height=\"1\" width=\"1\" alt=\"\" " +
|
||||
// "src=\"/addressbook/?wakeup=1&nonce=" + nonce + "\">";
|
||||
|
||||
@@ -628,7 +628,11 @@ public class WebMail extends HttpServlet
|
||||
type.equals("application/x-tar") || type.equals("application/x-bzip2") ||
|
||||
type.equals("application/pdf") || type.equals("application/x-bittorrent") ||
|
||||
type.equals("application/pgp-encrypted") ||
|
||||
type.equals("application/pgp-signature"))) {
|
||||
type.equals("application/pgp-signature") ||
|
||||
(type.equals("application/octet-stream") &&
|
||||
((mailPart.filename != null && mailPart.filename.endsWith(".asc")) ||
|
||||
(mailPart.name != null && mailPart.name.endsWith(".asc"))))
|
||||
)) {
|
||||
out.println( "<a href=\"" + myself + '?' + RAW_ATTACHMENT + '=' +
|
||||
mailPart.getID() +
|
||||
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) + "\">" +
|
||||
|
||||
@@ -588,7 +588,7 @@
|
||||
<jar destfile="./build/launchi2p.jar">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="net.i2p.router.RouterLaunch" />
|
||||
<attribute name="Class-Path" value="lib/i2p.jar lib/router.jar lib/jbigi.jar lib/BOB.jar lib/sam.jar lib/mstreaming.jar lib/streaming.jar lib/routerconsole.jar lib/i2ptunnel.jar lib/org.mortbay.jetty.jar lib/javax.servlet.jar lib/jasper-runtime.jar lib/commons-logging.jar lib/commons-el.jar lib/wrapper.jar lib/systray.jar lib/desktopgui.jar lib/i2psnark.jar lib/jrobin.jar lib/jstl.jar lib/standard.jar lib/jetty-continuation.jar lib/jetty-deploy.jar lib/jetty-http.jar lib/jetty-i2p.jar lib/jetty-io.jar lib/jetty-rewrite-handler.jar lib/jetty-security.jar lib/jetty-servlet.jar lib/jetty-servlets.jar lib/jetty-start.jar lib/jetty-util.jar lib/jetty-webapp.jar lib/jetty-xml.jar" />
|
||||
<attribute name="Class-Path" value="lib/i2p.jar lib/router.jar lib/jbigi.jar lib/BOB.jar lib/sam.jar lib/mstreaming.jar lib/streaming.jar lib/routerconsole.jar lib/i2ptunnel.jar lib/org.mortbay.jetty.jar lib/javax.servlet.jar lib/jasper-runtime.jar lib/commons-el.jar lib/wrapper.jar lib/systray.jar lib/desktopgui.jar lib/i2psnark.jar lib/jrobin.jar lib/jstl.jar lib/standard.jar lib/jetty-continuation.jar lib/jetty-deploy.jar lib/jetty-http.jar lib/jetty-i2p.jar lib/jetty-io.jar lib/jetty-rewrite-handler.jar lib/jetty-security.jar lib/jetty-servlet.jar lib/jetty-servlets.jar lib/jetty-start.jar lib/jetty-util.jar lib/jetty-webapp.jar lib/jetty-xml.jar" />
|
||||
<attribute name="Built-By" value="${build.built-by}" />
|
||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||
@@ -2011,7 +2011,7 @@
|
||||
<arg value="-output"/>
|
||||
<arg value="i2p.fba"/>
|
||||
<arg value="-auxclasspath"/>
|
||||
<arg value="build/commons-el.jar:build/commons-logging.jar:build/jasper-runtime.jar:build/javax.servlet.jar:build/org.mortbay.jetty.jar:apps/jrobin/jrobin-1.5.9.1.jar:installer/lib/wrapper/all/wrapper.jar:apps/susidns/src/lib/standard.jar:apps/susidns/src/lib/jstl.jar:apps/jrobin/jrobin-1.5.9.1.jar"/>
|
||||
<arg value="build/commons-el.jar:build/jasper-runtime.jar:build/javax.servlet.jar:build/org.mortbay.jetty.jar:apps/jrobin/jrobin-1.5.9.1.jar:installer/lib/wrapper/all/wrapper.jar:apps/susidns/src/lib/standard.jar:apps/susidns/src/lib/jstl.jar:apps/jrobin/jrobin-1.5.9.1.jar"/>
|
||||
<arg value="-sourcepath"/>
|
||||
<arg value="apps/BOB/src/:apps/addressbook/java/src/:apps/i2psnark/java/src/:apps/i2ptunnel/java/src/:apps/ministreaming/java/src/:apps/routerconsole/java/src/:apps/sam/java/src/:apps/streaming/java/src/:apps/susidns/src/java/src/:apps/susimail/src/src/:apps/systray/java/src/:core/java/src/:router/java/src/:installer/java/src"/>
|
||||
<!-- start of the files to be analyzed -->
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
2018-04-27 zzz
|
||||
* Tunnels: Fix and consolidate allow-zero-hop logic,
|
||||
prevent zero-hop client tunnels when no active peers
|
||||
|
||||
2018-04-24 meeh
|
||||
* Mac OS X launcher is still WIP, but:
|
||||
- Building the I2P.app bundle is mostly done
|
||||
@@ -6,6 +10,10 @@
|
||||
* Added new entries to mtn-ignore so we avoid any PEBCAK with commiting build directories
|
||||
* Added an SBT AutoPlugin named IconHelper to generate valid ICNS images for Mac OS X
|
||||
|
||||
2018-04-23 zzz
|
||||
* Clock: Fix early NPE via DoH
|
||||
* EepGet: Handle HTTP response line with no status text
|
||||
|
||||
2018-04-23 meeh
|
||||
* Added launchers for Browser Bundle and Mac OS X
|
||||
|
||||
|
||||
@@ -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 = 6;
|
||||
public final static long BUILD = 7;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
||||
@@ -79,7 +79,7 @@ public class TunnelPoolSettings {
|
||||
private static final int DEFAULT_OB_EXPL_LENGTH_VARIANCE = 0;
|
||||
//private static final int DEFAULT_OB_EXPL_LENGTH_VARIANCE = isSlow ? 0 : 1;
|
||||
|
||||
public static final boolean DEFAULT_ALLOW_ZERO_HOP = true;
|
||||
public static final boolean DEFAULT_ALLOW_ZERO_HOP = false;
|
||||
public static final int DEFAULT_IP_RESTRICTION = 2; // class B (/16)
|
||||
private static final int MIN_PRIORITY = -25;
|
||||
private static final int MAX_PRIORITY = 25;
|
||||
@@ -161,16 +161,29 @@ public class TunnelPoolSettings {
|
||||
|
||||
/**
|
||||
* If there are no tunnels to build with, will this pool allow 0 hop tunnels?
|
||||
*
|
||||
* Always true for exploratory.
|
||||
* Generally true for client, but should probably be ignored...
|
||||
* use getLength() + getLengthVariance() > 0 instead.
|
||||
* Prior to 0.9.35, generally true for client.
|
||||
* As of 0.9.35, generally false for client, but true if
|
||||
* getLength() + Math.min(getLengthVariance(), 0) <= 0,
|
||||
* OR if getLengthOverride() == 0
|
||||
* OR if setAllowZeroHop(true) was called or set in properties.
|
||||
*/
|
||||
public boolean getAllowZeroHop() { return _allowZeroHop; }
|
||||
public boolean getAllowZeroHop() {
|
||||
return _allowZeroHop ||
|
||||
_length + Math.min(_lengthVariance, 0) <= 0 ||
|
||||
_lengthOverride == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there are no tunnels to build with, will this pool allow 0 hop tunnels?
|
||||
* No effect on exploratory (always true)
|
||||
*
|
||||
* @param ok if true, getAllowZeroHop() will always return true
|
||||
* if false, getAllowZeroHop will return as documented.
|
||||
* @deprecated unused
|
||||
*/
|
||||
@Deprecated
|
||||
public void setAllowZeroHop(boolean ok) {
|
||||
if (!_isExploratory)
|
||||
_allowZeroHop = ok;
|
||||
|
||||
@@ -66,7 +66,7 @@ class BuildExecutor implements Runnable {
|
||||
_context.statManager().createRequiredRateStat("tunnel.buildClientReject", "Response time for rejection (ms)", "Tunnels", new long[] { 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRequiredRateStat("tunnel.buildRequestTime", "Time to build a tunnel request (ms)", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||
_context.statManager().createRateStat("tunnel.buildConfigTime", "Time to build a tunnel request (ms)", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||
_context.statManager().createRateStat("tunnel.buildRequestZeroHopTime", "How long it takes to build a zero hop tunnel", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||
//_context.statManager().createRateStat("tunnel.buildRequestZeroHopTime", "How long it takes to build a zero hop tunnel", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||
//_context.statManager().createRateStat("tunnel.pendingRemaining", "How many inbound requests are pending after a pass (period is how long the pass takes)?", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||
_context.statManager().createRateStat("tunnel.buildFailFirstHop", "How often we fail to build a OB tunnel because we can't contact the first hop", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||
_context.statManager().createRateStat("tunnel.buildReplySlow", "Build reply late, but not too late", "Tunnels", new long[] { 10*60*1000 });
|
||||
@@ -535,11 +535,10 @@ class BuildExecutor implements Runnable {
|
||||
boolean ok = BuildRequestor.request(_context, pool, cfg, this);
|
||||
if (!ok)
|
||||
return;
|
||||
long buildTime = System.currentTimeMillis() - beforeBuild;
|
||||
if (cfg.getLength() <= 1)
|
||||
_context.statManager().addRateData("tunnel.buildRequestZeroHopTime", buildTime, 0);
|
||||
else
|
||||
if (cfg.getLength() > 1) {
|
||||
long buildTime = System.currentTimeMillis() - beforeBuild;
|
||||
_context.statManager().addRateData("tunnel.buildRequestTime", buildTime, 0);
|
||||
}
|
||||
long id = cfg.getReplyMessageId();
|
||||
if (id > 0) {
|
||||
synchronized (_recentBuildIds) {
|
||||
|
||||
@@ -176,8 +176,7 @@ public class TunnelPool {
|
||||
TunnelInfo selectTunnel() { return selectTunnel(true); }
|
||||
|
||||
private TunnelInfo selectTunnel(boolean allowRecurseOnFail) {
|
||||
boolean avoidZeroHop = getSettings().getLength() > 0 &&
|
||||
getSettings().getLength() + getSettings().getLengthVariance() > 0;
|
||||
boolean avoidZeroHop = !_settings.getAllowZeroHop();
|
||||
|
||||
long period = curPeriod();
|
||||
synchronized (_tunnels) {
|
||||
@@ -243,7 +242,7 @@ public class TunnelPool {
|
||||
}
|
||||
}
|
||||
|
||||
if (_alive && _settings.getAllowZeroHop())
|
||||
if (_alive && !avoidZeroHop)
|
||||
buildFallback();
|
||||
if (allowRecurseOnFail)
|
||||
return selectTunnel(false);
|
||||
@@ -264,8 +263,7 @@ public class TunnelPool {
|
||||
* @since 0.8.10
|
||||
*/
|
||||
TunnelInfo selectTunnel(Hash closestTo) {
|
||||
boolean avoidZeroHop = getSettings().getLength() > 0 &&
|
||||
getSettings().getLength() + getSettings().getLengthVariance() > 0;
|
||||
boolean avoidZeroHop = !_settings.getAllowZeroHop();
|
||||
TunnelInfo rv = null;
|
||||
synchronized (_tunnels) {
|
||||
if (!_tunnels.isEmpty()) {
|
||||
@@ -659,13 +657,6 @@ public class TunnelPool {
|
||||
return false;
|
||||
|
||||
if (_settings.getAllowZeroHop()) {
|
||||
if ( (_settings.getLength() + _settings.getLengthVariance() > 0) &&
|
||||
(!_settings.isExploratory()) &&
|
||||
(_context.profileOrganizer().countActivePeers() > 0) ) {
|
||||
// if it is a client tunnel pool and our variance doesn't allow 0 hop, prefer failure to
|
||||
// 0 hop operation (unless our router is offline)
|
||||
return false;
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(toString() + ": building a fallback tunnel (usable: " + usable + " needed: " + quantity + ")");
|
||||
|
||||
@@ -847,7 +838,7 @@ public class TunnelPool {
|
||||
}
|
||||
int wanted = getAdjustedTotalQuantity();
|
||||
|
||||
boolean allowZeroHop = ((getSettings().getLength() + getSettings().getLengthVariance()) <= 0);
|
||||
boolean allowZeroHop = _settings.getAllowZeroHop();
|
||||
|
||||
/**
|
||||
* This algorithm builds based on the previous average length of time it takes
|
||||
|
||||
Reference in New Issue
Block a user