I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 949aea95 authored by zzz's avatar zzz
Browse files

* Plugins:

      - Hook up update/delete/check/save buttons
      - Implement delete
      - Hide unless router.enablePlugins=true
parent cfc49ab2
No related branches found
No related tags found
No related merge requests found
......@@ -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) {}
}
}
......@@ -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>");
}
......
......@@ -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");
......
......@@ -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);
......
......@@ -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");
......
......@@ -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();
}
}
}
......
......@@ -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>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment