private void MainWindow_FormLoadPost(object sender, EventArgs e) { //Can be null if restart after upgrade is in progress //In this case, EarlyUpdateCheckExt.Terminate() might have been called already //RemoveAndBackupFormLoadPostHandlers and RestoreFormLoadPostHandlers should work around that, but you never know... if (m_host == null || m_host.MainWindow == null) { return; } if (m_host.MainWindow.IsDisposed || m_host.MainWindow.Disposing) { return; } m_host.MainWindow.FormLoadPost -= MainWindow_FormLoadPost; //Load plugins and check check for new translations if not already done if (PluginUpdateHandler.CheckTranslations && !m_bRestartInvoke) { ThreadPool.QueueUserWorkItem(new WaitCallback(CheckPluginLanguages)); } else if (!m_bRestartInvoke) { //Only load plugins, do NOT check for new translations ThreadPool.QueueUserWorkItem(new WaitCallback((object o) => { PluginUpdateHandler.LoadPlugins(false); })); } PluginDebug.AddInfo("All plugins loaded", 0, DebugPrint); m_bRestartInvoke = false; }
private void CheckPluginLanguages(object o) { PluginUpdateHandler.LoadPlugins(false); if (!PluginConfig.Active) { return; } if (m_bPluginLanguagesChecked) { return; } m_bPluginLanguagesChecked = true; string translations = string.Empty; List <OwnPluginUpdate> lPlugins = new List <OwnPluginUpdate>(); foreach (PluginUpdate pu in PluginUpdateHandler.Plugins) { if (!PluginUpdateHandler.VersionsEqual(pu.VersionInstalled, pu.VersionAvailable)) { continue; } foreach (var t in pu.Translations) { if (t.NewTranslationAvailable || (PluginConfig.DownloadActiveLanguage && t.TranslationForCurrentLanguageAvailable)) { lPlugins.Add(pu as OwnPluginUpdate); break; } } } if (lPlugins.Count == 0) { return; } var arrPlugins = lPlugins.ConvertAll(x => x.ToString()).ToArray(); PluginDebug.AddInfo("Available translation updates", 0, arrPlugins); KeePassLib.Delegates.GAction DisplayTranslationForm = () => { using (TranslationUpdateForm t = new TranslationUpdateForm()) { t.InitEx(lPlugins); if (t.ShowDialog() == DialogResult.OK) { UpdatePluginTranslations(PluginConfig.DownloadActiveLanguage, t.SelectedPlugins); } } }; m_host.MainWindow.BeginInvoke(DisplayTranslationForm); }
internal void InitEx(List <OwnPluginUpdate> lPlugins) { Text = PluginTranslate.TranslationUpdateForm; lSelectPlugins.Text = PluginTranslate.SelectPluginsForTranslationUpdate; bOK.Text = PluginTranslate.TranslationDownload_Update; bOK.Text = PluginTranslate.PluginUpdateSelected; bCancel.Text = KPRes.Cancel; clbPlugins.Items.Clear(); lPlugins.Sort(SortOwnPluginUpdate); foreach (OwnPluginUpdate plugin in lPlugins) { clbPlugins.Items.Add(plugin.Name, PluginUpdateHandler.VersionsEqual(plugin.VersionInstalled, plugin.VersionAvailable) ? CheckState.Checked : CheckState.Indeterminate); } }
public override bool Initialize(IPluginHost host) { m_host = host; PluginTranslate.TranslationChanged += delegate(object sender, TranslationChangedEventArgs e) { if (!string.IsNullOrEmpty(KeePass.Program.Translation.Properties.Iso6391Code)) { PluginUpdateHandler.LanguageIso = KeePass.Program.Translation.Properties.Iso6391Code; } else { PluginUpdateHandler.LanguageIso = e.NewLanguageIso6391; } }; PluginTranslate.Init(this, KeePass.Program.Translation.Properties.Iso6391Code); Tools.DefaultCaption = PluginTranslate.PluginName; Tools.PluginURL = "https://github.com/rookiestyle/earlyupdatecheck/"; PluginConfig.Read(); GlobalWindowManager.WindowAdded += WindowAdded; GlobalWindowManager.WindowRemoved += WindowRemoved; m_tsMenu = new ToolStripMenuItem(PluginTranslate.PluginName + "..."); m_tsMenu.Click += (o, e) => Tools.ShowOptions(); ToolStripMenuItem tsmiUpdate = Tools.FindToolStripMenuItem(m_host.MainWindow.MainMenu.Items, "m_menuHelpCheckForUpdates", true); if (tsmiUpdate != null) { m_tsMenu.Image = tsmiUpdate.Image; } else { m_tsMenu.Image = m_host.MainWindow.ClientIcons.Images[(int)KeePassLib.PwIcon.World]; } m_host.MainWindow.ToolsMenu.DropDownItems.Add(m_tsMenu); Tools.OptionsFormShown += OptionsFormShown; Tools.OptionsFormClosed += OptionsFormClosed; m_host.MainWindow.FormLoadPost += MainWindow_FormLoadPost; PluginUpdateHandler.Init(); return(true); }
private void bUpdateTranslations_Click(object sender, EventArgs e) { List <OwnPluginUpdate> lPlugins = new List <OwnPluginUpdate>(); foreach (PluginUpdate pu in PluginUpdateHandler.Plugins) { OwnPluginUpdate opu = pu as OwnPluginUpdate; if (opu == null) { continue; } if (!PluginUpdateHandler.VersionsEqual(pu.VersionInstalled, pu.VersionAvailable)) { continue; } if (opu.Translations.Count == 0) { continue; } if (!lPlugins.Contains(opu)) { lPlugins.Add(opu); } } if (lPlugins.Count == 0) { PluginTools.PluginDebug.AddInfo("No plugins where translations can be updated", 0); return; } using (TranslationUpdateForm t = new TranslationUpdateForm()) { t.InitEx(lPlugins); if (t.ShowDialog() == DialogResult.OK) { Plugin.UpdatePluginTranslations(PluginConfig.DownloadActiveLanguage, t.SelectedPlugins); } } }
private bool PostProcessDownload(string sTargetFolder, bool bProcessOK) { if (!bProcessOK) { return(false); } //Some plugins contain the plugin version in the filename //Identify this case and trigger deletion of old version string sNewFile = UrlUtil.GetFileName(MergeInVersion(true)); string sOldFile = UrlUtil.GetFileName(MergeInVersion(false)); if (string.Compare(sNewFile, sOldFile, true) == 0) { return(true); } string sNewFileFull = MergeInPluginFolder(PluginUpdateHandler.PluginsFolder) + sNewFile; string sOldFileFull = MergeInPluginFolder(PluginUpdateHandler.PluginsFolder) + sOldFile; //File.Exists is case sensitive if the OS is case sensitive //As ExternalPluginUpdates.xml may contain filenames that don't match because of this, don't rely on File.Exists here bool bExists = false; if (!KeePassLib.Native.NativeLib.IsUnix()) { bExists = File.Exists(sOldFileFull); } else { bExists = UrlUtil.GetFilePaths(MergeInPluginFolder(PluginUpdateHandler.PluginsFolder), "*", SearchOption.TopDirectoryOnly).Find(x => string.Compare(UrlUtil.GetFileName(x), sOldFileFull, true) == 0) != null; } if (bExists && (string.Compare(sOldFileFull, PluginFile, true) == 0)) { PluginUpdateHandler.DeleteSpecialFile(PluginFile); } return(true); }
internal static int MoveFilesToTemp(params string[] files) { // 0 = success // -1 = aborted by user // other value = error string from = string.Empty; foreach (string file in files) { from += file + "\0"; } from += "\0"; string sTemp = PluginUpdateHandler.GetTempFolder() + "\0\0"; SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT(); lpFileOp.hwnd = IntPtr.Zero; lpFileOp.wFunc = FILE_OP_TYPE.FO_MOVE; lpFileOp.pFrom = from; lpFileOp.pTo = sTemp; lpFileOp.fFlags = FILE_OP_FLAGS.FOF_NOCONFIRMMKDIR | FILE_OP_FLAGS.FOF_NOCONFIRMATION | FILE_OP_FLAGS.FOF_ALLOWUNDO; lpFileOp.fAnyOperationsAborted = false; lpFileOp.hNameMappings = IntPtr.Zero; lpFileOp.lpszProgressTitle = string.Empty; int result = SHFileOperation(ref lpFileOp); if (result == 0 && lpFileOp.fAnyOperationsAborted) { result = -1; } PluginDebug.AddInfo("Move in UAC mode: " + result.ToString()); return(result); }
private void UpdateAvailableTranslations() { Dictionary <string, List <UpdateComponentInfo> > dUpdateInfo = new Dictionary <string, List <UpdateComponentInfo> >(); Dictionary <string, long> dResult = new Dictionary <string, long>(); Type t = typeof(KeePass.Program).Assembly.GetType("KeePass.Util.UpdateCheckEx"); if (t == null) { PluginDebug.AddError("Could not locate class 'UpdateCheckEx'", 0); return; } MethodInfo mi = t.GetMethod("DownloadInfoFiles", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Static); if (mi == null) { PluginDebug.AddError("Could not locate method 'DownloadInfoFiles'", 0); return; } if (string.IsNullOrEmpty(VersionURL)) { PluginDebug.AddError("Could not read plugin update url", 0); return; } dUpdateInfo = mi.Invoke(null, new object[] { new List <string>() { VersionURL }, null }) as Dictionary <string, List <UpdateComponentInfo> >; List <string> lTranslationsNew = new List <string>(); string[] cSplit = new string[] { "!", "!!!" }; foreach (KeyValuePair <string, List <UpdateComponentInfo> > kvp in dUpdateInfo) { if (kvp.Value == null) { continue; } Version vCheck = null; foreach (UpdateComponentInfo uci in kvp.Value) { //Github: <Plugin>!<language identifier> string[] sParts = uci.Name.Split(cSplit, StringSplitOptions.RemoveEmptyEntries); if (sParts.Length == 1) { vCheck = new Version(StrUtil.VersionToString(uci.VerAvailable, 2)); if (VersionAvailableIsUnknown()) { VersionAvailable = vCheck; } } if (!PluginUpdateHandler.VersionsEqual(VersionInstalled, vCheck)) { return; //Different version might require different translation files } if (sParts.Length != 2) { continue; } long lVer = 0; if (!long.TryParse(StrUtil.VersionToString(uci.VerAvailable), out lVer)) { continue; } string sLang = Name + "." + sParts[1].ToLowerInvariant() + ".language.xml"; TranslationVersionCheck tvc = Translations.Find(x => x.LangugageFile == sLang); if (tvc == null) { tvc = new TranslationVersionCheck() { LangugageFile = sLang }; Translations.Add(tvc); } tvc.Available = lVer; } } }
private void UpdatePlugins(bool bUpdateTranslationsOnly) { PluginDebug.AddInfo("UpdatePlugins start ", DebugPrint); Form fUpdateLog = null; m_slUpdatePlugins = StatusUtil.CreateStatusDialog(GlobalWindowManager.TopWindow, out fUpdateLog, PluginTranslate.PluginUpdateCaption, string.Empty, true, true); bool success = false; string sTempPluginsFolder = PluginUpdateHandler.GetTempFolder(); ThreadStart ts = new ThreadStart(() => { m_slUpdatePlugins.StartLogging(PluginTranslate.PluginUpdateCaption, false); PluginDebug.AddInfo("Use temp folder", PluginUpdateHandler.Shieldify.ToString(), sTempPluginsFolder, DebugPrint); //Download files foreach (PluginUpdate upd in PluginUpdateHandler.Plugins) { if (!upd.Selected) { continue; } success |= UpdatePlugin(upd, sTempPluginsFolder, bUpdateTranslationsOnly); } }); Thread t = new Thread(ts); t.IsBackground = true; t.Start(); while (true && t.IsAlive) { if (!m_slUpdatePlugins.ContinueWork()) { t.Abort(); break; } } if (t != null && t.IsAlive) { t.Abort(); } if (m_slUpdatePlugins != null) { m_slUpdatePlugins.EndLogging(); m_slUpdatePlugins = null; } if (fUpdateLog != null) { fUpdateLog.Dispose(); } //Move files from temp folder to plugin folder success &= PluginUpdateHandler.MoveAll(sTempPluginsFolder); foreach (var pu in PluginUpdateHandler.Plugins) { if (!pu.Selected) { continue; } if (pu is OwnPluginUpdate) { (pu as OwnPluginUpdate).UpdateTranslationInfo(true); } } if (success) { PluginUpdateHandler.Cleanup(sTempPluginsFolder); } success = true; //Restart KeePass to use new plugin versions PluginDebug.AddInfo("Update finished", "Succes: " + success.ToString(), DebugPrint); if (success && !bUpdateTranslationsOnly) { if (Tools.AskYesNo(PluginTranslate.PluginUpdateSuccess, PluginTranslate.PluginUpdateCaption) == DialogResult.Yes) { if (m_bRestartInvoke) { m_host.MainWindow.Invoke(new KeePassLib.Delegates.GAction(() => { Restart(); })); } else { Restart(); } } } }
private void OnUpdateCheckFormShown(object sender, EventArgs e) { m_lEventHandlerItemActivate = null; PluginDebug.AddSuccess("OUCFS 1", 0); if (!PluginConfig.Active || !PluginConfig.OneClickUpdate) { return; } PluginDebug.AddSuccess("OUCFS 2", 0); CustomListViewEx lvPlugins = (CustomListViewEx)Tools.GetControl("m_lvInfo", sender as UpdateCheckForm); if (lvPlugins == null) { PluginDebug.AddError("m_lvInfo not found", 0); return; } else { PluginDebug.AddSuccess("m_lvInfo found", 0); } PluginUpdateHandler.LoadPlugins(false); if (PluginUpdateHandler.Plugins.Count == 0) { return; } SetPluginSelectionStatus(false); bool bColumnAdded = false; m_lEventHandlerItemActivate = EventHelper.GetItemActivateHandlers(lvPlugins); if (m_lEventHandlerItemActivate.Count > 0) { EventHelper.RemoveItemActivateEventHandlers(lvPlugins, m_lEventHandlerItemActivate); lvPlugins.ItemActivate += LvPlugins_ItemActivate; } //https://github.com/mono/mono/issues/17747 //Do NOT use ListView.SmallImageList if (m_ImgApply == null) { m_ImgApply = (Image)KeePass.Program.Resources.GetObject("B16x16_Apply"); } if (m_ImgUnselected == null) { m_ImgUnselected = m_ImgApply == null ? null : UIUtil.CreateGrayImage(m_ImgApply); } foreach (ListViewItem item in lvPlugins.Items) { PluginDebug.AddInfo("Check plugin update status", 0, item.SubItems[0].Text, item.SubItems[1].Text); if (!item.SubItems[1].Text.Contains(KeePass.Resources.KPRes.NewVersionAvailable)) { continue; } foreach (PluginUpdate upd in PluginUpdateHandler.Plugins) { if (item.SubItems[0].Text != upd.Title) { continue; } if (upd.UpdateMode == UpdateOtherPluginMode.Unknown) { continue; } if (!bColumnAdded) { lvPlugins.Columns.Add(PluginTranslate.PluginUpdate); bColumnAdded = true; } ListViewItem.ListViewSubItem lvsiUpdate = new ListViewItem.ListViewSubItem(item, PluginTranslate.PluginUpdate); lvsiUpdate.Tag = upd; item.SubItems.Add(lvsiUpdate); upd.Selected = true; try { upd.VersionAvailable = new Version(item.SubItems[3].Text); } catch (Exception ex) { PluginDebug.AddError("Could not parse new version", 0, upd.Name, item.SubItems[3].Text, ex.Message); } break; } } if (bColumnAdded) { UIUtil.ResizeColumns(lvPlugins, new int[] { 3, 3, 2, 2, 1 }, true); lvPlugins.MouseClick += OnUpdateCheckFormPluginMouseClick; lvPlugins.OwnerDraw = true; lvPlugins.DrawSubItem += LvPlugins_DrawSubItem; lvPlugins.DrawColumnHeader += LvPlugins_DrawColumnHeader; ShowUpdateButton(sender as Form, true); } if (m_lEventHandlerItemActivate.Count == 0) { if (lvPlugins.ContextMenuStrip == null) { lvPlugins.ContextMenuStrip = new ContextMenuStrip(); string sMenuText = KeePass.Resources.KPRes.PluginsDesc; try { sMenuText = Tools.GetControl("m_linkPlugins", sender as UpdateCheckForm).Text; } catch { } lvPlugins.ContextMenuStrip.Items.Add(new ToolStripMenuItem(sMenuText, null, OnReleasePageClick)); lvPlugins.ContextMenuStrip.Opening += ContextMenuStrip_Opening; } else { PluginDebug.AddWarning("m_lvEntries.ContextMenuStrip already defined, special handling for added 'go to release page' to be defined", 0); } } }