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
|
|
|
package net.i2p.router.update;
|
2010-02-06 20:25:13 +00:00
|
|
|
|
|
|
|
import java.io.File;
|
2014-08-07 18:45:04 +00:00
|
|
|
import java.io.FileInputStream;
|
2010-02-06 20:25:13 +00:00
|
|
|
import java.io.IOException;
|
2013-01-01 00:02:18 +00:00
|
|
|
import java.lang.IllegalArgumentException;
|
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.util.List;
|
2010-02-10 15:35:00 +00:00
|
|
|
import java.util.Map;
|
2010-02-06 20:25:13 +00:00
|
|
|
import java.util.Properties;
|
|
|
|
|
|
|
|
import net.i2p.CoreVersion;
|
2014-08-07 18:45:04 +00:00
|
|
|
import net.i2p.crypto.SU3File;
|
2010-02-06 20:25:13 +00:00
|
|
|
import net.i2p.crypto.TrustedUpdate;
|
2014-08-05 21:23:48 +00:00
|
|
|
import net.i2p.data.DataFormatException;
|
2010-02-06 20:25:13 +00:00
|
|
|
import net.i2p.data.DataHelper;
|
2014-08-05 21:23:48 +00:00
|
|
|
import net.i2p.data.SigningPublicKey;
|
2010-02-06 20:25:13 +00:00
|
|
|
import net.i2p.router.RouterContext;
|
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.web.ConfigUpdateHandler;
|
|
|
|
import net.i2p.router.web.Messages;
|
|
|
|
import net.i2p.router.web.PluginStarter;
|
2017-12-01 14:07:29 +00:00
|
|
|
import net.i2p.router.web.RouterConsoleRunner;
|
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.update.*;
|
2010-02-06 20:25:13 +00:00
|
|
|
import net.i2p.util.EepGet;
|
|
|
|
import net.i2p.util.FileUtil;
|
2013-07-03 17:12:32 +00:00
|
|
|
import net.i2p.util.Log;
|
2010-02-06 20:25:13 +00:00
|
|
|
import net.i2p.util.OrderedProperties;
|
2015-04-24 16:08:08 +00:00
|
|
|
import net.i2p.util.PortMapper;
|
2010-07-06 15:22:48 +00:00
|
|
|
import net.i2p.util.SecureDirectory;
|
2012-03-13 09:49:15 +00:00
|
|
|
import net.i2p.util.SecureFile;
|
2018-09-23 15:11:16 +00:00
|
|
|
import net.i2p.util.SystemVersion;
|
2010-02-06 20:25:13 +00:00
|
|
|
import net.i2p.util.VersionComparator;
|
|
|
|
|
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
|
|
|
|
2010-02-06 20:25:13 +00:00
|
|
|
/**
|
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
|
|
|
* Check for an updated version of a plugin.
|
2010-02-06 20:25:13 +00:00
|
|
|
* A plugin is a standard .sud file with a 40-byte signature,
|
2010-02-07 13:32:49 +00:00
|
|
|
* a 16-byte version, and a .zip file.
|
2010-02-06 20:25:13 +00:00
|
|
|
*
|
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
|
|
|
* So we get the current version and update URL for the installed plugin,
|
|
|
|
* then fetch the first 56 bytes of the URL, extract the version,
|
|
|
|
* and compare.
|
|
|
|
*
|
2013-01-01 00:02:18 +00:00
|
|
|
* uri list must not be empty.
|
|
|
|
*
|
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
|
|
|
* Moved from web/ and turned into an UpdateTask.
|
2010-02-06 20:25:13 +00:00
|
|
|
*
|
2012-10-17 22:24:15 +00:00
|
|
|
* @since 0.9.4 moved from PluginUpdateHandler
|
2010-02-06 20:25:13 +00:00
|
|
|
*/
|
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
|
|
|
class PluginUpdateRunner extends UpdateRunner {
|
|
|
|
|
|
|
|
private String _appName;
|
|
|
|
private final String _oldVersion;
|
|
|
|
private final URI _uri;
|
|
|
|
private final String _xpi2pURL;
|
|
|
|
private boolean _updated;
|
2012-10-23 02:34:24 +00:00
|
|
|
private String _errMsg = "";
|
2012-01-23 17:53:59 +00:00
|
|
|
|
2010-02-06 20:25:13 +00:00
|
|
|
private static final String XPI2P = "app.xpi2p";
|
|
|
|
private static final String ZIP = XPI2P + ".zip";
|
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
|
|
|
public static final String PLUGIN_DIR = PluginStarter.PLUGIN_DIR;
|
2014-08-03 13:58:51 +00:00
|
|
|
private static final String PROP_ALLOW_NEW_KEYS = "routerconsole.allowUntrustedPlugins";
|
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
|
|
|
|
2012-10-19 20:26:08 +00:00
|
|
|
public PluginUpdateRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris,
|
2013-01-01 00:02:18 +00:00
|
|
|
String appName, String oldVersion ) {
|
2013-09-22 18:03:56 +00:00
|
|
|
super(ctx, mgr, UpdateType.PLUGIN, uris);
|
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 (uris.isEmpty())
|
2013-01-01 00:02:18 +00:00
|
|
|
throw new IllegalArgumentException("uri cannot be empty");
|
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
|
|
|
else
|
|
|
|
_uri = uris.get(0);
|
|
|
|
_xpi2pURL = _uri.toString();
|
|
|
|
_appName = appName;
|
|
|
|
_oldVersion = oldVersion;
|
2010-02-06 20:25:13 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
@Override
|
|
|
|
public URI getURI() { return _uri; }
|
2010-02-06 20:25:13 +00:00
|
|
|
|
2012-10-22 20:25:01 +00:00
|
|
|
@Override
|
|
|
|
public String getID() { return _appName; }
|
|
|
|
|
2010-02-06 20:25:13 +00:00
|
|
|
@Override
|
|
|
|
protected void update() {
|
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
|
|
|
|
2012-01-23 17:53:59 +00:00
|
|
|
_updated = false;
|
2015-03-21 17:23:19 +00:00
|
|
|
if (_xpi2pURL.startsWith("file:") || _method == UpdateMethod.FILE) {
|
|
|
|
// strip off file:// or just file:
|
|
|
|
String xpi2pfile = _uri.getPath();
|
|
|
|
if(xpi2pfile == null || xpi2pfile.length() == 0) {
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Bad URL {0}", _xpi2pURL) + "</b>");
|
2012-03-13 05:49:02 +00:00
|
|
|
} else {
|
2012-03-15 00:39:11 +00:00
|
|
|
// copy the contents of from to _updateFile
|
|
|
|
long alreadyTransferred = (new File(xpi2pfile)).getAbsoluteFile().length();
|
|
|
|
if(FileUtil.copy((new File(xpi2pfile)).getAbsolutePath(), _updateFile, true, false)) {
|
2015-09-25 19:55:36 +00:00
|
|
|
updateStatus("<b>" + _t("Attempting to install from file {0}", _xpi2pURL) + "</b>");
|
2012-03-15 00:39:11 +00:00
|
|
|
transferComplete(alreadyTransferred, alreadyTransferred, 0L, _xpi2pURL, _updateFile, false);
|
|
|
|
} else {
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Failed to install from file {0}, copy failed.", _xpi2pURL) + "</b>");
|
2012-03-13 05:49:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// use the same settings as for updater
|
2015-04-24 16:08:08 +00:00
|
|
|
//boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
|
|
|
|
// always proxy, or else FIXME
|
|
|
|
boolean shouldProxy = true;
|
2012-03-13 05:49:02 +00:00
|
|
|
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
|
|
|
|
int proxyPort = ConfigUpdateHandler.proxyPort(_context);
|
2015-04-24 16:08:08 +00:00
|
|
|
if (shouldProxy && proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
|
|
|
|
proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
|
|
|
|
_context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
|
2015-09-25 19:55:36 +00:00
|
|
|
String msg = _t("HTTP client proxy tunnel must be running");
|
2015-04-24 16:08:08 +00:00
|
|
|
if (_log.shouldWarn())
|
|
|
|
_log.warn(msg);
|
|
|
|
statusDone("<b>" + msg + "</b>");
|
|
|
|
_mgr.notifyTaskFailed(this, msg, null);
|
|
|
|
return;
|
|
|
|
}
|
2015-09-25 19:55:36 +00:00
|
|
|
updateStatus("<b>" + _t("Downloading plugin from {0}", _xpi2pURL) + "</b>");
|
2012-03-13 05:49:02 +00:00
|
|
|
try {
|
|
|
|
if (shouldProxy)
|
|
|
|
// 10 retries!!
|
|
|
|
_get = new EepGet(_context, proxyHost, proxyPort, 10, _updateFile, _xpi2pURL, false);
|
|
|
|
else
|
|
|
|
_get = new EepGet(_context, 1, _updateFile, _xpi2pURL, false);
|
|
|
|
_get.addStatusListener(PluginUpdateRunner.this);
|
2012-08-03 18:56:53 +00:00
|
|
|
_get.fetch(CONNECT_TIMEOUT, -1, shouldProxy ? INACTIVITY_TIMEOUT : NOPROXY_INACTIVITY_TIMEOUT);
|
2012-03-13 05:49:02 +00:00
|
|
|
} catch (Throwable t) {
|
|
|
|
_log.error("Error downloading plugin", t);
|
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
}
|
2012-10-23 02:34:24 +00:00
|
|
|
if (_updated)
|
|
|
|
_mgr.notifyComplete(this, _newVersion, null);
|
|
|
|
else
|
|
|
|
_mgr.notifyTaskFailed(this, _errMsg, null);
|
2010-02-06 20:25:13 +00:00
|
|
|
}
|
2012-03-13 05:49:02 +00:00
|
|
|
|
2018-04-17 12:37:54 +00:00
|
|
|
/**
|
|
|
|
* Overridden to change the "Updating I2P" text in super
|
|
|
|
* @since 0.9.35
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {
|
|
|
|
long d = currentWrite + bytesTransferred;
|
|
|
|
String status = "<b>" + _t("Downloading plugin") + ": " + _appName + "</b>";
|
|
|
|
_mgr.notifyProgress(this, status, d, d + bytesRemaining);
|
|
|
|
}
|
|
|
|
|
2010-02-06 20:25:13 +00:00
|
|
|
@Override
|
|
|
|
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
|
2017-11-25 19:53:25 +00:00
|
|
|
if (!(_xpi2pURL.startsWith("file:") || _method == UpdateMethod.FILE))
|
|
|
|
updateStatus("<b>" + _t("Plugin downloaded") + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
File f = new File(_updateFile);
|
2010-07-06 15:22:48 +00:00
|
|
|
File appDir = new SecureDirectory(_context.getConfigDir(), PLUGIN_DIR);
|
2010-02-06 20:25:13 +00:00
|
|
|
if ((!appDir.exists()) && (!appDir.mkdir())) {
|
|
|
|
f.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Cannot create plugin directory {0}", appDir.getAbsolutePath()) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-08-07 18:45:04 +00:00
|
|
|
boolean isSU3;
|
|
|
|
try {
|
|
|
|
isSU3 = isSU3File(f);
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
f.delete();
|
|
|
|
statusDone("<b>" + ioe + "</b>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (isSU3)
|
|
|
|
processSU3(f, appDir, url);
|
|
|
|
else
|
|
|
|
processSUD(f, appDir, url);
|
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
|
2014-08-07 18:45:04 +00:00
|
|
|
/**
|
|
|
|
* @since 0.9.15
|
|
|
|
* @return if SU3
|
|
|
|
*/
|
|
|
|
private static boolean isSU3File(File f) throws IOException {
|
|
|
|
FileInputStream fis = null;
|
|
|
|
try {
|
|
|
|
fis = new FileInputStream(f);
|
|
|
|
for (int i = 0; i < SU3File.MAGIC.length(); i++) {
|
|
|
|
if (fis.read() != SU3File.MAGIC.charAt(i))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} finally {
|
|
|
|
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
|
2014-08-07 18:45:04 +00:00
|
|
|
/**
|
|
|
|
* @since 0.9.15
|
|
|
|
* @return success
|
|
|
|
*/
|
|
|
|
private void processSUD(File f, File appDir, String url) {
|
2010-02-06 20:25:13 +00:00
|
|
|
TrustedUpdate up = new TrustedUpdate(_context);
|
|
|
|
File to = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + ZIP);
|
|
|
|
// extract to a zip file whether the sig is good or not, so we can get the properties file
|
|
|
|
String err = up.migrateFile(f, to);
|
|
|
|
if (err != null) {
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + err + ' ' + _t("from {0}", url) + " </b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
f.delete();
|
|
|
|
to.delete();
|
|
|
|
return;
|
|
|
|
}
|
2014-08-07 19:06:41 +00:00
|
|
|
Properties props = getPluginConfig(f, to, url);
|
|
|
|
if (props == null)
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// ok, now we check sigs and deal with a bad sig
|
|
|
|
String pubkey = props.getProperty("key");
|
2014-08-03 13:58:51 +00:00
|
|
|
String signer = DataHelper.stripHTML(props.getProperty("signer"));
|
2010-02-17 18:12:46 +00:00
|
|
|
if (pubkey == null || signer == null || pubkey.length() != 172 || signer.length() <= 0) {
|
2010-02-06 20:25:13 +00:00
|
|
|
f.delete();
|
|
|
|
to.delete();
|
2010-02-17 18:12:46 +00:00
|
|
|
//updateStatus("<b>" + "Plugin contains an invalid key" + ' ' + pubkey + ' ' + signer + "</b>");
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin from {0} contains an invalid key", url) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-08-05 21:23:48 +00:00
|
|
|
SigningPublicKey spk;
|
|
|
|
try {
|
|
|
|
spk = new SigningPublicKey(pubkey);
|
|
|
|
} catch (DataFormatException dfe) {
|
|
|
|
f.delete();
|
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin from {0} contains an invalid key", url) + "</b>");
|
2014-08-05 21:23:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
|
2010-02-10 15:35:00 +00:00
|
|
|
// add all existing plugin keys, so any conflicts with existing keys
|
|
|
|
// will be discovered and rejected
|
|
|
|
Map<String, String> existingKeys = PluginStarter.getPluginKeys(_context);
|
|
|
|
for (Map.Entry<String, String> e : existingKeys.entrySet()) {
|
|
|
|
// ignore dups/bad keys
|
|
|
|
up.addKey(e.getKey(), e.getValue());
|
|
|
|
}
|
|
|
|
|
2014-08-03 13:58:51 +00:00
|
|
|
// add all trusted plugin keys, so any conflicts with trusted keys
|
|
|
|
// will be discovered and rejected
|
|
|
|
Map<String, String> trustedKeys = TrustedPluginKeys.getKeys();
|
|
|
|
for (Map.Entry<String, String> e : trustedKeys.entrySet()) {
|
|
|
|
// ignore dups/bad keys
|
|
|
|
up.addKey(e.getKey(), e.getValue());
|
|
|
|
}
|
|
|
|
|
2010-02-06 20:25:13 +00:00
|
|
|
if (up.haveKey(pubkey)) {
|
|
|
|
// the key is already in the TrustedUpdate keyring
|
2010-02-17 18:12:46 +00:00
|
|
|
// verify the sig and verify that it is signed by the signer in the plugin.config file
|
2011-02-19 19:14:05 +00:00
|
|
|
// Allow "" as the previously-known signer
|
2014-08-05 21:23:48 +00:00
|
|
|
boolean ok = up.verify(f, spk);
|
|
|
|
String signingKeyName = up.getKeys().get(spk);
|
|
|
|
if ((!ok) || !(signer.equals(signingKeyName) || "".equals(signingKeyName))) {
|
2010-02-06 20:25:13 +00:00
|
|
|
f.delete();
|
|
|
|
to.delete();
|
2011-02-19 19:14:05 +00:00
|
|
|
if (signingKeyName == null)
|
|
|
|
_log.error("Failed to verify plugin signature, corrupt plugin or bad signature, signed by: " + signer);
|
|
|
|
else
|
|
|
|
_log.error("Plugin signer \"" + signer + "\" does not match existing signer in plugin.config file \"" + signingKeyName + "\"");
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin signature verification of {0} failed", url) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-08-03 13:58:51 +00:00
|
|
|
} else if (_context.getBooleanProperty(PROP_ALLOW_NEW_KEYS)) {
|
2010-02-06 20:25:13 +00:00
|
|
|
// add to keyring...
|
2010-02-17 18:12:46 +00:00
|
|
|
if(!up.addKey(pubkey, signer)) {
|
2010-02-06 20:25:13 +00:00
|
|
|
// bad or duplicate key
|
|
|
|
f.delete();
|
|
|
|
to.delete();
|
2011-02-19 19:14:05 +00:00
|
|
|
_log.error("Bad key or key mismatch - Failed to add plugin key \"" + pubkey + "\" for plugin signer \"" + signer + "\"");
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin signature verification of {0} failed", url) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// ...and try the verify again
|
2010-02-17 18:12:46 +00:00
|
|
|
// verify the sig and verify that it is signed by the signer in the plugin.config file
|
2010-02-15 16:12:49 +00:00
|
|
|
String signingKeyName = up.verifyAndGetSigner(f);
|
2010-02-17 18:12:46 +00:00
|
|
|
if (!signer.equals(signingKeyName)) {
|
2010-02-06 20:25:13 +00:00
|
|
|
f.delete();
|
|
|
|
to.delete();
|
2011-02-19 19:14:05 +00:00
|
|
|
if (signingKeyName == null)
|
|
|
|
_log.error("Failed to verify plugin signature, corrupt plugin or bad signature, signed by: " + signer);
|
|
|
|
else
|
|
|
|
// shouldn't happen
|
|
|
|
_log.error("Plugin signer \"" + signer + "\" does not match new signer in plugin.config file \"" + signingKeyName + "\"");
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin signature verification of {0} failed", url) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-08-03 13:58:51 +00:00
|
|
|
} else {
|
|
|
|
// unknown key
|
|
|
|
f.delete();
|
|
|
|
to.delete();
|
|
|
|
_log.error("Untrusted plugin key \"" + pubkey + "\" for plugin signer \"" + signer + "\"");
|
|
|
|
// don't display signer, we're really checking the key not the signer name
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin not installed - signer is untrusted") + "</b>");
|
2014-08-03 13:58:51 +00:00
|
|
|
return;
|
2010-02-06 20:25:13 +00:00
|
|
|
}
|
2010-02-08 22:50:30 +00:00
|
|
|
|
|
|
|
String sudVersion = TrustedUpdate.getVersionString(f);
|
2010-02-06 20:25:13 +00:00
|
|
|
f.delete();
|
2014-08-07 19:06:41 +00:00
|
|
|
processFinal(to, appDir, url, props, sudVersion, pubkey, signer);
|
2014-08-07 18:45:04 +00:00
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
|
2014-08-07 18:45:04 +00:00
|
|
|
/**
|
|
|
|
* @since 0.9.15
|
|
|
|
*/
|
|
|
|
private void processSU3(File f, File appDir, String url) {
|
2014-08-07 19:06:41 +00:00
|
|
|
SU3File su3 = new SU3File(_context, f);
|
|
|
|
File to = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + ZIP);
|
|
|
|
String sudVersion;
|
|
|
|
String signingKeyName;
|
|
|
|
try {
|
|
|
|
su3.verifyAndMigrate(to);
|
2014-08-07 19:27:53 +00:00
|
|
|
if (su3.getFileType() != SU3File.TYPE_ZIP)
|
|
|
|
throw new IOException("bad file type");
|
|
|
|
if (su3.getContentType() != SU3File.CONTENT_PLUGIN)
|
|
|
|
throw new IOException("bad content type");
|
2014-08-07 19:06:41 +00:00
|
|
|
sudVersion = su3.getVersionString();
|
|
|
|
signingKeyName = su3.getSignerString();
|
|
|
|
} catch (IOException ioe) {
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + ioe + ' ' + _t("from {0}", url) + " </b>");
|
2014-08-07 19:06:41 +00:00
|
|
|
f.delete();
|
|
|
|
to.delete();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Properties props = getPluginConfig(f, to, url);
|
|
|
|
if (props == null)
|
|
|
|
return;
|
|
|
|
String signer = props.getProperty("signer");
|
2014-08-07 19:27:53 +00:00
|
|
|
if (signer == null || signer.length() <= 0) {
|
2014-08-07 19:06:41 +00:00
|
|
|
f.delete();
|
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin from {0} contains an invalid key", url) + "</b>");
|
2014-08-07 19:06:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!signer.equals(signingKeyName)) {
|
|
|
|
f.delete();
|
|
|
|
to.delete();
|
|
|
|
if (signingKeyName == null)
|
|
|
|
_log.error("Failed to verify plugin signature, corrupt plugin or bad signature, signed by: " + signer);
|
|
|
|
else
|
|
|
|
// shouldn't happen
|
|
|
|
_log.error("Plugin signer \"" + signer + "\" does not match new signer in plugin.config file \"" + signingKeyName + "\"");
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin signature verification of {0} failed", url) + "</b>");
|
2014-08-07 19:06:41 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-08-07 19:27:53 +00:00
|
|
|
processFinal(to, appDir, url, props, sudVersion, null, signer);
|
2014-08-07 19:06:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @since 0.9.15
|
|
|
|
* @return null on error
|
|
|
|
*/
|
|
|
|
private Properties getPluginConfig(File f, File to, String url) {
|
|
|
|
File tempDir = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + "-unzip");
|
|
|
|
if (!FileUtil.extractZip(to, tempDir, Log.ERROR)) {
|
|
|
|
f.delete();
|
|
|
|
to.delete();
|
|
|
|
FileUtil.rmdir(tempDir, false);
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin from {0} is corrupt", url) + "</b>");
|
2014-08-07 19:06:41 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
File installProps = new File(tempDir, "plugin.config");
|
|
|
|
Properties props = new OrderedProperties();
|
|
|
|
try {
|
|
|
|
DataHelper.loadProps(props, installProps);
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
f.delete();
|
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin from {0} does not contain the required configuration file", url) + "</b>");
|
2014-08-07 19:06:41 +00:00
|
|
|
return null;
|
|
|
|
} finally {
|
|
|
|
// we don't need this anymore, we will unzip again
|
|
|
|
FileUtil.rmdir(tempDir, false);
|
|
|
|
}
|
|
|
|
return props;
|
2014-08-07 18:45:04 +00:00
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
|
2014-08-07 18:45:04 +00:00
|
|
|
/**
|
2014-08-07 19:27:53 +00:00
|
|
|
* @param pubkey null OK for su3
|
2014-08-07 18:45:04 +00:00
|
|
|
* @since 0.9.15
|
|
|
|
*/
|
2014-08-07 19:06:41 +00:00
|
|
|
private void processFinal(File to, File appDir, String url, Properties props, String sudVersion, String pubkey, String signer) {
|
2014-08-07 18:45:04 +00:00
|
|
|
boolean update = false;
|
2010-02-06 20:25:13 +00:00
|
|
|
String appName = props.getProperty("name");
|
|
|
|
String version = props.getProperty("version");
|
|
|
|
if (appName == null || version == null || appName.length() <= 0 || version.length() <= 0 ||
|
2016-12-02 18:52:37 +00:00
|
|
|
appName.indexOf('<') >= 0 || appName.indexOf('>') >= 0 ||
|
|
|
|
version.indexOf('<') >= 0 || version.indexOf('>') >= 0 ||
|
|
|
|
appName.startsWith(".") || appName.indexOf('/') >= 0 || appName.indexOf('\\') >= 0) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin from {0} has invalid name or version", url) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-02-08 22:50:30 +00:00
|
|
|
if (!version.equals(sudVersion)) {
|
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin {0} has mismatched versions", appName) + "</b>");
|
2010-02-08 22:50:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-10-23 02:34:24 +00:00
|
|
|
// set so notifyComplete() will work
|
|
|
|
_appName = appName;
|
|
|
|
_newVersion = version;
|
2010-02-06 20:25:13 +00:00
|
|
|
|
2017-12-01 14:07:29 +00:00
|
|
|
String minVersion = PluginStarter.stripHTML(props, "min-i2p-version");
|
2010-02-06 20:25:13 +00:00
|
|
|
if (minVersion != null &&
|
2013-05-26 17:25:02 +00:00
|
|
|
VersionComparator.comp(CoreVersion.VERSION, minVersion) < 0) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("This plugin requires I2P version {0} or higher", minVersion) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-01 14:07:29 +00:00
|
|
|
minVersion = PluginStarter.stripHTML(props, "min-java-version");
|
2010-02-06 20:25:13 +00:00
|
|
|
if (minVersion != null &&
|
2013-05-26 17:25:02 +00:00
|
|
|
VersionComparator.comp(System.getProperty("java.version"), minVersion) < 0) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("This plugin requires Java version {0} or higher", minVersion) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-01-15 16:59:33 +00:00
|
|
|
boolean wasRunning = false;
|
2010-07-06 15:22:48 +00:00
|
|
|
File destDir = new SecureDirectory(appDir, appName);
|
2010-02-06 20:25:13 +00:00
|
|
|
if (destDir.exists()) {
|
2010-02-07 13:32:49 +00:00
|
|
|
if (Boolean.valueOf(props.getProperty("install-only")).booleanValue()) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Downloaded plugin is for new installs only, but the plugin is already installed", url) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// compare previous version
|
2010-02-07 13:32:49 +00:00
|
|
|
File oldPropFile = new File(destDir, "plugin.config");
|
2010-02-06 20:25:13 +00:00
|
|
|
Properties oldProps = new OrderedProperties();
|
|
|
|
try {
|
|
|
|
DataHelper.loadProps(oldProps, oldPropFile);
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Installed plugin does not contain the required configuration file", url) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
String oldPubkey = oldProps.getProperty("key");
|
2010-02-17 18:12:46 +00:00
|
|
|
String oldKeyName = oldProps.getProperty("signer");
|
2012-03-13 09:49:15 +00:00
|
|
|
String oldAppName = oldProps.getProperty("name");
|
2014-08-07 19:27:53 +00:00
|
|
|
if ((pubkey != null && !pubkey.equals(oldPubkey)) || (!signer.equals(oldKeyName)) || (!appName.equals(oldAppName))) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Signature of downloaded plugin does not match installed plugin") + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
String oldVersion = oldProps.getProperty("version");
|
|
|
|
if (oldVersion == null ||
|
2013-05-26 17:25:02 +00:00
|
|
|
VersionComparator.comp(oldVersion, version) >= 0) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Downloaded plugin version {0} is not newer than installed plugin", version) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-12-01 14:07:29 +00:00
|
|
|
minVersion = PluginStarter.stripHTML(props, "min-installed-version");
|
2010-02-06 20:25:13 +00:00
|
|
|
if (minVersion != null &&
|
2013-05-26 17:25:02 +00:00
|
|
|
VersionComparator.comp(minVersion, oldVersion) > 0) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin update requires installed plugin version {0} or higher", minVersion) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-12-01 14:07:29 +00:00
|
|
|
String maxVersion = PluginStarter.stripHTML(props, "max-installed-version");
|
2010-02-06 20:25:13 +00:00
|
|
|
if (maxVersion != null &&
|
2013-05-26 17:25:02 +00:00
|
|
|
VersionComparator.comp(maxVersion, oldVersion) < 0) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin update requires installed plugin version {0} or lower", maxVersion) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-12-01 14:07:29 +00:00
|
|
|
oldVersion = RouterConsoleRunner.jettyVersion();
|
|
|
|
minVersion = PluginStarter.stripHTML(props, "min-jetty-version");
|
2011-12-24 00:48:30 +00:00
|
|
|
if (minVersion != null &&
|
2013-05-26 17:25:02 +00:00
|
|
|
VersionComparator.comp(minVersion, oldVersion) > 0) {
|
2011-12-24 00:48:30 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin requires Jetty version {0} or higher", minVersion) + "</b>");
|
2011-12-24 00:48:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-03-23 14:55:56 +00:00
|
|
|
String blacklistVersion = PluginStarter.jetty9Blacklist.get(appName);
|
|
|
|
if (blacklistVersion != null &&
|
|
|
|
VersionComparator.comp(version, blacklistVersion) <= 0) {
|
|
|
|
to.delete();
|
|
|
|
statusDone("<b>" + _t("Plugin requires Jetty version {0} or lower", "8.9999") + "</b>");
|
|
|
|
return;
|
|
|
|
}
|
2018-09-23 15:11:16 +00:00
|
|
|
if (SystemVersion.isJava9()) {
|
|
|
|
blacklistVersion = PluginStarter.java9Blacklist.get(appName);
|
|
|
|
if (blacklistVersion != null &&
|
|
|
|
VersionComparator.comp(version, blacklistVersion) <= 0) {
|
|
|
|
to.delete();
|
|
|
|
statusDone("<b>" + _t("Plugin requires Java version {0} or lower", "8.9999") + "</b>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-12-01 14:07:29 +00:00
|
|
|
maxVersion = PluginStarter.stripHTML(props, "max-jetty-version");
|
2011-12-24 00:48:30 +00:00
|
|
|
if (maxVersion != null &&
|
2013-05-26 17:25:02 +00:00
|
|
|
VersionComparator.comp(maxVersion, oldVersion) < 0) {
|
2011-12-24 00:48:30 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin requires Jetty version {0} or lower", maxVersion) + "</b>");
|
2011-12-24 00:48:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-03-13 05:49:02 +00:00
|
|
|
// do we defer extraction and installation?
|
2012-03-13 09:49:15 +00:00
|
|
|
if (Boolean.valueOf(props.getProperty("router-restart-required")).booleanValue()) {
|
2012-03-13 05:49:02 +00:00
|
|
|
// Yup!
|
2012-03-13 09:49:15 +00:00
|
|
|
try {
|
|
|
|
if(!FileUtil.copy(to, (new SecureFile( new SecureFile(appDir.getCanonicalPath() +"/" + appName +"/"+ ZIP).getCanonicalPath())) , true, true)) {
|
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Cannot copy plugin to directory {0}", destDir.getAbsolutePath()) + "</b>");
|
2012-03-13 09:49:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch (Throwable t) {
|
2012-03-13 05:49:02 +00:00
|
|
|
to.delete();
|
2012-03-13 09:49:15 +00:00
|
|
|
_log.error("Error copying plugin {0}", t);
|
2012-03-13 05:49:02 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// we don't need the original file anymore.
|
|
|
|
to.delete();
|
2017-03-23 13:54:02 +00:00
|
|
|
statusDone("<b>" + _t("Plugin will be installed on next restart.") + ' ' + appName + ' ' + version + "</b>");
|
2012-03-13 09:49:15 +00:00
|
|
|
return;
|
2012-03-13 05:49:02 +00:00
|
|
|
}
|
2012-01-15 16:59:33 +00:00
|
|
|
if (PluginStarter.isPluginRunning(appName, _context)) {
|
|
|
|
wasRunning = true;
|
|
|
|
try {
|
|
|
|
if (!PluginStarter.stopPlugin(_context, appName)) {
|
|
|
|
// failed, ignore
|
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
// no updateStatus() for this one
|
|
|
|
_log.error("Error stopping plugin " + appName, e);
|
2010-02-08 20:37:49 +00:00
|
|
|
}
|
2010-02-11 21:41:54 +00:00
|
|
|
}
|
2012-03-15 00:39:11 +00:00
|
|
|
update = true;
|
2010-02-06 20:25:13 +00:00
|
|
|
} else {
|
2010-02-07 13:32:49 +00:00
|
|
|
if (Boolean.valueOf(props.getProperty("update-only")).booleanValue()) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2017-03-23 13:54:02 +00:00
|
|
|
statusDone("<b>" + _t("Plugin is for upgrades only, but the plugin is not installed") + ". " + appName + ' ' + version + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!destDir.mkdir()) {
|
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Cannot create plugin directory {0}", destDir.getAbsolutePath()) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, extract the zip to the plugin directory
|
2013-07-03 17:12:32 +00:00
|
|
|
if (!FileUtil.extractZip(to, destDir, Log.WARN)) {
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Failed to install plugin in {0}", destDir.getAbsolutePath()) + "</b>");
|
2010-02-06 20:25:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-01-23 17:53:59 +00:00
|
|
|
_updated = true;
|
2010-02-06 20:25:13 +00:00
|
|
|
to.delete();
|
2012-03-15 00:39:11 +00:00
|
|
|
// install != update. Changing the user's settings like this is probabbly a bad idea.
|
|
|
|
if (Boolean.valueOf( props.getProperty("dont-start-at-install")).booleanValue()) {
|
2017-03-23 13:54:02 +00:00
|
|
|
statusDone("<b>" + _t("Plugin {0} installed", appName + ' ' + version) + "</b>");
|
2012-03-15 00:39:11 +00:00
|
|
|
if(!update) {
|
2010-02-08 16:15:23 +00:00
|
|
|
Properties pluginProps = PluginStarter.pluginProperties();
|
|
|
|
pluginProps.setProperty(PluginStarter.PREFIX + appName + PluginStarter.ENABLED, "false");
|
|
|
|
PluginStarter.storePluginProperties(pluginProps);
|
|
|
|
}
|
2012-01-15 16:59:33 +00:00
|
|
|
} else if (wasRunning || PluginStarter.isPluginEnabled(appName)) {
|
|
|
|
// start everything unless it was disabled and not running before
|
2010-02-07 13:32:49 +00:00
|
|
|
try {
|
2010-11-27 13:48:53 +00:00
|
|
|
if (PluginStarter.startPlugin(_context, appName)) {
|
2017-12-01 14:07:29 +00:00
|
|
|
String linkName = PluginStarter.stripHTML(props, "consoleLinkName_" + Messages.getLanguage(_context));
|
2010-11-27 13:48:53 +00:00
|
|
|
if (linkName == null)
|
2017-12-01 14:07:29 +00:00
|
|
|
linkName = PluginStarter.stripHTML(props, "consoleLinkName");
|
|
|
|
String linkURL = PluginStarter.stripHTML(props, "consoleLinkURL");
|
2010-11-27 13:48:53 +00:00
|
|
|
String link;
|
|
|
|
if (linkName != null && linkURL != null)
|
2017-03-23 13:54:02 +00:00
|
|
|
link = "<a target=\"_blank\" href=\"" + linkURL + "\"/>" + linkName + ' ' + version + "</a>";
|
2010-11-27 13:48:53 +00:00
|
|
|
else
|
2017-03-23 13:54:02 +00:00
|
|
|
link = appName + ' ' + version;
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Plugin {0} installed and started", link) + "</b>");
|
2010-11-27 13:48:53 +00:00
|
|
|
}
|
2010-02-07 13:32:49 +00:00
|
|
|
else
|
2017-03-23 13:54:02 +00:00
|
|
|
statusDone("<b>" + _t("Plugin {0} installed but failed to start, check logs", appName + ' ' + version) + "</b>");
|
2010-02-11 21:41:54 +00:00
|
|
|
} catch (Throwable e) {
|
2017-03-23 13:54:02 +00:00
|
|
|
statusDone("<b>" + _t("Plugin {0} installed but failed to start", appName + ' ' + version) + ": " + e + "</b>");
|
|
|
|
_log.error("Error starting plugin " + appName + ' ' + version, e);
|
2010-02-07 13:32:49 +00:00
|
|
|
}
|
2012-01-15 16:59:33 +00:00
|
|
|
} else {
|
2017-03-23 13:54:02 +00:00
|
|
|
statusDone("<b>" + _t("Plugin {0} installed", appName + ' ' + version) + "</b>");
|
2010-02-07 13:32:49 +00:00
|
|
|
}
|
2010-02-06 20:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
|
|
|
|
File f = new File(_updateFile);
|
|
|
|
f.delete();
|
2015-09-25 19:55:36 +00:00
|
|
|
statusDone("<b>" + _t("Failed to download plugin from {0}", url) + "</b>");
|
2010-03-25 20:23:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void statusDone(String msg) {
|
2012-10-23 02:34:24 +00:00
|
|
|
// if we fail, we will pass this back in notifyTaskFailed()
|
|
|
|
_errMsg = msg;
|
2010-03-25 20:23:32 +00:00
|
|
|
updateStatus(msg);
|
2010-02-06 20:25:13 +00:00
|
|
|
}
|
2010-03-25 20:23:32 +00:00
|
|
|
|
2010-02-06 20:25:13 +00:00
|
|
|
}
|
2012-03-13 05:49:02 +00:00
|
|
|
|