Skip to content

Commit

Permalink
Improve one-click update of 3rd party plugins
Browse files Browse the repository at this point in the history
Add version information to ExternalPluginUpdates.xml and include this into one-click update
Introduce ExternalPluginUpdatesUser.xml for user-specific definitions and to override ExternalPluginUpdates.xml if required

Closes Rookiestyle#16
  • Loading branch information
Rookiestyle committed Feb 14, 2021
1 parent fa94726 commit 62e04a6
Show file tree
Hide file tree
Showing 11 changed files with 272 additions and 88 deletions.
81 changes: 46 additions & 35 deletions ExternalPluginUpdates/ExternalPluginUpdates.xml
Original file line number Diff line number Diff line change
@@ -1,38 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is part of EarlyUpdateCheck's one-click update
If a newer version is released than the version you're using
this new version will be downloaded automatically
In the rare case of issues with updated plugins, you
can use ExternalPluginUpdatesUser.xml to remove certain plugins
from one-click update
-->
<UpdateInfoExternList>
<UpdateInfoExtern>
<PluginName>WebAutoType</PluginName>
<PluginURL>https://sourceforge.net/projects/webautotype/</PluginURL>
<PluginUpdateURL>https://sourceforge.net/projects/webautotype/files/latest/download</PluginUpdateURL>
<UpdateMode>ZipExtractPlgx</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
<UpdateInfoExtern>
<PluginName>KPEnhancedEntryView</PluginName>
<PluginURL>https://sourceforge.net/projects/kpenhentryview/</PluginURL>
<PluginUpdateURL>https://sourceforge.net/projects/kpenhentryview/files/latest/download</PluginUpdateURL>
<UpdateMode>ZipExtractPlgx</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
<UpdateInfoExtern>
<PluginName>SourceForgeUpdateChecker</PluginName>
<PluginURL>https://sourceforge.net/projects/kpsfupdatechecker/</PluginURL>
<PluginUpdateURL>https://sourceforge.net/projects/kpsfupdatechecker/files/latest/download</PluginUpdateURL>
<UpdateMode>ZipExtractPlgx</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
<UpdateInfoExtern>
<PluginName>KeePass Sync For Google Drive</PluginName>
<PluginURL>https://github.com/walterpg/google-drive-sync/releases</PluginURL>
<PluginUpdateURL>https://github.com/walterpg/google-drive-sync/releases/latest/download/keepasssyncfordrive-{major}.{minor}.{build}-beta.plgx</PluginUpdateURL>
<UpdateMode>PlgxDirect</UpdateMode>
<AllowVersionStripping>False</AllowVersionStripping>
</UpdateInfoExtern>
<UpdateInfoExtern>
<PluginName>KeeAutoExec</PluginName>
<PluginURL>https://keepass.info/plugins.html#keeautoexec</PluginURL>
<PluginUpdateURL>https://keepass.info/extensions/v2/keeautoexec/KeeAutoExec-{major}{.minor}{.build}.zip</PluginUpdateURL>
<UpdateMode>ZipExtractPlgx</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
<Version>2</Version>
<UpdateInfoExtern>
<PluginName>WebAutoType</PluginName>
<PluginURL>https://sourceforge.net/projects/webautotype/</PluginURL>
<PluginUpdateURL>https://sourceforge.net/projects/webautotype/files/latest/download</PluginUpdateURL>
<UpdateMode>ZipExtractPlgx</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
<UpdateInfoExtern>
<PluginName>KPEnhancedEntryView</PluginName>
<PluginURL>https://sourceforge.net/projects/kpenhentryview/</PluginURL>
<PluginUpdateURL>https://sourceforge.net/projects/kpenhentryview/files/latest/download</PluginUpdateURL>
<UpdateMode>ZipExtractPlgx</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
<UpdateInfoExtern>
<PluginName>SourceForgeUpdateChecker</PluginName>
<PluginURL>https://sourceforge.net/projects/kpsfupdatechecker/</PluginURL>
<PluginUpdateURL>https://sourceforge.net/projects/kpsfupdatechecker/files/latest/download</PluginUpdateURL>
<UpdateMode>ZipExtractPlgx</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
<UpdateInfoExtern>
<PluginName>KeePass Sync For Google Drive</PluginName>
<PluginURL>https://github.com/walterpg/google-drive-sync/releases</PluginURL>
<PluginUpdateURL>https://github.com/walterpg/google-drive-sync/releases/latest/download/keepasssyncfordrive-{major}.{minor}.{build}-beta.plgx</PluginUpdateURL>
<UpdateMode>PlgxDirect</UpdateMode>
<AllowVersionStripping>False</AllowVersionStripping>
</UpdateInfoExtern>
<UpdateInfoExtern>
<PluginName>KeeAutoExec</PluginName>
<PluginURL>https://keepass.info/plugins.html#keeautoexec</PluginURL>
<PluginUpdateURL>https://keepass.info/extensions/v2/keeautoexec/KeeAutoExec-{major}{.minor}{.build}.zip</PluginUpdateURL>
<UpdateMode>ZipExtractPlgx</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
</UpdateInfoExternList>
30 changes: 30 additions & 0 deletions ExternalPluginUpdates/ExternalPluginUpdatesUser.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is _not_ part of EarlyUpdateCheck's one-click update
It MUST NOT contain a version tag
It can be used to add / change update information, e. g. for plugins
available in your local network (private, office, ...)
It can also be used tomexclude plugins from one-click update
-->
<UpdateInfoExternList>
<!-- Example for additional plugins -->
<!--
<UpdateInfoExtern>
<PluginName>My plugin</PluginName>
<PluginURL>https://localhost/myplugin</PluginURL>
<PluginUpdateURL>https://localhost/myplugin/download/myplugin.plgx</PluginUpdateURL>
<UpdateMode>PlgxDirect</UpdateMode>
<AllowVersionStripping>True</AllowVersionStripping>
</UpdateInfoExtern>
-->

