From 949aea951e4fada832750a16ee26f28c2d6f2f41 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 10 Feb 2010 19:09:35 +0000 Subject: [PATCH] * Plugins: - Hook up update/delete/check/save buttons - Implement delete - Hide unless router.enablePlugins=true --- .../i2p/router/web/ConfigClientsHandler.java | 90 ++++++++++++++++++- .../i2p/router/web/ConfigClientsHelper.java | 6 +- .../src/net/i2p/router/web/PluginStarter.java | 29 +++++- .../i2p/router/web/PluginUpdateChecker.java | 11 ++- .../i2p/router/web/PluginUpdateHandler.java | 4 +- .../i2p/router/web/RouterConsoleRunner.java | 6 +- apps/routerconsole/jsp/configclients.jsp | 10 ++- 7 files changed, 136 insertions(+), 20 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java index 6d0a4faa9f..1f433b60f4 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java @@ -35,6 +35,10 @@ public class ConfigClientsHandler extends FormHandler { saveWebAppChanges(); return; } + if (_action.equals(_("Save Plugin Configuration"))) { + savePluginChanges(); + return; + } if (_action.equals(_("Install Plugin"))) { installPlugin(); return; @@ -60,10 +64,42 @@ public class ConfigClientsHandler extends FormHandler { try { appnum = Integer.parseInt(app); } catch (NumberFormatException nfe) {} - if (appnum >= 0) + if (appnum >= 0) { deleteClient(appnum); + } else { + try { + PluginStarter.stopPlugin(_context, app); + } catch (Exception e) {} + PluginStarter.deletePlugin(_context, app); + addFormNotice(_("Deleted plugin {0}", app)); + } return; } + + // value + if (_action.startsWith("Stop ")) { + String app = _action.substring(5); + try { + PluginStarter.stopPlugin(_context, app); + } catch (Exception e) {} + addFormNotice(_("Stopped plugin {0}", app)); + return; + } + + // value + if (_action.startsWith("Update ")) { + String app = _action.substring(7); + updatePlugin(app); + return; + } + + // value + if (_action.startsWith("Check ")) { + String app = _action.substring(6); + checkPlugin(app); + return; + } + // label (IE) String xStart = _("Start"); if (_action.toLowerCase().startsWith(xStart + "<span class=hide> ") && @@ -81,6 +117,7 @@ public class ConfigClientsHandler extends FormHandler { } else { addFormError(_("Unsupported") + ' ' + _action + '.'); } + } public void setSettings(Map settings) { _settings = new HashMap(settings); } @@ -175,7 +212,23 @@ public class ConfigClientsHandler extends FormHandler { props.setProperty(name, "" + (val != null)); } RouterConsoleRunner.storeWebAppProperties(props); - addFormNotice(_("WebApp configuration saved successfully - restart required to take effect.")); + addFormNotice(_("WebApp configuration saved.")); + } + + private void savePluginChanges() { + Properties props = PluginStarter.pluginProperties(); + Set keys = props.keySet(); + int cur = 0; + for (Iterator iter = keys.iterator(); iter.hasNext(); ) { + String name = (String)iter.next(); + 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); + addFormNotice(_("Plugin configuration saved.")); } /** @@ -205,6 +258,20 @@ public class ConfigClientsHandler extends FormHandler { addFormError(_("No plugin URL specified.")); return; } + installPlugin(url); + } + + private void updatePlugin(String app) { + Properties props = PluginStarter.pluginProperties(_context, app); + String url = props.getProperty("updateURL"); + if (url == null) { + addFormError(_("No update URL specified for {0}",app)); + return; + } + installPlugin(url); + } + + private void installPlugin(String url) { if ("true".equals(System.getProperty(UpdateHandler.PROP_UPDATE_IN_PROGRESS))) { addFormError(_("Plugin or update download already in progress.")); return; @@ -221,4 +288,23 @@ public class ConfigClientsHandler extends FormHandler { Thread.sleep(1000); } catch (InterruptedException ie) {} } + + private void checkPlugin(String app) { + if ("true".equals(System.getProperty(UpdateHandler.PROP_UPDATE_IN_PROGRESS))) { + addFormError(_("Plugin or update download already in progress.")); + return; + } + PluginUpdateChecker puc = PluginUpdateChecker.getInstance(_context); + if (puc.isRunning()) { + addFormError(_("Plugin or update download already in progress.")); + return; + } + puc.update(app); + addFormNotice(_("Checking plugin {0} for updates", app)); + // So that update() will post a status to the summary bar before we reload + try { + Thread.sleep(1000); + } catch (InterruptedException ie) {} + } + } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java index 2f38774591..d0daac4b2e 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java @@ -70,6 +70,10 @@ public class ConfigClientsHelper extends HelperBase { return buf.toString(); } + public boolean showPlugins() { + return PluginStarter.pluginsEnabled(_context); + } + public String getForm3() { StringBuilder buf = new StringBuilder(1024); buf.append("<table>\n"); @@ -170,7 +174,7 @@ public class ConfigClientsHelper extends HelperBase { if (ro) buf.append("disabled=\"true\" "); } - buf.append("/></td><td align=\"center\" width=\"15%\">"); + buf.append("></td><td align=\"center\" width=\"15%\">"); if ((!enabled) && !edit) { buf.append("<button type=\"submit\" name=\"action\" value=\"Start ").append(index).append("\" >" + _("Start") + "<span class=hide> ").append(index).append("</span></button>"); } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java index d24e28d00d..5b92ec0c3b 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java @@ -19,6 +19,7 @@ import net.i2p.data.DataHelper; import net.i2p.router.RouterContext; import net.i2p.router.startup.ClientAppConfig; import net.i2p.router.startup.LoadClientAppsJob; +import net.i2p.util.FileUtil; import net.i2p.util.Log; import net.i2p.util.Translate; @@ -41,6 +42,10 @@ public class PluginStarter implements Runnable { _context = ctx; } + static boolean pluginsEnabled(I2PAppContext ctx) { + return Boolean.valueOf(ctx.getProperty("router.enablePlugins")).booleanValue(); + } + public void run() { startPlugins(_context); } @@ -50,9 +55,9 @@ public class PluginStarter implements Runnable { Properties props = pluginProperties(); for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) { String name = (String)iter.next(); - if (name.startsWith(PluginStarter.PREFIX) && name.endsWith(PluginStarter.ENABLED)) { + if (name.startsWith(PREFIX) && name.endsWith(ENABLED)) { if (Boolean.valueOf(props.getProperty(name)).booleanValue()) { - String app = name.substring(PluginStarter.PREFIX.length(), name.lastIndexOf(PluginStarter.ENABLED)); + String app = name.substring(PREFIX.length(), name.lastIndexOf(ENABLED)); try { if (!startPlugin(ctx, app)) log.error("Failed to start plugin: " + app); @@ -188,7 +193,6 @@ public class PluginStarter implements Runnable { } } - // remove summary bar link Properties props = pluginProperties(ctx, appName); String name = ConfigClientsHelper.stripHTML(props, "consoleLinkName_" + Messages.getLanguage(ctx)); @@ -200,6 +204,25 @@ public class PluginStarter implements Runnable { return true; } + /** @return true on success - call stopPlugin() first */ + static boolean deletePlugin(RouterContext ctx, String appName) { + Log log = ctx.logManager().getLog(PluginStarter.class); + File pluginDir = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName); + if ((!pluginDir.exists()) || (!pluginDir.isDirectory())) { + log.error("Cannot stop nonexistent plugin: " + appName); + return false; + } + FileUtil.rmdir(pluginDir, false); + Properties props = pluginProperties(); + for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) { + String name = (String)iter.next(); + if (name.startsWith(PREFIX + appName)) + iter.remove(); + } + storePluginProperties(props); + return true; + } + /** plugin.config */ public static Properties pluginProperties(I2PAppContext ctx, String appName) { File cfgFile = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName + '/' + "plugin.config"); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateChecker.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateChecker.java index e19e23d91f..8b5d2c0147 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateChecker.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateChecker.java @@ -62,14 +62,15 @@ public class PluginUpdateChecker extends UpdateHandler { String oldVersion = props.getProperty("version"); String xpi2pURL = props.getProperty("updateURL"); if (oldVersion == null || xpi2pURL == null) { - updateStatus("<b>" + _("Cannot update, plugin {0} is not installed", appName) + "</b>"); + updateStatus("<b>" + _("Cannot check, plugin {0} is not installed", appName) + "</b>"); return; } if (_pluginUpdateCheckerRunner == null) - _pluginUpdateCheckerRunner = new PluginUpdateCheckerRunner(xpi2pURL); + _pluginUpdateCheckerRunner = new PluginUpdateCheckerRunner(); if (_pluginUpdateCheckerRunner.isRunning()) return; + _xpi2pURL = xpi2pURL; _appName = appName; _oldVersion = oldVersion; System.setProperty(PROP_UPDATE_IN_PROGRESS, "true"); @@ -89,18 +90,16 @@ public class PluginUpdateChecker extends UpdateHandler { } public class PluginUpdateCheckerRunner extends UpdateRunner implements Runnable, EepGet.StatusListener { - String _updateURL; ByteArrayOutputStream _baos; - public PluginUpdateCheckerRunner(String url) { + public PluginUpdateCheckerRunner() { super(); - _updateURL = url; _baos = new ByteArrayOutputStream(TrustedUpdate.HEADER_BYTES); } @Override protected void update() { - updateStatus("<b>" + _("Checking plugin {0} for updates", _appName) + "</b>"); + updateStatus("<b>" + _("Checking for update of plugin {0}", _appName) + "</b>"); // use the same settings as for updater boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue(); String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateHandler.java index 60df3f89ec..8e0ba021f6 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginUpdateHandler.java @@ -90,11 +90,9 @@ public class PluginUpdateHandler extends UpdateHandler { } public class PluginUpdateRunner extends UpdateRunner implements Runnable, EepGet.StatusListener { - String _updateURL; public PluginUpdateRunner(String url) { super(); - _updateURL = url; } @Override @@ -287,7 +285,7 @@ public class PluginUpdateHandler extends UpdateHandler { if (oldVersion == null || (new VersionComparator()).compare(oldVersion, version) >= 0) { to.delete(); - updateStatus("<b>" + _("New plugin version {0} is not newer than installed plugin", version) + "</b>"); + updateStatus("<b>" + _("Downloaded plugin version {0} is not newer than installed plugin", version) + "</b>"); return; } minVersion = ConfigClientsHelper.stripHTML(props, "min-installed-version"); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java index 07d3c2ed75..f4f7bd79e0 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java @@ -189,8 +189,10 @@ public class RouterConsoleRunner { List<RouterContext> contexts = RouterContext.listContexts(); if (contexts != null) { - t = new I2PAppThread(new PluginStarter(contexts.get(0)), "PluginStarter", true); - t.start(); + if (PluginStarter.pluginsEnabled(contexts.get(0))) { + t = new I2PAppThread(new PluginStarter(contexts.get(0)), "PluginStarter", true); + t.start(); + } } } diff --git a/apps/routerconsole/jsp/configclients.jsp b/apps/routerconsole/jsp/configclients.jsp index 6d52901b8b..4bb17007c6 100644 --- a/apps/routerconsole/jsp/configclients.jsp +++ b/apps/routerconsole/jsp/configclients.jsp @@ -54,16 +54,20 @@ button span.hide{ <i><%=intl._("All changes require restart to take effect.")%></i> </p><hr><div class="formaction"> <input type="submit" name="action" value="<%=intl._("Save WebApp Configuration")%>" /> -</div></div><h3><a name="webapp"></a><%=intl._("Plugin Configuration")%></h3><p> +</div></div> +<% if (clientshelper.showPlugins()) { %> +<h3><a name="webapp"></a><%=intl._("Plugin Configuration")%></h3><p> <%=intl._("The plugins listed below are started by the webConsole client.")%> </p><div class="wideload"><p> <jsp:getProperty name="clientshelper" property="form3" /> </p><hr><div class="formaction"> <input type="submit" name="action" value="<%=intl._("Save Plugin Configuration")%>" /> </div></div><h3><a name="plugin"></a><%=intl._("Plugin Installation")%></h3><p> - <%=intl._("To install a plugin, enter the URL to download the plugin from:")%> + <%=intl._("To install a plugin, enter the download URL:")%> </p><div class="wideload"><p> <input type="text" size="60" name="pluginURL" > </p><hr><div class="formaction"> <input type="submit" name="action" value="<%=intl._("Install Plugin")%>" /> - </div></div></form></div></div></body></html> + </div></div> +<% } %> +</form></div></div></body></html> -- GitLab