|
|
|
@ -44,6 +44,7 @@ import org.mortbay.jetty.handler.DefaultHandler;
|
|
|
|
|
import org.mortbay.jetty.handler.HandlerCollection;
|
|
|
|
|
import org.mortbay.jetty.handler.RequestLogHandler;
|
|
|
|
|
import org.mortbay.jetty.nio.SelectChannelConnector;
|
|
|
|
|
import org.mortbay.jetty.security.Credential.MD5;
|
|
|
|
|
import org.mortbay.jetty.security.DigestAuthenticator;
|
|
|
|
|
import org.mortbay.jetty.security.HashUserRealm;
|
|
|
|
|
import org.mortbay.jetty.security.Constraint;
|
|
|
|
@ -61,6 +62,7 @@ import org.mortbay.thread.concurrent.ThreadPool;
|
|
|
|
|
* Start the router console.
|
|
|
|
|
*/
|
|
|
|
|
public class RouterConsoleRunner {
|
|
|
|
|
private final RouterContext _context;
|
|
|
|
|
private static Server _server;
|
|
|
|
|
private String _listenPort;
|
|
|
|
|
private String _listenHost;
|
|
|
|
@ -69,14 +71,19 @@ public class RouterConsoleRunner {
|
|
|
|
|
private String _webAppsDir;
|
|
|
|
|
|
|
|
|
|
private static final String DEFAULT_WEBAPP_CONFIG_FILENAME = "webapps.config";
|
|
|
|
|
|
|
|
|
|
// Jetty Auth
|
|
|
|
|
private static final DigestAuthenticator authenticator = new DigestAuthenticator();
|
|
|
|
|
private static final String JETTY_REALM = "i2prouter";
|
|
|
|
|
private static final String JETTY_ROLE = "routerAdmin";
|
|
|
|
|
|
|
|
|
|
public static final String ROUTERCONSOLE = "routerconsole";
|
|
|
|
|
public static final String PREFIX = "webapps.";
|
|
|
|
|
public static final String ENABLED = ".startOnLoad";
|
|
|
|
|
private static final String PROP_KEYSTORE_PASSWORD = "routerconsole.keystorePassword";
|
|
|
|
|
private static final String DEFAULT_KEYSTORE_PASSWORD = "changeit";
|
|
|
|
|
private static final String PROP_KEY_PASSWORD = "routerconsole.keyPassword";
|
|
|
|
|
private static final String DEFAULT_LISTEN_PORT = "7657";
|
|
|
|
|
public static final int DEFAULT_LISTEN_PORT = 7657;
|
|
|
|
|
private static final String DEFAULT_LISTEN_HOST = "127.0.0.1";
|
|
|
|
|
private static final String DEFAULT_WEBAPPS_DIR = "./webapps/";
|
|
|
|
|
private static final String USAGE = "Bad RouterConsoleRunner arguments, check clientApp.0.args in your clients.config file! " +
|
|
|
|
@ -123,7 +130,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
public RouterConsoleRunner(String args[]) {
|
|
|
|
|
if (args.length == 0) {
|
|
|
|
|
// _listenHost and _webAppsDir are defaulted below
|
|
|
|
|
_listenPort = DEFAULT_LISTEN_PORT;
|
|
|
|
|
_listenPort = Integer.toString(DEFAULT_LISTEN_PORT);
|
|
|
|
|
} else {
|
|
|
|
|
boolean ssl = false;
|
|
|
|
|
for (int i = 0; i < args.length; i++) {
|
|
|
|
@ -156,11 +163,15 @@ public class RouterConsoleRunner {
|
|
|
|
|
System.err.println(USAGE);
|
|
|
|
|
throw new IllegalArgumentException(USAGE);
|
|
|
|
|
}
|
|
|
|
|
List<RouterContext> contexts = RouterContext.listContexts();
|
|
|
|
|
if (contexts == null || contexts.isEmpty())
|
|
|
|
|
throw new IllegalStateException("no router context");
|
|
|
|
|
_context = contexts.get(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String args[]) {
|
|
|
|
|
startTrayApp();
|
|
|
|
|
RouterConsoleRunner runner = new RouterConsoleRunner(args);
|
|
|
|
|
startTrayApp(runner._context);
|
|
|
|
|
runner.startConsole();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -173,14 +184,14 @@ public class RouterConsoleRunner {
|
|
|
|
|
return _server;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void startTrayApp() {
|
|
|
|
|
private static void startTrayApp(I2PAppContext ctx) {
|
|
|
|
|
try {
|
|
|
|
|
//TODO: move away from routerconsole into a separate application.
|
|
|
|
|
//ApplicationManager?
|
|
|
|
|
VersionComparator v = new VersionComparator();
|
|
|
|
|
boolean recentJava = v.compare(System.getProperty("java.runtime.version"), "1.6") >= 0;
|
|
|
|
|
// default false for now
|
|
|
|
|
boolean desktopguiEnabled = I2PAppContext.getGlobalContext().getBooleanProperty("desktopgui.enabled");
|
|
|
|
|
boolean desktopguiEnabled = ctx.getBooleanProperty("desktopgui.enabled");
|
|
|
|
|
if (recentJava && desktopguiEnabled) {
|
|
|
|
|
//Check if we are in a headless environment, set properties accordingly
|
|
|
|
|
System.setProperty("java.awt.headless", Boolean.toString(GraphicsEnvironment.isHeadless()));
|
|
|
|
@ -215,7 +226,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
*</pre>
|
|
|
|
|
*/
|
|
|
|
|
public void startConsole() {
|
|
|
|
|
File workDir = new SecureDirectory(I2PAppContext.getGlobalContext().getTempDir(), "jetty-work");
|
|
|
|
|
File workDir = new SecureDirectory(_context.getTempDir(), "jetty-work");
|
|
|
|
|
boolean workDirRemoved = FileUtil.rmdir(workDir, false);
|
|
|
|
|
if (!workDirRemoved)
|
|
|
|
|
System.err.println("ERROR: Unable to remove Jetty temporary work directory");
|
|
|
|
@ -224,7 +235,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
System.err.println("ERROR: Unable to create Jetty temporary work directory");
|
|
|
|
|
|
|
|
|
|
//try {
|
|
|
|
|
// Log.setLog(new I2PLogger(I2PAppContext.getGlobalContext()));
|
|
|
|
|
// Log.setLog(new I2PLogger(_context));
|
|
|
|
|
//} catch (Throwable t) {
|
|
|
|
|
// System.err.println("INFO: I2P Jetty logging class not found, logging to wrapper log");
|
|
|
|
|
//}
|
|
|
|
@ -232,7 +243,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
System.setProperty("org.mortbay.log.class", "net.i2p.jetty.I2PLogger");
|
|
|
|
|
|
|
|
|
|
// so Jetty can find WebAppConfiguration
|
|
|
|
|
System.setProperty("jetty.class.path", I2PAppContext.getGlobalContext().getBaseDir() + "/lib/routerconsole.jar");
|
|
|
|
|
System.setProperty("jetty.class.path", _context.getBaseDir() + "/lib/routerconsole.jar");
|
|
|
|
|
_server = new Server();
|
|
|
|
|
_server.setGracefulShutdown(1000);
|
|
|
|
|
|
|
|
|
@ -255,11 +266,11 @@ public class RouterConsoleRunner {
|
|
|
|
|
hColl.addHandler(chColl);
|
|
|
|
|
hColl.addHandler(new DefaultHandler());
|
|
|
|
|
|
|
|
|
|
String log = I2PAppContext.getGlobalContext().getProperty("routerconsole.log");
|
|
|
|
|
String log = _context.getProperty("routerconsole.log");
|
|
|
|
|
if (log != null) {
|
|
|
|
|
File logFile = new File(log);
|
|
|
|
|
if (!logFile.isAbsolute())
|
|
|
|
|
logFile = new File(I2PAppContext.getGlobalContext().getLogDir(), "logs/" + log);
|
|
|
|
|
logFile = new File(_context.getLogDir(), "logs/" + log);
|
|
|
|
|
try {
|
|
|
|
|
RequestLogHandler rhl = new RequestLogHandler();
|
|
|
|
|
rhl.setRequestLog(new NCSARequestLog(logFile.getAbsolutePath()));
|
|
|
|
@ -279,7 +290,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
// We assume relative to the base install dir for backward compatibility
|
|
|
|
|
File app = new File(_webAppsDir);
|
|
|
|
|
if (!app.isAbsolute()) {
|
|
|
|
|
app = new File(I2PAppContext.getGlobalContext().getBaseDir(), _webAppsDir);
|
|
|
|
|
app = new File(_context.getBaseDir(), _webAppsDir);
|
|
|
|
|
try {
|
|
|
|
|
_webAppsDir = app.getCanonicalPath();
|
|
|
|
|
} catch (IOException ioe) {}
|
|
|
|
@ -349,7 +360,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// XXX: what if listenhosts do not include 127.0.0.1? (Should that ever even happen?)
|
|
|
|
|
I2PAppContext.getGlobalContext().portMapper().register(PortMapper.SVC_CONSOLE,lport);
|
|
|
|
|
_context.portMapper().register(PortMapper.SVC_CONSOLE,lport);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add SSL listeners
|
|
|
|
@ -362,8 +373,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
System.err.println("Bad routerconsole SSL port " + _sslListenPort);
|
|
|
|
|
}
|
|
|
|
|
if (sslPort > 0) {
|
|
|
|
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
|
|
|
|
File keyStore = new File(ctx.getConfigDir(), "keystore/console.ks");
|
|
|
|
|
File keyStore = new File(_context.getConfigDir(), "keystore/console.ks");
|
|
|
|
|
if (verifyKeyStore(keyStore)) {
|
|
|
|
|
StringTokenizer tok = new StringTokenizer(_sslListenHost, " ,");
|
|
|
|
|
while (tok.hasMoreTokens()) {
|
|
|
|
@ -394,9 +404,9 @@ public class RouterConsoleRunner {
|
|
|
|
|
ssll.setPort(sslPort);
|
|
|
|
|
// the keystore path and password
|
|
|
|
|
ssll.setKeystore(keyStore.getAbsolutePath());
|
|
|
|
|
ssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD));
|
|
|
|
|
ssll.setPassword(_context.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD));
|
|
|
|
|
// the X.509 cert password (if not present, verifyKeyStore() returned false)
|
|
|
|
|
ssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork"));
|
|
|
|
|
ssll.setKeyPassword(_context.getProperty(PROP_KEY_PASSWORD, "thisWontWork"));
|
|
|
|
|
ssll.setMaxIdleTime(90*1000); // default 10 sec
|
|
|
|
|
ssll.setName("ConsoleSocket"); // all with same name will use the same thread pool
|
|
|
|
|
ssll.setUseDirectBuffers(false); // default true seems to be leaky
|
|
|
|
@ -408,7 +418,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
System.err.println("You may ignore this warning if the console is still available at https://localhost:" + sslPort);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
I2PAppContext.getGlobalContext().portMapper().register(PortMapper.SVC_HTTPS_CONSOLE,sslPort);
|
|
|
|
|
_context.portMapper().register(PortMapper.SVC_HTTPS_CONSOLE,sslPort);
|
|
|
|
|
} else {
|
|
|
|
|
System.err.println("Unable to create or access keystore for SSL: " + keyStore.getAbsolutePath());
|
|
|
|
|
}
|
|
|
|
@ -419,7 +429,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rootWebApp = new LocaleWebAppHandler(I2PAppContext.getGlobalContext(),
|
|
|
|
|
rootWebApp = new LocaleWebAppHandler(_context,
|
|
|
|
|
"/", _webAppsDir + ROUTERCONSOLE + ".war");
|
|
|
|
|
File tmpdir = new SecureDirectory(workDir, ROUTERCONSOLE + "-" +
|
|
|
|
|
(_listenPort != null ? _listenPort : _sslListenPort));
|
|
|
|
@ -429,7 +439,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
rootWebApp.setSessionHandler(new SessionHandler());
|
|
|
|
|
rootServletHandler = new ServletHandler();
|
|
|
|
|
rootWebApp.setServletHandler(rootServletHandler);
|
|
|
|
|
initialize(rootWebApp);
|
|
|
|
|
initialize(_context, rootWebApp);
|
|
|
|
|
chColl.addHandler(rootWebApp);
|
|
|
|
|
|
|
|
|
|
} catch (Exception ioe) {
|
|
|
|
@ -466,7 +476,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
}
|
|
|
|
|
if (error) {
|
|
|
|
|
System.err.println("WARNING: Error starting one or more listeners of the Router Console server.\n" +
|
|
|
|
|
"If your console is still accessible at http://127.0.0.1:7657/,\n" +
|
|
|
|
|
"If your console is still accessible at http://127.0.0.1:" + _listenPort + "/,\n" +
|
|
|
|
|
"this may be a problem only with binding to the IPV6 address ::1.\n" +
|
|
|
|
|
"If so, you may ignore this error, or remove the\n" +
|
|
|
|
|
"\"::1,\" in the \"clientApp.0.args\" line of the clients.config file.");
|
|
|
|
@ -488,7 +498,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
if (! "false".equals(enabled)) {
|
|
|
|
|
try {
|
|
|
|
|
String path = new File(dir, fileNames[i]).getCanonicalPath();
|
|
|
|
|
WebAppStarter.startWebApp(I2PAppContext.getGlobalContext(), chColl, appName, path);
|
|
|
|
|
WebAppStarter.startWebApp(_context, chColl, appName, path);
|
|
|
|
|
if (enabled == null) {
|
|
|
|
|
// do this so configclients.jsp knows about all apps from reading the config
|
|
|
|
|
props.setProperty(PREFIX + appName + ENABLED, "true");
|
|
|
|
@ -509,7 +519,7 @@ public class RouterConsoleRunner {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rewrite)
|
|
|
|
|
storeWebAppProperties(props);
|
|
|
|
|
storeWebAppProperties(_context, props);
|
|
|
|
|
|
|
|
|
|
if (rootServletHandler != null && notStarted.size() > 0) {
|
|
|
|
|
// map each not-started webapp to the error page
|
|
|
|
@ -536,38 +546,32 @@ public class RouterConsoleRunner {
|
|
|
|
|
t.setPriority(Thread.NORM_PRIORITY - 1);
|
|
|
|
|
t.start();
|
|
|
|
|
|
|
|
|
|
List<RouterContext> contexts = RouterContext.listContexts();
|
|
|
|
|
if (contexts != null) {
|
|
|
|
|
RouterContext ctx = contexts.get(0);
|
|
|
|
|
|
|
|
|
|
NewsFetcher fetcher = NewsFetcher.getInstance(ctx);
|
|
|
|
|
NewsFetcher fetcher = NewsFetcher.getInstance(_context);
|
|
|
|
|
Thread newsThread = new I2PAppThread(fetcher, "NewsFetcher", true);
|
|
|
|
|
newsThread.setPriority(Thread.NORM_PRIORITY - 1);
|
|
|
|
|
newsThread.start();
|
|
|
|
|
|
|
|
|
|
if (PluginStarter.pluginsEnabled(ctx)) {
|
|
|
|
|
t = new I2PAppThread(new PluginStarter(ctx), "PluginStarter", true);
|
|
|
|
|
if (PluginStarter.pluginsEnabled(_context)) {
|
|
|
|
|
t = new I2PAppThread(new PluginStarter(_context), "PluginStarter", true);
|
|
|
|
|
t.setPriority(Thread.NORM_PRIORITY - 1);
|
|
|
|
|
t.start();
|
|
|
|
|
ctx.addShutdownTask(new PluginStopper(ctx));
|
|
|
|
|
_context.addShutdownTask(new PluginStopper(_context));
|
|
|
|
|
}
|
|
|
|
|
ctx.addShutdownTask(new NewsShutdown(fetcher, newsThread));
|
|
|
|
|
_context.addShutdownTask(new NewsShutdown(fetcher, newsThread));
|
|
|
|
|
// stat summarizer registers its own hook
|
|
|
|
|
ctx.addShutdownTask(new ServerShutdown());
|
|
|
|
|
ConfigServiceHandler.registerSignalHandler(ctx);
|
|
|
|
|
} // else log CRIT ?
|
|
|
|
|
_context.addShutdownTask(new ServerShutdown(_context));
|
|
|
|
|
ConfigServiceHandler.registerSignalHandler(_context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return success if it exists and we have a password, or it was created successfully.
|
|
|
|
|
* @since 0.8.3
|
|
|
|
|
*/
|
|
|
|
|
private static boolean verifyKeyStore(File ks) {
|
|
|
|
|
private boolean verifyKeyStore(File ks) {
|
|
|
|
|
if (ks.exists()) {
|
|
|
|
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
|
|
|
|
boolean rv = ctx.getProperty(PROP_KEY_PASSWORD) != null;
|
|
|
|
|
boolean rv = _context.getProperty(PROP_KEY_PASSWORD) != null;
|
|
|
|
|
if (!rv)
|
|
|
|
|
System.err.println("Console SSL error, must set " + PROP_KEY_PASSWORD + " in " + (new File(ctx.getConfigDir(), "router.config")).getAbsolutePath());
|
|
|
|
|
System.err.println("Console SSL error, must set " + PROP_KEY_PASSWORD + " in " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath());
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
File dir = ks.getParentFile();
|
|
|
|
@ -588,14 +592,13 @@ public class RouterConsoleRunner {
|
|
|
|
|
* @return success
|
|
|
|
|
* @since 0.8.3
|
|
|
|
|
*/
|
|
|
|
|
private static boolean createKeyStore(File ks) {
|
|
|
|
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
|
|
|
|
private boolean createKeyStore(File ks) {
|
|
|
|
|
// make a random 48 character password (30 * 8 / 5)
|
|
|
|
|
byte[] rand = new byte[30];
|
|
|
|
|
ctx.random().nextBytes(rand);
|
|
|
|
|
_context.random().nextBytes(rand);
|
|
|
|
|
String keyPassword = Base32.encode(rand);
|
|
|
|
|
// and one for the cname
|
|
|
|
|
ctx.random().nextBytes(rand);
|
|
|
|
|
_context.random().nextBytes(rand);
|
|
|
|
|
String cname = Base32.encode(rand) + ".console.i2p.net";
|
|
|
|
|
|
|
|
|
|
String keytool = (new File(System.getProperty("java.home"), "bin/keytool")).getAbsolutePath();
|
|
|
|
@ -617,11 +620,10 @@ public class RouterConsoleRunner {
|
|
|
|
|
if (success) {
|
|
|
|
|
SecureFileOutputStream.setPerms(ks);
|
|
|
|
|
try {
|
|
|
|
|
RouterContext rctx = (RouterContext) ctx;
|
|
|
|
|
Map<String, String> changes = new HashMap();
|
|
|
|
|
changes.put(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD);
|
|
|
|
|
changes.put(PROP_KEY_PASSWORD, keyPassword);
|
|
|
|
|
rctx.router().saveConfig(changes, null);
|
|
|
|
|
_context.router().saveConfig(changes, null);
|
|
|
|
|
} catch (Exception e) {} // class cast exception
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -638,27 +640,37 @@ public class RouterConsoleRunner {
|
|
|
|
|
System.err.println(buf.toString());
|
|
|
|
|
System.err.println("This is for the Sun/Oracle keytool, others may be incompatible.\n" +
|
|
|
|
|
"If you create the keystore manually, you must add " + PROP_KEYSTORE_PASSWORD + " and " + PROP_KEY_PASSWORD +
|
|
|
|
|
" to " + (new File(ctx.getConfigDir(), "router.config")).getAbsolutePath());
|
|
|
|
|
" to " + (new File(_context.getConfigDir(), "router.config")).getAbsolutePath());
|
|
|
|
|
}
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void initialize(WebAppContext context) {
|
|
|
|
|
/**
|
|
|
|
|
* Set up basic security constraints for the webapp.
|
|
|
|
|
* Add all users and passwords.
|
|
|
|
|
*/
|
|
|
|
|
static void initialize(RouterContext ctx, WebAppContext context) {
|
|
|
|
|
SecurityHandler sec = new SecurityHandler();
|
|
|
|
|
List<ConstraintMapping> constraints = new ArrayList(4);
|
|
|
|
|
String password = getPassword();
|
|
|
|
|
if (password != null) {
|
|
|
|
|
HashUserRealm realm = new HashUserRealm("i2prouter");
|
|
|
|
|
realm.put("admin", password);
|
|
|
|
|
realm.addUserToRole("admin", "routerAdmin");
|
|
|
|
|
ConsolePasswordManager mgr = new ConsolePasswordManager(ctx);
|
|
|
|
|
mgr.migrateConsole();
|
|
|
|
|
Map<String, String> userpw = mgr.getMD5(PasswordManager.PROP_CONSOLE_NEW);
|
|
|
|
|
if (!userpw.isEmpty()) {
|
|
|
|
|
HashUserRealm realm = new HashUserRealm(JETTY_REALM);
|
|
|
|
|
sec.setUserRealm(realm);
|
|
|
|
|
sec.setAuthenticator(authenticator);
|
|
|
|
|
Constraint constraint = new Constraint("admin", "routerAdmin");
|
|
|
|
|
constraint.setAuthenticate(true);
|
|
|
|
|
ConstraintMapping cm = new ConstraintMapping();
|
|
|
|
|
cm.setConstraint(constraint);
|
|
|
|
|
cm.setPathSpec("/");
|
|
|
|
|
constraints.add(cm);
|
|
|
|
|
for (Map.Entry<String, String> e : userpw.entrySet()) {
|
|
|
|
|
String user = e.getKey();
|
|
|
|
|
String pw = e.getValue();
|
|
|
|
|
realm.put(user, MD5.__TYPE + pw);
|
|
|
|
|
realm.addUserToRole(user, JETTY_ROLE);
|
|
|
|
|
Constraint constraint = new Constraint(user, JETTY_ROLE);
|
|
|
|
|
constraint.setAuthenticate(true);
|
|
|
|
|
ConstraintMapping cm = new ConstraintMapping();
|
|
|
|
|
cm.setConstraint(constraint);
|
|
|
|
|
cm.setPathSpec("/");
|
|
|
|
|
constraints.add(cm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This forces a '403 Forbidden' response for TRACE and OPTIONS unless the
|
|
|
|
@ -693,33 +705,21 @@ public class RouterConsoleRunner {
|
|
|
|
|
context.setSecurityHandler(sec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static String getPassword() {
|
|
|
|
|
List<RouterContext> contexts = RouterContext.listContexts();
|
|
|
|
|
if (contexts != null) {
|
|
|
|
|
for (int i = 0; i < contexts.size(); i++) {
|
|
|
|
|
RouterContext ctx = contexts.get(i);
|
|
|
|
|
String password = ctx.getProperty("consolePassword");
|
|
|
|
|
if (password != null) {
|
|
|
|
|
password = password.trim();
|
|
|
|
|
if (password.length() > 0) {
|
|
|
|
|
return password;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// no password in any context
|
|
|
|
|
return null;
|
|
|
|
|
} else {
|
|
|
|
|
// no contexts?!
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @since 0.8.8 */
|
|
|
|
|
private static class ServerShutdown implements Runnable {
|
|
|
|
|
private final I2PAppContext _ctx;
|
|
|
|
|
|
|
|
|
|
public ServerShutdown(I2PAppContext ctx) {
|
|
|
|
|
_ctx = ctx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void run() {
|
|
|
|
|
try {
|
|
|
|
|
_server.stop();
|
|
|
|
|
} catch (Exception ie) {}
|
|
|
|
|
PortMapper portMapper = _ctx.portMapper();
|
|
|
|
|
portMapper.unregister(PortMapper.SVC_CONSOLE);
|
|
|
|
|
portMapper.unregister(PortMapper.SVC_HTTPS_CONSOLE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -739,13 +739,18 @@ public class RouterConsoleRunner {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Properties webAppProperties() {
|
|
|
|
|
return webAppProperties(I2PAppContext.getGlobalContext().getConfigDir().getAbsolutePath());
|
|
|
|
|
private Properties webAppProperties() {
|
|
|
|
|
return webAppProperties(_context.getConfigDir().getAbsolutePath());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @since 0.9.4 */
|
|
|
|
|
public static Properties webAppProperties(I2PAppContext ctx) {
|
|
|
|
|
return webAppProperties(ctx.getConfigDir().getAbsolutePath());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Properties webAppProperties(String dir) {
|
|
|
|
|
Properties rv = new Properties();
|
|
|
|
|
// String webappConfigFile = ctx.getProperty(PROP_WEBAPP_CONFIG_FILENAME, DEFAULT_WEBAPP_CONFIG_FILENAME);
|
|
|
|
|
// String webappConfigFile = _context.getProperty(PROP_WEBAPP_CONFIG_FILENAME, DEFAULT_WEBAPP_CONFIG_FILENAME);
|
|
|
|
|
String webappConfigFile = DEFAULT_WEBAPP_CONFIG_FILENAME;
|
|
|
|
|
File cfgFile = new File(dir, webappConfigFile);
|
|
|
|
|
|
|
|
|
@ -758,10 +763,10 @@ public class RouterConsoleRunner {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void storeWebAppProperties(Properties props) {
|
|
|
|
|
// String webappConfigFile = ctx.getProperty(PROP_WEBAPP_CONFIG_FILENAME, DEFAULT_WEBAPP_CONFIG_FILENAME);
|
|
|
|
|
public static void storeWebAppProperties(RouterContext ctx, Properties props) {
|
|
|
|
|
// String webappConfigFile = _context.getProperty(PROP_WEBAPP_CONFIG_FILENAME, DEFAULT_WEBAPP_CONFIG_FILENAME);
|
|
|
|
|
String webappConfigFile = DEFAULT_WEBAPP_CONFIG_FILENAME;
|
|
|
|
|
File cfgFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), webappConfigFile);
|
|
|
|
|
File cfgFile = new File(ctx.getConfigDir(), webappConfigFile);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
DataHelper.storeProps(props, cfgFile);
|
|
|
|
|