<!-- Example for plugin to ignore -->
<!--
<UpdateInfoExtern>
<PluginName>Some other plugin</PluginName>
<Ignore />
</UpdateInfoExtern>
-->
</UpdateInfoExternList>
7 changes: 6 additions & 1 deletion Translations/EarlyUpdateCheck.de.language.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Translation>
<TranslationVersion>4</TranslationVersion>
<TranslationVersion>5</TranslationVersion>
<item>
<key>Active</key>
<value>Aktiv</value>
Expand Down Expand Up @@ -92,4 +92,9 @@ Die Windows Benutzerkontensteuerung wird eventuell angezeigt und muss bestätigt
<key>SelectPluginsForTranslationUpdate</key>
<value>Bitte wähle die Plugins aus, bei denen aktualisierte Übersetzungen installiert werden sollen.</value>
</item>
<item>
<key>UpdateExternalInfo</key>
<value>Eine neue Version von ExternalPluginUpdates.xml steht zur Verfügung.
Herunterladen, um mehr Plugins automatisch aktualisieren zu können?</value>
</item>
</Translation>
5 changes: 5 additions & 0 deletions Translations/EarlyUpdateCheck.template.language.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,9 @@ This might show the UAC prompt.</value>
<key>SelectPluginsForTranslationUpdate</key>
<value>Please select plugins for which translations shall be updated</value>
</item>
<item>
<key>UpdateExternalInfo</key>
<value>A new veraion of ExternalPluginUpdates.xml is available.
Download to update more 3rd party plugins?</value>
</item>
</Translation>
83 changes: 70 additions & 13 deletions src/EarlyUpdateCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ private void MainWindow_FormLoadPost(object sender, EventArgs e)
else if (!m_bRestartTriggered)
{
//Only load plugins, do NOT check for new translations
ThreadPool.QueueUserWorkItem(new WaitCallback((object o) => { PluginUpdateHandler.LoadPlugins(false); }));
ThreadPool.QueueUserWorkItem(new WaitCallback((object o) =>
{
PluginUpdateHandler.LoadPlugins(false);
CheckExternalPluginUpdate();
}));
}
PluginDebug.AddInfo("All plugins loaded", 0, DebugPrint);
m_bRestartInvoke = false;
Expand Down Expand Up @@ -402,6 +406,8 @@ private void CheckPluginLanguages(object o)
PluginUpdateHandler.LoadPlugins(false);
if (!PluginConfig.Active) return;
if (m_bPluginLanguagesChecked) return;

CheckExternalPluginUpdate();
m_bPluginLanguagesChecked = true;
string translations = string.Empty;
List<OwnPluginUpdate> lPlugins = new List<OwnPluginUpdate>();
Expand All @@ -417,6 +423,7 @@ private void CheckPluginLanguages(object o)
}
}
}

if (lPlugins.Count == 0) return;
var arrPlugins = lPlugins.ConvertAll(x => x.ToString()).ToArray();
PluginDebug.AddInfo("Available translation updates", 0, arrPlugins);
Expand All @@ -433,6 +440,21 @@ private void CheckPluginLanguages(object o)
};
m_host.MainWindow.BeginInvoke(DisplayTranslationForm);
}

