2008-06-16 12:31:14 +00:00
|
|
|
package net.i2p.router.web;
|
|
|
|
|
2015-03-21 17:23:19 +00:00
|
|
|
import java.io.BufferedOutputStream;
|
2009-06-15 15:32:27 +00:00
|
|
|
import java.io.File;
|
2015-03-21 17:23:19 +00:00
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.OutputStream;
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
import java.net.URI;
|
|
|
|
import java.net.URISyntaxException;
|
2008-06-16 12:31:14 +00:00
|
|
|
import java.util.HashMap;
|
2008-06-17 13:48:41 +00:00
|
|
|
import java.util.List;
|
2011-11-28 20:32:23 +00:00
|
|
|
import java.util.Locale;
|
2008-06-16 12:31:14 +00:00
|
|
|
import java.util.Map;
|
2008-06-17 13:48:41 +00:00
|
|
|
import java.util.Properties;
|
|
|
|
import java.util.Set;
|
|
|
|
|
2013-04-16 14:59:18 +00:00
|
|
|
import net.i2p.app.ClientApp;
|
|
|
|
import net.i2p.app.ClientAppState;
|
2015-03-21 17:23:19 +00:00
|
|
|
import net.i2p.crypto.SU3File;
|
|
|
|
import net.i2p.crypto.TrustedUpdate;
|
|
|
|
import net.i2p.data.DataHelper;
|
2010-12-24 16:52:23 +00:00
|
|
|
import net.i2p.router.client.ClientManagerFacadeImpl;
|
2008-06-17 13:48:41 +00:00
|
|
|
import net.i2p.router.startup.ClientAppConfig;
|
2008-06-20 20:20:50 +00:00
|
|
|
import net.i2p.router.startup.LoadClientAppsJob;
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
import net.i2p.router.update.ConsoleUpdateManager;
|
|
|
|
import static net.i2p.update.UpdateType.*;
|
2015-03-21 17:23:19 +00:00
|
|
|
import net.i2p.util.SecureFileOutputStream;
|
2015-04-24 16:08:08 +00:00
|
|
|
import net.i2p.util.PortMapper;
|
2008-06-16 12:31:14 +00:00
|
|
|
|
2012-11-21 20:49:18 +00:00
|
|
|
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
2008-06-20 20:20:50 +00:00
|
|
|
|
2008-06-16 12:31:14 +00:00
|
|
|
/**
|
2008-06-17 13:48:41 +00:00
|
|
|
* Saves changes to clients.config or webapps.config
|
2008-06-16 12:31:14 +00:00
|
|
|
*/
|
|
|
|
public class ConfigClientsHandler extends FormHandler {
|
|
|
|
|
2009-08-15 16:08:33 +00:00
|
|
|
@Override
|
2008-06-16 12:31:14 +00:00
|
|
|
protected void processForm() {
|
2010-03-29 21:20:48 +00:00
|
|
|
// set action for when CR is hit in a text input box
|
|
|
|
if (_action.length() <= 0) {
|
|
|
|
String url = getJettyString("pluginURL");
|
|
|
|
if (url != null && url.length() > 0)
|
|
|
|
_action = "Install Plugin";
|
|
|
|
else
|
|
|
|
_action = "Save Client Configuration";
|
|
|
|
}
|
|
|
|
|
2015-09-25 19:55:36 +00:00
|
|
|
if (_action.equals(_t("Save Client Configuration"))) {
|
2008-06-17 13:48:41 +00:00
|
|
|
saveClientChanges();
|
2009-10-28 18:26:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-09-25 19:55:36 +00:00
|
|
|
if (_action.equals(_t("Save Interface Configuration"))) {
|
2010-12-24 16:52:23 +00:00
|
|
|
saveInterfaceChanges();
|
|
|
|
return;
|
|
|
|
}
|
2015-09-25 19:55:36 +00:00
|
|
|
if (_action.equals(_t("Save WebApp Configuration"))) {
|
2008-06-17 13:48:41 +00:00
|
|
|
saveWebAppChanges();
|
2009-10-28 18:26:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-08-03 13:58:51 +00:00
|
|
|
boolean pluginsEnabled = PluginStarter.pluginsEnabled(_context);
|
2015-09-25 19:55:36 +00:00
|
|
|
if (_action.equals(_t("Save Plugin Configuration"))) {
|
2014-08-03 13:58:51 +00:00
|
|
|
if (pluginsEnabled)
|
|
|
|
savePluginChanges();
|
|
|
|
else
|
|
|
|
addFormError("Plugins disabled");
|
2010-02-10 19:09:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-09-25 19:55:36 +00:00
|
|
|
if (_action.equals(_t("Install Plugin"))) {
|
2014-08-03 13:58:51 +00:00
|
|
|
if (pluginsEnabled &&
|
2014-08-30 16:14:41 +00:00
|
|
|
(_context.getBooleanPropertyDefaultTrue(ConfigClientsHelper.PROP_ENABLE_PLUGIN_INSTALL) ||
|
2014-08-03 13:58:51 +00:00
|
|
|
isAdvanced()))
|
|
|
|
installPlugin();
|
|
|
|
else
|
|
|
|
addFormError("Plugins disabled");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-09-25 19:55:36 +00:00
|
|
|
if (_action.equals(_t("Install Plugin from File"))) {
|
2015-03-21 17:23:19 +00:00
|
|
|
if (pluginsEnabled &&
|
|
|
|
(_context.getBooleanPropertyDefaultTrue(ConfigClientsHelper.PROP_ENABLE_PLUGIN_INSTALL) ||
|
|
|
|
isAdvanced()))
|
|
|
|
installPluginFromFile();
|
|
|
|
else
|
|
|
|
addFormError("Plugins disabled");
|
|
|
|
return;
|
|
|
|
}
|
2015-09-25 19:55:36 +00:00
|
|
|
if (_action.equals(_t("Update All Installed Plugins"))) {
|
2014-08-03 13:58:51 +00:00
|
|
|
if (pluginsEnabled)
|
|
|
|
updateAllPlugins();
|
|
|
|
else
|
|
|
|
addFormError("Plugins disabled");
|
2012-01-15 21:15:08 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-10-28 18:26:50 +00:00
|
|
|
// value
|
|
|
|
if (_action.startsWith("Start ")) {
|
2008-06-20 20:20:50 +00:00
|
|
|
String app = _action.substring(6);
|
|
|
|
int appnum = -1;
|
|
|
|
try {
|
|
|
|
appnum = Integer.parseInt(app);
|
|
|
|
} catch (NumberFormatException nfe) {}
|
2010-02-17 18:12:46 +00:00
|
|
|
if (appnum >= 0) {
|
2008-06-20 20:20:50 +00:00
|
|
|
startClient(appnum);
|
2010-02-17 18:12:46 +00:00
|
|
|
} else {
|
|
|
|
List<String> plugins = PluginStarter.getPlugins();
|
2014-08-03 13:58:51 +00:00
|
|
|
if (plugins.contains(app)) {
|
|
|
|
if (pluginsEnabled)
|
|
|
|
startPlugin(app);
|
|
|
|
else
|
|
|
|
addFormError("Plugins disabled");
|
|
|
|
} else {
|
2010-02-17 18:12:46 +00:00
|
|
|
startWebApp(app);
|
2014-08-03 13:58:51 +00:00
|
|
|
}
|
2010-02-17 18:12:46 +00:00
|
|
|
}
|
2009-10-28 18:26:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-01-06 21:24:08 +00:00
|
|
|
|
|
|
|
// value
|
|
|
|
if (_action.startsWith("Delete ")) {
|
|
|
|
String app = _action.substring(7);
|
|
|
|
int appnum = -1;
|
|
|
|
try {
|
|
|
|
appnum = Integer.parseInt(app);
|
|
|
|
} catch (NumberFormatException nfe) {}
|
2010-02-10 19:09:35 +00:00
|
|
|
if (appnum >= 0) {
|
2014-08-10 12:18:18 +00:00
|
|
|
if (_context.getBooleanProperty(ConfigClientsHelper.PROP_ENABLE_CLIENT_CHANGE) ||
|
|
|
|
isAdvanced()) {
|
|
|
|
deleteClient(appnum);
|
|
|
|
} else {
|
|
|
|
addFormError("Delete client disabled");
|
|
|
|
}
|
2014-08-03 13:58:51 +00:00
|
|
|
} else if (pluginsEnabled) {
|
2010-02-10 19:09:35 +00:00
|
|
|
try {
|
|
|
|
PluginStarter.stopPlugin(_context, app);
|
2012-03-19 01:46:47 +00:00
|
|
|
} catch (ClassNotFoundException cnfe) {
|
|
|
|
// don't complain here. Some plugins need to be ran to be deleted.
|
|
|
|
// I tried to check to see if the plugin was ran elsewhere,
|
|
|
|
// and it sait it was when it was not. -- Sponge
|
|
|
|
} catch (Throwable e) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Error stopping plugin {0}", app) + ": " + e);
|
2012-03-19 01:46:47 +00:00
|
|
|
_log.error("Error stopping plugin " + app, e);
|
|
|
|
}
|
|
|
|
try {
|
2010-02-11 19:18:26 +00:00
|
|
|
PluginStarter.deletePlugin(_context, app);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Deleted plugin {0}", app));
|
2010-02-11 21:41:54 +00:00
|
|
|
} catch (Throwable e) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Error deleting plugin {0}", app) + ": " + e);
|
2010-02-11 21:41:54 +00:00
|
|
|
_log.error("Error deleting plugin " + app, e);
|
2010-02-11 19:18:26 +00:00
|
|
|
}
|
2014-08-03 13:58:51 +00:00
|
|
|
} else {
|
|
|
|
addFormError("Plugins disabled");
|
2010-02-10 19:09:35 +00:00
|
|
|
}
|
2010-01-06 21:24:08 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-02-10 19:09:35 +00:00
|
|
|
|
|
|
|
// value
|
|
|
|
if (_action.startsWith("Stop ")) {
|
2011-06-01 03:59:12 +00:00
|
|
|
|
2010-02-10 19:09:35 +00:00
|
|
|
String app = _action.substring(5);
|
2011-06-01 03:59:12 +00:00
|
|
|
int appnum = -1;
|
2010-02-10 19:09:35 +00:00
|
|
|
try {
|
2011-06-01 03:59:12 +00:00
|
|
|
appnum = Integer.parseInt(app);
|
|
|
|
} catch (NumberFormatException nfe) {}
|
|
|
|
if (appnum >= 0) {
|
|
|
|
stopClient(appnum);
|
|
|
|
} else {
|
2013-09-21 16:11:55 +00:00
|
|
|
List<String> plugins = PluginStarter.getPlugins();
|
|
|
|
if (plugins.contains(app)) {
|
|
|
|
try {
|
2014-08-03 13:58:51 +00:00
|
|
|
if (pluginsEnabled) {
|
|
|
|
PluginStarter.stopPlugin(_context, app);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Stopped plugin {0}", app));
|
2014-08-03 13:58:51 +00:00
|
|
|
} else {
|
|
|
|
addFormError("Plugins disabled");
|
|
|
|
}
|
2013-09-21 16:11:55 +00:00
|
|
|
} catch (Throwable e) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Error stopping plugin {0}", app) + ": " + e);
|
2013-09-21 16:11:55 +00:00
|
|
|
_log.error("Error stopping plugin " + app, e);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
WebAppStarter.stopWebApp(app);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Stopped webapp {0}", app));
|
2011-06-01 03:59:12 +00:00
|
|
|
}
|
2010-02-11 21:41:54 +00:00
|
|
|
}
|
2010-02-10 19:09:35 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// value
|
|
|
|
if (_action.startsWith("Update ")) {
|
2014-08-03 13:58:51 +00:00
|
|
|
if (pluginsEnabled) {
|
|
|
|
String app = _action.substring(7);
|
|
|
|
updatePlugin(app);
|
|
|
|
} else {
|
|
|
|
addFormError("Plugins disabled");
|
|
|
|
}
|
2010-02-10 19:09:35 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// value
|
|
|
|
if (_action.startsWith("Check ")) {
|
2014-08-03 13:58:51 +00:00
|
|
|
if (pluginsEnabled) {
|
|
|
|
String app = _action.substring(6);
|
|
|
|
checkPlugin(app);
|
|
|
|
} else {
|
|
|
|
addFormError("Plugins disabled");
|
|
|
|
}
|
2010-02-10 19:09:35 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-28 18:26:50 +00:00
|
|
|
// label (IE)
|
2015-09-25 19:55:36 +00:00
|
|
|
String xStart = _t("Start");
|
2011-11-28 20:32:23 +00:00
|
|
|
if (_action.toLowerCase(Locale.US).startsWith(xStart + "<span class=hide> ") &&
|
|
|
|
_action.toLowerCase(Locale.US).endsWith("</span>")) {
|
2009-04-03 21:33:35 +00:00
|
|
|
// IE sucks
|
2009-10-28 18:26:50 +00:00
|
|
|
String app = _action.substring(xStart.length() + 18, _action.length() - 7);
|
2009-04-03 21:33:35 +00:00
|
|
|
int appnum = -1;
|
|
|
|
try {
|
|
|
|
appnum = Integer.parseInt(app);
|
|
|
|
} catch (NumberFormatException nfe) {}
|
2010-02-17 18:12:46 +00:00
|
|
|
if (appnum >= 0) {
|
2009-04-03 21:33:35 +00:00
|
|
|
startClient(appnum);
|
2010-02-17 18:12:46 +00:00
|
|
|
} else {
|
|
|
|
List<String> plugins = PluginStarter.getPlugins();
|
2014-08-03 13:58:51 +00:00
|
|
|
if (plugins.contains(app)) {
|
|
|
|
if (pluginsEnabled)
|
|
|
|
startPlugin(app);
|
|
|
|
else
|
|
|
|
addFormError("Plugins disabled");
|
|
|
|
} else {
|
2010-02-17 18:12:46 +00:00
|
|
|
startWebApp(app);
|
2014-08-03 13:58:51 +00:00
|
|
|
}
|
2010-02-17 18:12:46 +00:00
|
|
|
}
|
2008-06-16 12:31:14 +00:00
|
|
|
} else {
|
2015-09-25 19:55:36 +00:00
|
|
|
//addFormError(_t("Unsupported") + ' ' + _action + '.');
|
2008-06-16 12:31:14 +00:00
|
|
|
}
|
2010-02-10 19:09:35 +00:00
|
|
|
|
2008-06-16 12:31:14 +00:00
|
|
|
}
|
|
|
|
|
2008-06-17 13:48:41 +00:00
|
|
|
private void saveClientChanges() {
|
2010-01-06 21:24:08 +00:00
|
|
|
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(_context);
|
2008-06-17 13:48:41 +00:00
|
|
|
for (int cur = 0; cur < clients.size(); cur++) {
|
2010-01-06 21:24:08 +00:00
|
|
|
ClientAppConfig ca = clients.get(cur);
|
2008-06-17 13:48:41 +00:00
|
|
|
Object val = _settings.get(cur + ".enabled");
|
2014-05-07 14:36:41 +00:00
|
|
|
if (! (RouterConsoleRunner.class.getName().equals(ca.className)))
|
2008-06-17 13:48:41 +00:00
|
|
|
ca.disabled = val == null;
|
2010-01-06 21:24:08 +00:00
|
|
|
// edit of an existing entry
|
2014-08-03 13:58:51 +00:00
|
|
|
if (_context.getBooleanProperty(ConfigClientsHelper.PROP_ENABLE_CLIENT_CHANGE) ||
|
|
|
|
isAdvanced()) {
|
|
|
|
String desc = getJettyString("desc" + cur);
|
|
|
|
if (desc != null) {
|
|
|
|
int spc = desc.indexOf(" ");
|
|
|
|
String clss = desc;
|
|
|
|
String args = null;
|
|
|
|
if (spc >= 0) {
|
|
|
|
clss = desc.substring(0, spc);
|
|
|
|
args = desc.substring(spc + 1);
|
|
|
|
}
|
|
|
|
ca.className = clss;
|
|
|
|
ca.args = args;
|
|
|
|
ca.clientName = getJettyString("name" + cur);
|
2010-01-06 21:24:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-03 13:58:51 +00:00
|
|
|
// new client
|
|
|
|
if (_context.getBooleanProperty(ConfigClientsHelper.PROP_ENABLE_CLIENT_CHANGE) ||
|
|
|
|
isAdvanced()) {
|
|
|
|
int newClient = clients.size();
|
|
|
|
String newDesc = getJettyString("desc" + newClient);
|
|
|
|
if (newDesc != null && newDesc.trim().length() > 0) {
|
|
|
|
// new entry
|
|
|
|
int spc = newDesc.indexOf(" ");
|
|
|
|
String clss = newDesc;
|
|
|
|
String args = null;
|
|
|
|
if (spc >= 0) {
|
|
|
|
clss = newDesc.substring(0, spc);
|
|
|
|
args = newDesc.substring(spc + 1);
|
|
|
|
}
|
|
|
|
String name = getJettyString("name" + newClient);
|
|
|
|
if (name == null || name.trim().length() <= 0) name = "new client";
|
|
|
|
ClientAppConfig ca = new ClientAppConfig(clss, name, args, 2*60*1000,
|
|
|
|
_settings.get(newClient + ".enabled") != null);
|
|
|
|
clients.add(ca);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("New client added") + ": " + name + " (" + clss + ").");
|
2010-01-06 21:24:08 +00:00
|
|
|
}
|
2008-06-17 13:48:41 +00:00
|
|
|
}
|
2010-01-06 21:24:08 +00:00
|
|
|
|
2008-06-17 13:48:41 +00:00
|
|
|
ClientAppConfig.writeClientAppConfig(_context, clients);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Client configuration saved successfully"));
|
|
|
|
//addFormNotice(_t("Restart required to take effect"));
|
2010-01-06 21:24:08 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 14:59:18 +00:00
|
|
|
/**
|
|
|
|
* @since Implemented in 0.9.6 using ClientAppManager
|
|
|
|
*/
|
2011-06-01 03:59:12 +00:00
|
|
|
private void stopClient(int i) {
|
|
|
|
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(_context);
|
|
|
|
if (i >= clients.size()) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Bad client index."));
|
2011-06-01 03:59:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ClientAppConfig ca = clients.get(i);
|
2014-01-06 13:57:45 +00:00
|
|
|
ClientApp clientApp = _context.routerAppManager().getClientApp(ca.className, LoadClientAppsJob.parseArgs(ca.args));
|
2013-04-16 14:59:18 +00:00
|
|
|
if (clientApp != null && clientApp.getState() == ClientAppState.RUNNING) {
|
|
|
|
try {
|
|
|
|
// todo parseArgs(ca.stopArgs) ?
|
|
|
|
clientApp.shutdown(null);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Client {0} stopped", ca.clientName));
|
2013-04-16 14:59:18 +00:00
|
|
|
// Give a chance for status to update
|
|
|
|
try {
|
|
|
|
Thread.sleep(1000);
|
|
|
|
} catch (InterruptedException ie) {}
|
|
|
|
} catch (Throwable t) {
|
|
|
|
addFormError("Cannot stop client " + ca.className + ": " + t);
|
|
|
|
_log.error("Error stopping client " + ca.className, t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
addFormError("Cannot stop client " + i + ": " + ca.className);
|
|
|
|
}
|
2011-06-01 03:59:12 +00:00
|
|
|
}
|
|
|
|
|
2008-06-20 20:20:50 +00:00
|
|
|
private void startClient(int i) {
|
2010-01-06 21:24:08 +00:00
|
|
|
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(_context);
|
2008-06-20 20:20:50 +00:00
|
|
|
if (i >= clients.size()) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Bad client index."));
|
2008-06-20 20:20:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-01-06 21:24:08 +00:00
|
|
|
ClientAppConfig ca = clients.get(i);
|
2012-10-13 12:51:24 +00:00
|
|
|
LoadClientAppsJob.runClient(ca.className, ca.clientName, LoadClientAppsJob.parseArgs(ca.args), _context, _log);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Client {0} started", ca.clientName));
|
2013-04-16 14:59:18 +00:00
|
|
|
// Give a chance for status to update
|
|
|
|
try {
|
|
|
|
Thread.sleep(1000);
|
|
|
|
} catch (InterruptedException ie) {}
|
2008-06-20 20:20:50 +00:00
|
|
|
}
|
|
|
|
|
2010-01-06 21:24:08 +00:00
|
|
|
private void deleteClient(int i) {
|
|
|
|
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(_context);
|
|
|
|
if (i < 0 || i >= clients.size()) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Bad client index."));
|
2010-01-06 21:24:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ClientAppConfig ca = clients.remove(i);
|
|
|
|
ClientAppConfig.writeClientAppConfig(_context, clients);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Client {0} deleted", ca.clientName));
|
2010-01-06 21:24:08 +00:00
|
|
|
}
|
|
|
|
|
2008-06-17 13:48:41 +00:00
|
|
|
private void saveWebAppChanges() {
|
2012-10-13 13:06:22 +00:00
|
|
|
Properties props = RouterConsoleRunner.webAppProperties(_context);
|
2015-04-24 16:27:03 +00:00
|
|
|
Set<String> keys = props.stringPropertyNames();
|
|
|
|
for (String name : keys) {
|
2008-06-17 13:48:41 +00:00
|
|
|
if (! (name.startsWith(RouterConsoleRunner.PREFIX) && name.endsWith(RouterConsoleRunner.ENABLED)))
|
|
|
|
continue;
|
|
|
|
String app = name.substring(RouterConsoleRunner.PREFIX.length(), name.lastIndexOf(RouterConsoleRunner.ENABLED));
|
|
|
|
Object val = _settings.get(app + ".enabled");
|
|
|
|
if (! RouterConsoleRunner.ROUTERCONSOLE.equals(app))
|
|
|
|
props.setProperty(name, "" + (val != null));
|
2008-06-16 12:31:14 +00:00
|
|
|
}
|
2012-10-13 13:06:22 +00:00
|
|
|
RouterConsoleRunner.storeWebAppProperties(_context, props);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("WebApp configuration saved."));
|
2010-02-10 19:09:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void savePluginChanges() {
|
|
|
|
Properties props = PluginStarter.pluginProperties();
|
2015-04-24 16:27:03 +00:00
|
|
|
Set<String> keys = props.stringPropertyNames();
|
|
|
|
for (String name : keys) {
|
2010-02-10 19:09:35 +00:00
|
|
|
if (! (name.startsWith(PluginStarter.PREFIX) && name.endsWith(PluginStarter.ENABLED)))
|
|
|
|
continue;
|
|
|
|
String app = name.substring(PluginStarter.PREFIX.length(), name.lastIndexOf(PluginStarter.ENABLED));
|
|
|
|
Object val = _settings.get(app + ".enabled");
|
|
|
|
props.setProperty(name, "" + (val != null));
|
|
|
|
}
|
|
|
|
PluginStarter.storePluginProperties(props);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Plugin configuration saved."));
|
2008-06-16 12:31:14 +00:00
|
|
|
}
|
2008-06-20 20:20:50 +00:00
|
|
|
|
2010-02-07 13:32:49 +00:00
|
|
|
/**
|
|
|
|
* Big hack for the moment, not using properties for directory and port
|
|
|
|
* Go through all the Jetty servers, find the one serving port 7657,
|
|
|
|
* requested and add the .war to that one
|
|
|
|
*/
|
2008-06-20 20:20:50 +00:00
|
|
|
private void startWebApp(String app) {
|
2011-12-23 00:56:48 +00:00
|
|
|
ContextHandlerCollection s = WebAppStarter.getConsoleServer();
|
2010-02-07 13:32:49 +00:00
|
|
|
if (s != null) {
|
2008-06-20 20:20:50 +00:00
|
|
|
try {
|
2009-06-15 15:32:27 +00:00
|
|
|
File path = new File(_context.getBaseDir(), "webapps");
|
|
|
|
path = new File(path, app + ".war");
|
2010-02-06 20:25:13 +00:00
|
|
|
WebAppStarter.startWebApp(_context, s, app, path.getAbsolutePath());
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNoticeNoEscape(_t("WebApp") + " <a href=\"/" + app + "/\">" + _t(app) + "</a> " + _t("started") + '.');
|
2010-02-11 21:41:54 +00:00
|
|
|
} catch (Throwable e) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Failed to start") + ' ' + _t(app) + " " + e + '.');
|
2010-02-11 21:41:54 +00:00
|
|
|
_log.error("Failed to start webapp " + app, e);
|
2008-06-20 20:20:50 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Failed to find server."));
|
2008-06-20 20:20:50 +00:00
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
|
|
|
|
private void installPlugin() {
|
2010-03-05 14:44:50 +00:00
|
|
|
String url = getJettyString("pluginURL");
|
2010-02-06 20:25:13 +00:00
|
|
|
if (url == null || url.length() <= 0) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("No plugin URL specified."));
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-10-21 17:14:54 +00:00
|
|
|
installPlugin(null, url);
|
2010-02-10 19:09:35 +00:00
|
|
|
}
|
|
|
|
|
2015-03-21 17:23:19 +00:00
|
|
|
/**
|
|
|
|
* @since 0.9.19
|
|
|
|
*/
|
|
|
|
private void installPluginFromFile() {
|
|
|
|
InputStream in = _requestWrapper.getInputStream("pluginFile");
|
|
|
|
// go to some trouble to verify it's an su3 or xpi2p file before
|
|
|
|
// passing it along, so we can display a good error message
|
|
|
|
byte[] su3Magic = DataHelper.getASCII(SU3File.MAGIC);
|
|
|
|
byte[] zipMagic = new byte[] { 0x50, 0x4b, 0x03, 0x04 };
|
|
|
|
byte[] magic = new byte[TrustedUpdate.HEADER_BYTES + zipMagic.length];
|
|
|
|
File tmp = null;
|
|
|
|
OutputStream out = null;
|
|
|
|
try {
|
|
|
|
// non-null but zero bytes if no file entered, don't know why
|
|
|
|
if (in == null || in.available() <= 0) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("You must enter a file"));
|
2015-03-21 17:23:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
DataHelper.read(in, magic);
|
|
|
|
boolean isSU3 = DataHelper.eq(magic, 0, su3Magic, 0, su3Magic.length);
|
|
|
|
if (!isSU3) {
|
|
|
|
if (!DataHelper.eq(magic, TrustedUpdate.HEADER_BYTES, zipMagic, 0, zipMagic.length)) {
|
|
|
|
String name = _requestWrapper.getFilename("pluginFile");
|
|
|
|
if (name == null)
|
|
|
|
name = "File";
|
|
|
|
throw new IOException(name + " is not an xpi2p or su3 plugin");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tmp = new File(_context.getTempDir(), "plugin-" + _context.random().nextInt() + (isSU3 ? ".su3" : ".xpi2p"));
|
|
|
|
out = new BufferedOutputStream(new SecureFileOutputStream(tmp));
|
|
|
|
out.write(magic);
|
|
|
|
byte buf[] = new byte[16*1024];
|
|
|
|
int read = 0;
|
|
|
|
while ( (read = in.read(buf)) != -1) {
|
|
|
|
out.write(buf, 0, read);
|
|
|
|
}
|
|
|
|
out.close();
|
|
|
|
String url = tmp.toURI().toString();
|
|
|
|
// threaded... TODO inline to get better result to UI?
|
|
|
|
installPlugin(null, url);
|
|
|
|
// above sleeps 1000, give it some more time?
|
|
|
|
// or check for complete?
|
|
|
|
ConsoleUpdateManager mgr = UpdateHandler.updateManager(_context);
|
|
|
|
if (mgr == null)
|
|
|
|
return;
|
2015-03-22 10:08:48 +00:00
|
|
|
for (int i = 0; i < 20; i++) {
|
2015-03-21 17:23:19 +00:00
|
|
|
if (!mgr.isUpdateInProgress(PLUGIN)) {
|
|
|
|
tmp.delete();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
try {
|
2015-03-22 10:08:48 +00:00
|
|
|
Thread.sleep(500);
|
2015-03-21 17:23:19 +00:00
|
|
|
} catch (InterruptedException ie) {}
|
|
|
|
}
|
|
|
|
String status = mgr.getStatus();
|
|
|
|
if (status != null && status.length() > 0)
|
|
|
|
addFormNoticeNoEscape(status);
|
|
|
|
} catch (IOException ioe) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Install from file failed") + " - " + ioe.getMessage());
|
2015-03-21 17:23:19 +00:00
|
|
|
} finally {
|
|
|
|
// it's really a ByteArrayInputStream but we'll play along...
|
|
|
|
if (in != null)
|
|
|
|
try { in.close(); } catch (IOException ioe) {}
|
|
|
|
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-10 19:09:35 +00:00
|
|
|
private void updatePlugin(String app) {
|
|
|
|
Properties props = PluginStarter.pluginProperties(_context, app);
|
2014-08-07 19:27:53 +00:00
|
|
|
String url = props.getProperty("updateURL.su3");
|
|
|
|
if (url == null)
|
|
|
|
url = props.getProperty("updateURL");
|
2010-02-10 19:09:35 +00:00
|
|
|
if (url == null) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("No update URL specified for {0}",app));
|
2010-02-10 19:09:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-10-21 17:14:54 +00:00
|
|
|
installPlugin(app, url);
|
2010-02-10 19:09:35 +00:00
|
|
|
}
|
|
|
|
|
2012-01-15 21:15:08 +00:00
|
|
|
/** @since 0.8.13 */
|
|
|
|
private void updateAllPlugins() {
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
if (NewsHelper.isAnyUpdateInProgress()) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Plugin or update download already in progress."));
|
2012-01-18 01:55:53 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-04-24 16:08:08 +00:00
|
|
|
if (!verifyProxy())
|
|
|
|
return;
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Updating all plugins"));
|
2012-01-15 21:15:08 +00:00
|
|
|
PluginStarter.updateAll(_context);
|
|
|
|
// So that update() will post a status to the summary bar before we reload
|
|
|
|
try {
|
|
|
|
Thread.sleep(1000);
|
|
|
|
} catch (InterruptedException ie) {}
|
|
|
|
}
|
|
|
|
|
2012-10-21 17:14:54 +00:00
|
|
|
/**
|
|
|
|
* @param app null for a new install
|
2015-04-24 16:08:08 +00:00
|
|
|
* @param url http: or file:
|
2012-10-21 17:14:54 +00:00
|
|
|
*/
|
|
|
|
private void installPlugin(String app, String url) {
|
2014-02-07 15:40:23 +00:00
|
|
|
ConsoleUpdateManager mgr = UpdateHandler.updateManager(_context);
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
if (mgr == null) {
|
|
|
|
addFormError("Update manager not registered, cannot install");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
if (mgr.isUpdateInProgress()) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Plugin or update download already in progress."));
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
URI uri;
|
|
|
|
try {
|
|
|
|
uri = new URI(url);
|
|
|
|
} catch (URISyntaxException use) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Bad URL {0}", url));
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-04-24 16:08:08 +00:00
|
|
|
if (!url.startsWith("file:")) {
|
|
|
|
if (!verifyProxy())
|
|
|
|
return;
|
|
|
|
}
|
2015-03-21 17:23:19 +00:00
|
|
|
if (mgr.installPlugin(app, uri)) {
|
|
|
|
if (url.startsWith("file:"))
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Installing plugin from {0}", uri.getPath()));
|
2015-03-21 17:23:19 +00:00
|
|
|
else
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Downloading plugin from {0}", url));
|
2015-03-21 17:23:19 +00:00
|
|
|
} else {
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
addFormError("Cannot install, check logs");
|
2015-03-21 17:23:19 +00:00
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
// So that update() will post a status to the summary bar before we reload
|
|
|
|
try {
|
|
|
|
Thread.sleep(1000);
|
|
|
|
} catch (InterruptedException ie) {}
|
|
|
|
}
|
2010-02-10 19:09:35 +00:00
|
|
|
|
|
|
|
private void checkPlugin(String app) {
|
2014-02-07 15:40:23 +00:00
|
|
|
ConsoleUpdateManager mgr = UpdateHandler.updateManager(_context);
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
if (mgr == null) {
|
|
|
|
addFormError("Update manager not registered, cannot check");
|
2010-02-10 19:09:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-04-24 16:08:08 +00:00
|
|
|
if (!verifyProxy())
|
|
|
|
return;
|
Big refactor of the router console update subsystem, in preparation for
implementing out-of-console updaters like i2psnark.
- Add new update interfaces in net.i2p.update
- All update implementations moved to routerconsole update/
- Implement an UpdateManager that registers with the RouterContext
- UpdateManager handles multiple types of things to update
(router, plugins, news, ...) and methods of updating (HTTP, ...)
- UpdateManager maintains list of installed, downloaded, and available versions of everything
- Define Updaters that can check for a new version and/or download an item
- Individual Updaters register with the UpdateManager obtained from
I2PAppContext, identifying the type of update item and
update method they can handle.
- Updaters need only core libs, no router.jar or routerconsole access required.
- All checks and updates are initiated via the UpdateManager.
- All status on checks and updates in-progress or completed are
obtained from the UpdateManager. No more use of System properties
to broadcast update state.
- All update and checker tasks are intantiated on demand and threaded;
no more static references left over.
- Split out the Runners and Checkers from the Handlers and make the inheritance more sane.
- No more permanent NewsFetcher thread; run on the SimpleScheduler queue
and thread a checker task only to fetch the news.
- No more static NewsFetcher instance in routerconsole.
All helper methods that are still required are moved to NewsHelper.
The UpdateManager implements the policy for when to check and download.
All requests go through the UpdateManager.
For each update type, there's several parts:
- The xxxUpdateHandler implements the Updater
- The xxxUpdateChecker implements the UpdateTask for checking
- The xxxUpdateRunner implements the UpdateTask for downloading
New and moved classes:
web/ update/
---- -------
new ConsoleUpdateManager.java
new PluginUpdateChecker.java from PluginUpdateChecker
PluginUpdateChecker -> PluginUpdateHandler.java
PluginUpdateHandler.java -> PluginUpdateRunner
new UnsignedUpdateHandler.java
UnsignedUpdateHandler -> UnsignedUpdateRunner.java
new UnsignedUpdateChecker from NewsFetcher
UpdateHandler.java remains
new UpdateHandler.java
new UpdateRunner.java from UpdateHandler
move NewsHandler from NewsFetcher
new NewsFetcher
new NewsTimerTask
new DummyHandler
Initial checkin. Unfinished, untested, unpolished.
2012-06-18 22:09:45 +00:00
|
|
|
mgr.check(PLUGIN, app);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Checking plugin {0} for updates", app));
|
2010-02-10 19:09:35 +00:00
|
|
|
// So that update() will post a status to the summary bar before we reload
|
|
|
|
try {
|
|
|
|
Thread.sleep(1000);
|
|
|
|
} catch (InterruptedException ie) {}
|
|
|
|
}
|
|
|
|
|
2015-04-24 16:08:08 +00:00
|
|
|
/**
|
|
|
|
* Plugin checks, updates, and installs are always proxied.
|
|
|
|
* See if the proxy tunnel is available, unless we're configured
|
|
|
|
* to use something else (probably not).
|
|
|
|
* Outputs form error if returning false.
|
|
|
|
*
|
|
|
|
* @return true if available
|
|
|
|
* @since 0.9.20
|
|
|
|
*/
|
|
|
|
private boolean verifyProxy() {
|
|
|
|
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
|
|
|
|
int proxyPort = ConfigUpdateHandler.proxyPort(_context);
|
|
|
|
boolean rv = !
|
|
|
|
(proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
|
|
|
|
proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
|
|
|
|
_context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0);
|
|
|
|
if (!rv)
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("HTTP client proxy tunnel must be running"));
|
2015-04-24 16:08:08 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2010-02-17 18:12:46 +00:00
|
|
|
private void startPlugin(String app) {
|
|
|
|
try {
|
|
|
|
PluginStarter.startPlugin(_context, app);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Started plugin {0}", app));
|
2010-02-17 18:12:46 +00:00
|
|
|
} catch (Throwable e) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Error starting plugin {0}", app) + ": " + e);
|
2010-02-17 18:12:46 +00:00
|
|
|
_log.error("Error starting plugin " + app, e);
|
|
|
|
}
|
|
|
|
}
|
2010-12-24 16:52:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle interface form
|
|
|
|
* @since 0.8.3
|
|
|
|
*/
|
|
|
|
private void saveInterfaceChanges() {
|
2013-11-21 11:31:50 +00:00
|
|
|
Map<String, String> changes = new HashMap<String, String>();
|
2010-12-24 16:52:23 +00:00
|
|
|
String port = getJettyString("port");
|
|
|
|
if (port != null)
|
2012-01-18 01:55:53 +00:00
|
|
|
changes.put(ClientManagerFacadeImpl.PROP_CLIENT_PORT, port);
|
2010-12-24 16:52:23 +00:00
|
|
|
String intfc = getJettyString("interface");
|
|
|
|
if (intfc != null)
|
2012-01-18 01:55:53 +00:00
|
|
|
changes.put(ClientManagerFacadeImpl.PROP_CLIENT_HOST, intfc);
|
2010-12-24 16:52:23 +00:00
|
|
|
String user = getJettyString("user");
|
2014-08-03 13:58:51 +00:00
|
|
|
String pw = getJettyString("nofilter_pw");
|
2012-10-13 22:42:26 +00:00
|
|
|
if (user != null && pw != null && user.length() > 0 && pw.length() > 0) {
|
|
|
|
ConsolePasswordManager mgr = new ConsolePasswordManager(_context);
|
|
|
|
mgr.saveHash(ConfigClientsHelper.PROP_AUTH, user, pw);
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Added user {0}", user));
|
2012-10-13 22:42:26 +00:00
|
|
|
}
|
2010-12-24 16:52:23 +00:00
|
|
|
String mode = getJettyString("mode");
|
|
|
|
boolean disabled = "0".equals(mode);
|
|
|
|
boolean ssl = "2".equals(mode);
|
2012-01-18 01:55:53 +00:00
|
|
|
changes.put(ConfigClientsHelper.PROP_DISABLE_EXTERNAL,
|
2010-12-24 16:52:23 +00:00
|
|
|
Boolean.toString(disabled));
|
2012-01-18 01:55:53 +00:00
|
|
|
changes.put(ConfigClientsHelper.PROP_ENABLE_SSL,
|
2010-12-24 16:52:23 +00:00
|
|
|
Boolean.toString(ssl));
|
2012-01-18 01:55:53 +00:00
|
|
|
changes.put(ConfigClientsHelper.PROP_AUTH,
|
2010-12-24 16:52:23 +00:00
|
|
|
Boolean.toString((_settings.get("auth") != null)));
|
|
|
|
boolean all = "0.0.0.0".equals(intfc) || "0:0:0:0:0:0:0:0".equals(intfc) ||
|
|
|
|
"::".equals(intfc);
|
2012-01-18 01:55:53 +00:00
|
|
|
changes.put(ConfigClientsHelper.BIND_ALL_INTERFACES, Boolean.toString(all));
|
2012-10-13 21:20:16 +00:00
|
|
|
if (_context.router().saveConfig(changes, null)) {
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormNotice(_t("Interface configuration saved"));
|
|
|
|
addFormNotice(_t("Restart required to take effect"));
|
2012-10-13 21:20:16 +00:00
|
|
|
} else
|
2015-09-25 19:55:36 +00:00
|
|
|
addFormError(_t("Error saving the configuration (applied but not saved) - please see the error logs"));
|
2010-12-24 16:52:23 +00:00
|
|
|
}
|
2008-06-16 12:31:14 +00:00
|
|
|
}
|