forked from I2P_Developers/i2p.i2p
* Plugins:
- Hook up update/delete/check/save buttons - Implement delete - Hide unless router.enablePlugins=true
This commit is contained in:
@ -35,6 +35,10 @@ public class ConfigClientsHandler extends FormHandler {
|
|||||||
saveWebAppChanges();
|
saveWebAppChanges();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (_action.equals(_("Save Plugin Configuration"))) {
|
||||||
|
savePluginChanges();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_action.equals(_("Install Plugin"))) {
|
if (_action.equals(_("Install Plugin"))) {
|
||||||
installPlugin();
|
installPlugin();
|
||||||
return;
|
return;
|
||||||
@ -60,10 +64,42 @@ public class ConfigClientsHandler extends FormHandler {
|
|||||||
try {
|
try {
|
||||||
appnum = Integer.parseInt(app);
|
appnum = Integer.parseInt(app);
|
||||||
} catch (NumberFormatException nfe) {}
|
} catch (NumberFormatException nfe) {}
|
||||||
if (appnum >= 0)
|
if (appnum >= 0) {
|
||||||
deleteClient(appnum);
|
deleteClient(appnum);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
PluginStarter.stopPlugin(_context, app);
|
||||||
|
} catch (Exception e) {}
|
||||||
|
PluginStarter.deletePlugin(_context, app);
|
||||||
|
addFormNotice(_("Deleted plugin {0}", app));
|
||||||
|
}
|
||||||
return;
|
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)
|
// label (IE)
|
||||||
String xStart = _("Start");
|
String xStart = _("Start");
|
||||||
if (_action.toLowerCase().startsWith(xStart + "<span class=hide> ") &&
|
if (_action.toLowerCase().startsWith(xStart + "<span class=hide> ") &&
|
||||||
@ -81,6 +117,7 @@ public class ConfigClientsHandler extends FormHandler {
|
|||||||
} else {
|
} else {
|
||||||
addFormError(_("Unsupported") + ' ' + _action + '.');
|
addFormError(_("Unsupported") + ' ' + _action + '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSettings(Map settings) { _settings = new HashMap(settings); }
|
public void setSettings(Map settings) { _settings = new HashMap(settings); }
|
||||||
@ -175,7 +212,23 @@ public class ConfigClientsHandler extends FormHandler {
|
|||||||
props.setProperty(name, "" + (val != null));
|
props.setProperty(name, "" + (val != null));
|
||||||
}
|
}
|
||||||
RouterConsoleRunner.storeWebAppProperties(props);
|
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."));
|
addFormError(_("No plugin URL specified."));
|
||||||
return;
|
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))) {
|
if ("true".equals(System.getProperty(UpdateHandler.PROP_UPDATE_IN_PROGRESS))) {
|
||||||
addFormError(_("Plugin or update download already in progress."));
|
addFormError(_("Plugin or update download already in progress."));
|
||||||
return;
|
return;
|
||||||
@ -221,4 +288,23 @@ public class ConfigClientsHandler extends FormHandler {
|
|||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
} catch (InterruptedException ie) {}
|
} 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();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean showPlugins() {
|
||||||
|
return PluginStarter.pluginsEnabled(_context);
|
||||||
|
}
|
||||||
|
|
||||||
public String getForm3() {
|
public String getForm3() {
|
||||||
StringBuilder buf = new StringBuilder(1024);
|
StringBuilder buf = new StringBuilder(1024);
|
||||||
buf.append("<table>\n");
|
buf.append("<table>\n");
|
||||||
@ -170,7 +174,7 @@ public class ConfigClientsHelper extends HelperBase {
|
|||||||
if (ro)
|
if (ro)
|
||||||
buf.append("disabled=\"true\" ");
|
buf.append("disabled=\"true\" ");
|
||||||
}
|
}
|
||||||
buf.append("/></td><td align=\"center\" width=\"15%\">");
|
buf.append("></td><td align=\"center\" width=\"15%\">");
|
||||||
if ((!enabled) && !edit) {
|
if ((!enabled) && !edit) {
|
||||||
buf.append("<button type=\"submit\" name=\"action\" value=\"Start ").append(index).append("\" >" + _("Start") + "<span class=hide> ").append(index).append("</span></button>");
|
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.RouterContext;
|
||||||
import net.i2p.router.startup.ClientAppConfig;
|
import net.i2p.router.startup.ClientAppConfig;
|
||||||
import net.i2p.router.startup.LoadClientAppsJob;
|
import net.i2p.router.startup.LoadClientAppsJob;
|
||||||
|
import net.i2p.util.FileUtil;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.Translate;
|
import net.i2p.util.Translate;
|
||||||
|
|
||||||
@ -41,6 +42,10 @@ public class PluginStarter implements Runnable {
|
|||||||
_context = ctx;
|
_context = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean pluginsEnabled(I2PAppContext ctx) {
|
||||||
|
return Boolean.valueOf(ctx.getProperty("router.enablePlugins")).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
startPlugins(_context);
|
startPlugins(_context);
|
||||||
}
|
}
|
||||||
@ -50,9 +55,9 @@ public class PluginStarter implements Runnable {
|
|||||||
Properties props = pluginProperties();
|
Properties props = pluginProperties();
|
||||||
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
||||||
String name = (String)iter.next();
|
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()) {
|
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 {
|
try {
|
||||||
if (!startPlugin(ctx, app))
|
if (!startPlugin(ctx, app))
|
||||||
log.error("Failed to start plugin: " + app);
|
log.error("Failed to start plugin: " + app);
|
||||||
@ -188,7 +193,6 @@ public class PluginStarter implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// remove summary bar link
|
// remove summary bar link
|
||||||
Properties props = pluginProperties(ctx, appName);
|
Properties props = pluginProperties(ctx, appName);
|
||||||
String name = ConfigClientsHelper.stripHTML(props, "consoleLinkName_" + Messages.getLanguage(ctx));
|
String name = ConfigClientsHelper.stripHTML(props, "consoleLinkName_" + Messages.getLanguage(ctx));
|
||||||
@ -200,6 +204,25 @@ public class PluginStarter implements Runnable {
|
|||||||
return true;
|
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 */
|
/** plugin.config */
|
||||||
public static Properties pluginProperties(I2PAppContext ctx, String appName) {
|
public static Properties pluginProperties(I2PAppContext ctx, String appName) {
|
||||||
File cfgFile = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName + '/' + "plugin.config");
|
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 oldVersion = props.getProperty("version");
|
||||||
String xpi2pURL = props.getProperty("updateURL");
|
String xpi2pURL = props.getProperty("updateURL");
|
||||||
if (oldVersion == null || xpi2pURL == null) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pluginUpdateCheckerRunner == null)
|
if (_pluginUpdateCheckerRunner == null)
|
||||||
_pluginUpdateCheckerRunner = new PluginUpdateCheckerRunner(xpi2pURL);
|
_pluginUpdateCheckerRunner = new PluginUpdateCheckerRunner();
|
||||||
if (_pluginUpdateCheckerRunner.isRunning())
|
if (_pluginUpdateCheckerRunner.isRunning())
|
||||||
return;
|
return;
|
||||||
|
_xpi2pURL = xpi2pURL;
|
||||||
_appName = appName;
|
_appName = appName;
|
||||||
_oldVersion = oldVersion;
|
_oldVersion = oldVersion;
|
||||||
System.setProperty(PROP_UPDATE_IN_PROGRESS, "true");
|
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 {
|
public class PluginUpdateCheckerRunner extends UpdateRunner implements Runnable, EepGet.StatusListener {
|
||||||
String _updateURL;
|
|
||||||
ByteArrayOutputStream _baos;
|
ByteArrayOutputStream _baos;
|
||||||
|
|
||||||
public PluginUpdateCheckerRunner(String url) {
|
public PluginUpdateCheckerRunner() {
|
||||||
super();
|
super();
|
||||||
_updateURL = url;
|
|
||||||
_baos = new ByteArrayOutputStream(TrustedUpdate.HEADER_BYTES);
|
_baos = new ByteArrayOutputStream(TrustedUpdate.HEADER_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void update() {
|
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
|
// use the same settings as for updater
|
||||||
boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
|
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);
|
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 {
|
public class PluginUpdateRunner extends UpdateRunner implements Runnable, EepGet.StatusListener {
|
||||||
String _updateURL;
|
|
||||||
|
|
||||||
public PluginUpdateRunner(String url) {
|
public PluginUpdateRunner(String url) {
|
||||||
super();
|
super();
|
||||||
_updateURL = url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -287,7 +285,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
|||||||
if (oldVersion == null ||
|
if (oldVersion == null ||
|
||||||
(new VersionComparator()).compare(oldVersion, version) >= 0) {
|
(new VersionComparator()).compare(oldVersion, version) >= 0) {
|
||||||
to.delete();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
minVersion = ConfigClientsHelper.stripHTML(props, "min-installed-version");
|
minVersion = ConfigClientsHelper.stripHTML(props, "min-installed-version");
|
||||||
|
@ -189,8 +189,10 @@ public class RouterConsoleRunner {
|
|||||||
|
|
||||||
List<RouterContext> contexts = RouterContext.listContexts();
|
List<RouterContext> contexts = RouterContext.listContexts();
|
||||||
if (contexts != null) {
|
if (contexts != null) {
|
||||||
t = new I2PAppThread(new PluginStarter(contexts.get(0)), "PluginStarter", true);
|
if (PluginStarter.pluginsEnabled(contexts.get(0))) {
|
||||||
t.start();
|
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>
|
<i><%=intl._("All changes require restart to take effect.")%></i>
|
||||||
</p><hr><div class="formaction">
|
</p><hr><div class="formaction">
|
||||||
<input type="submit" name="action" value="<%=intl._("Save WebApp Configuration")%>" />
|
<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.")%>
|
<%=intl._("The plugins listed below are started by the webConsole client.")%>
|
||||||
</p><div class="wideload"><p>
|
</p><div class="wideload"><p>
|
||||||
<jsp:getProperty name="clientshelper" property="form3" />
|
<jsp:getProperty name="clientshelper" property="form3" />
|
||||||
</p><hr><div class="formaction">
|
</p><hr><div class="formaction">
|
||||||
<input type="submit" name="action" value="<%=intl._("Save Plugin Configuration")%>" />
|
<input type="submit" name="action" value="<%=intl._("Save Plugin Configuration")%>" />
|
||||||
</div></div><h3><a name="plugin"></a><%=intl._("Plugin Installation")%></h3><p>
|
</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>
|
</p><div class="wideload"><p>
|
||||||
<input type="text" size="60" name="pluginURL" >
|
<input type="text" size="60" name="pluginURL" >
|
||||||
</p><hr><div class="formaction">
|
</p><hr><div class="formaction">
|
||||||
<input type="submit" name="action" value="<%=intl._("Install Plugin")%>" />
|
<input type="submit" name="action" value="<%=intl._("Install Plugin")%>" />
|
||||||
</div></div></form></div></div></body></html>
|
</div></div>
|
||||||
|
<% } %>
|
||||||
|
</form></div></div></body></html>
|
||||||
|
Reference in New Issue
Block a user