private bool m_bExternalPluginInfoChecked = false;
private void CheckExternalPluginUpdate()
{
if (!PluginConfig.Active) return;
if (!PluginConfig.OneClickUpdate) return;
if (m_bExternalPluginInfoChecked) return;
m_bExternalPluginInfoChecked = true;
if (UpdateInfoExternParser.VersionInstalled < 0) return;
if (UpdateInfoExternParser.VersionInstalled >= UpdateInfoExternParser.VersionAvailable) return;
var pu = PluginUpdateHandler.Plugins.Find(x => x is EarlyUpdateCheckUpdate) as OwnPluginUpdate;
if (pu == null) return;
if (Tools.AskYesNo(PluginTranslate.UpdateExternalInfo) != DialogResult.Yes) return;
m_host.MainWindow.Invoke(new KeePassLib.Delegates.GAction(() => { UpdatePlugins(UpdateFlags.ExternalUpdateInfo); }), null);
}
#endregion

#region Adjust UpdateCheckForm if required
Expand All @@ -455,6 +477,7 @@ private void OnUpdateCheckFormShown(object sender, EventArgs e)
else PluginDebug.AddSuccess("m_lvInfo found", 0);
PluginUpdateHandler.LoadPlugins(false);
if (PluginUpdateHandler.Plugins.Count == 0) return;
CheckExternalPluginUpdate();
SetPluginSelectionStatus(false);
bool bColumnAdded = false;
m_lEventHandlerItemActivate = EventHelper.GetItemActivateHandlers(lvPlugins);
Expand Down Expand Up @@ -665,7 +688,7 @@ public void UpdatePluginTranslations(bool bDownloadActiveLanguage, List<string>

//If called from CheckPluginLanguages, we're running in a different thread
//Use Invoke because the IStatusLogger will attach to the KeyPromptForm within the UI thread
m_host.MainWindow.Invoke(new KeePassLib.Delegates.GAction(() => { UpdatePlugins(true); }), null);
m_host.MainWindow.Invoke(new KeePassLib.Delegates.GAction(() => { UpdatePlugins(UpdateFlags.Translations); }), null);
PluginConfig.DownloadActiveLanguage = bBackup;
foreach (var upd in PluginUpdateHandler.Plugins)
{
Expand All @@ -692,12 +715,21 @@ public void UpdatePluginTranslations(bool bDownloadActiveLanguage, List<string>
SetPluginSelectionStatus(false);
}

[Flags]
private enum UpdateFlags
{
None = 0,
Plugin = 1,
Translations = 2,
ExternalUpdateInfo = 4,
All = Plugin | Translations | ExternalUpdateInfo,
}
private void bUpdatePlugins_Click(object sender, EventArgs e)
{
UpdatePlugins(false);
UpdatePlugins(UpdateFlags.All);
}

private void UpdatePlugins(bool bUpdateTranslationsOnly)
private void UpdatePlugins(UpdateFlags uf)
{
PluginDebug.AddInfo("UpdatePlugins start ", DebugPrint);
Form fUpdateLog = null;
Expand All @@ -715,8 +747,15 @@ private void UpdatePlugins(bool bUpdateTranslationsOnly)
//Download files
foreach (PluginUpdate upd in PluginUpdateHandler.Plugins)
{
if (!upd.Selected) continue;
success |= UpdatePlugin(upd, sTempPluginsFolder, bUpdateTranslationsOnly);
if (uf == UpdateFlags.ExternalUpdateInfo && upd is EarlyUpdateCheckUpdate)
{
success |= UpdatePlugin(upd, sTempPluginsFolder, uf);
}
else
{
if (!upd.Selected) continue;
success |= UpdatePlugin(upd, sTempPluginsFolder, uf);
}
}
});
Thread t = new Thread(ts);
Expand Down Expand Up @@ -749,7 +788,14 @@ private void UpdatePlugins(bool bUpdateTranslationsOnly)
success = true;
//Restart KeePass to use new plugin versions
PluginDebug.AddInfo("Update finished", "Succes: " + success.ToString(), DebugPrint);
if (success && !bUpdateTranslationsOnly)
if (success && uf == UpdateFlags.ExternalUpdateInfo)
{
KeePass.Program.Config.Application.LastUpdateCheck = TimeUtil.SerializeUtc(DateTime.UtcNow.AddDays(-1));
UpdateInfoExternParser.Init();
PluginUpdateHandler.LoadPlugins(true);
}

if (success && UpdateFlagSet(uf, UpdateFlags.Plugin))
{
if (Tools.AskYesNo(PluginTranslate.PluginUpdateSuccess, PluginTranslate.PluginUpdateCaption) == DialogResult.Yes)
{
Expand All @@ -767,24 +813,35 @@ private void UpdatePlugins(bool bUpdateTranslationsOnly)
/// <param name="upd">Update information for plugin</param>
/// <param name="sPluginFolder">Target folder for plugin file</param>
/// <param name="sTranslationFolder">Target folder for plugin translations</param>
/// <param name="bTranslationsOnly">Only download newest translations</param>
/// <param name="uf">Only download newest translations</param>
/// <returns></returns>
internal bool UpdatePlugin(PluginUpdate upd, string sPluginFolder, bool bTranslationsOnly)
private bool UpdatePlugin(PluginUpdate upd, string sPluginFolder, UpdateFlags uf)
{
bool bOK = true;
if (m_slUpdatePlugins != null)
m_slUpdatePlugins.SetText(string.Format(PluginTranslate.PluginUpdating, upd.Title), LogStatusType.Info);
if (!bTranslationsOnly) bOK = upd.Download(sPluginFolder);
if (upd is OwnPluginUpdate)
if (UpdateFlagSet(uf, UpdateFlags.Plugin)) bOK = upd.Download(sPluginFolder);
if (upd is OwnPluginUpdate && UpdateFlagSet(uf, UpdateFlags.Translations))
{
bool bTranslationsOK = (upd as OwnPluginUpdate).DownloadTranslations(sPluginFolder, PluginConfig.DownloadActiveLanguage, bTranslationsOnly);
if (bTranslationsOnly) bOK = bTranslationsOK;
bool bTranslationsOK = (upd as OwnPluginUpdate).DownloadTranslations(sPluginFolder, PluginConfig.DownloadActiveLanguage, !UpdateFlagSet(uf, UpdateFlags.Plugin));
if (!UpdateFlagSet(uf, UpdateFlags.Plugin)) bOK = bTranslationsOK;
}
if (upd is EarlyUpdateCheckUpdate && UpdateFlagSet(uf, UpdateFlags.ExternalUpdateInfo))
{
var euc = upd as EarlyUpdateCheckUpdate;
bool bExtOK = euc.DownloadExternalPluginUpdates(sPluginFolder);
if (uf == UpdateFlags.ExternalUpdateInfo) bOK = bExtOK;
}
if (bOK) bOK = upd.ProcessDownload(sPluginFolder);
upd.Cleanup();
return bOK;
}

private bool UpdateFlagSet(UpdateFlags flags, UpdateFlags flag)
{
return (flags & flag) == flag;
}

private void Restart()
{
PluginDebug.AddInfo("Restart started", DebugPrint);
Expand Down
10 changes: 6 additions & 4 deletions src/Options.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 11 additions & 6 deletions src/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,27 @@ private void Options_Load(object sender, EventArgs e)
tpEUCOptions.Text = KPRes.Options;
tpEUC3rdParty.Text = KPRes.More;
lFile.Text = KPRes.File;
tbFile.Text = UpdateInfoParser.PluginInfoFile;
if (System.IO.File.Exists(UpdateInfoParser.PluginInfoFile))
tbFile.Text = UpdateInfoExternParser.PluginInfoFile;
if (System.IO.File.Exists(UpdateInfoExternParser.PluginInfoFile))
{
lFile.Links.Add(0, lFile.Text.Length);
lFile.LinkClicked += LFile_LinkClicked;
}
foreach (var p in PluginUpdateHandler.Plugins)
{
string s = p.Title;
if (p is OtherPluginUpdate) s += " - " + p.UpdateMode.ToString();
lv3rdPartyPlugins.Items.Add(s);
string s = p.Title + (p is OtherPluginUpdate ? " - " + p.UpdateMode.ToString() : string.Empty);
if (p.Ignore)
{
ListViewItem lvi = new ListViewItem(p.Title);
lvi.Font = new Font(lvi.Font, lvi.Font.Style | FontStyle.Strikeout);
lv3rdPartyPlugins.Items.Add(lvi);
}
else lv3rdPartyPlugins.Items.Add(s);
}
}
private void LFile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
PluginTools.Tools.OpenUrl(UpdateInfoParser.PluginInfoFile);
PluginTools.Tools.OpenUrl(UpdateInfoExternParser.PluginInfoFile);
}
}
}
Loading

0 comments on commit 62e04a6

Please sign in to comment.