1 /* 2 KeePass Password Safe - The Open-Source Password Manager 3 Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 using System; 21 using System.Collections.Generic; 22 using System.ComponentModel; 23 using System.Diagnostics; 24 using System.Drawing; 25 using System.IO; 26 using System.Text; 27 using System.Windows.Forms; 28 29 using KeePass.App; 30 using KeePass.App.Configuration; 31 using KeePass.Resources; 32 using KeePass.UI; 33 using KeePass.Util; 34 using KeePass.Util.XmlSerialization; 35 36 using KeePassLib; 37 using KeePassLib.Translation; 38 using KeePassLib.Utility; 39 40 namespace KeePass.Forms 41 { 42 public partial class LanguageForm : Form, IGwmWindow 43 { 44 private ImageList m_ilIcons = null; 45 46 public bool CanCloseWithoutDataLoss { get { return true; } } 47 LanguageForm()48 public LanguageForm() 49 { 50 InitializeComponent(); 51 GlobalWindowManager.InitializeForm(this); 52 } 53 InitEx()54 public bool InitEx() 55 { 56 try 57 { 58 string strDir = UrlUtil.GetFileDirectory(WinUtil.GetExecutable(), 59 false, true); 60 List<string> l = UrlUtil.GetFilePaths(strDir, "*." + 61 KPTranslation.FileExtension, SearchOption.TopDirectoryOnly); 62 if(l.Count != 0) 63 { 64 string str = KPRes.LngInAppDir + MessageService.NewParagraph; 65 66 const int cMaxFL = 6; 67 for(int i = 0; i < Math.Min(l.Count, cMaxFL); ++i) 68 { 69 if(i == (cMaxFL - 1)) str += "..."; 70 else str += l[i]; 71 str += MessageService.NewLine; 72 } 73 str += MessageService.NewLine; 74 75 str += KPRes.LngInAppDirNote + MessageService.NewParagraph; 76 str += KPRes.LngInAppDirQ; 77 78 if(MessageService.AskYesNo(str, PwDefs.ShortProductName, true, 79 MessageBoxIcon.Warning)) 80 { 81 WinUtil.OpenUrlDirectly(strDir); 82 return false; 83 } 84 } 85 } 86 catch(Exception) { Debug.Assert(false); } 87 88 return true; 89 } 90 OnFormLoad(object sender, EventArgs e)91 private void OnFormLoad(object sender, EventArgs e) 92 { 93 GlobalWindowManager.AddWindow(this, this); 94 95 BannerFactory.CreateBannerEx(this, m_bannerImage, 96 Properties.Resources.B48x48_Keyboard_Layout, 97 KPRes.SelectLanguage, KPRes.SelectLanguageDesc); 98 this.Icon = AppIcons.Default; 99 this.Text = KPRes.SelectLanguage; 100 101 UIUtil.SetExplorerTheme(m_lvLanguages, true); 102 103 List<Image> lImg = new List<Image>(); 104 lImg.Add(Properties.Resources.B16x16_Browser); 105 106 m_ilIcons = UIUtil.BuildImageListUnscaled(lImg, 107 DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16)); 108 m_lvLanguages.SmallImageList = m_ilIcons; 109 110 m_lvLanguages.Columns.Add(KPRes.InstalledLanguages); 111 m_lvLanguages.Columns.Add(KPRes.Version); 112 m_lvLanguages.Columns.Add(KPRes.Author); 113 m_lvLanguages.Columns.Add(KPRes.Contact); 114 m_lvLanguages.Columns.Add(KPRes.File); 115 116 KPTranslation trlEng = new KPTranslation(); 117 trlEng.Properties.NameEnglish = "English"; 118 trlEng.Properties.NameNative = "English"; 119 trlEng.Properties.ApplicationVersion = PwDefs.VersionString; 120 trlEng.Properties.AuthorName = AppDefs.DefaultTrlAuthor; 121 trlEng.Properties.AuthorContact = AppDefs.DefaultTrlContact; 122 123 string strDirA = AceApplication.GetLanguagesDir(AceDir.App, false); 124 string strDirASep = UrlUtil.EnsureTerminatingSeparator(strDirA, false); 125 string strDirU = AceApplication.GetLanguagesDir(AceDir.User, false); 126 127 List<KeyValuePair<string, KPTranslation>> lTrls = 128 new List<KeyValuePair<string, KPTranslation>>(); 129 lTrls.Add(new KeyValuePair<string, KPTranslation>(string.Empty, trlEng)); 130 AddTranslations(strDirA, lTrls); 131 if(WinUtil.IsAppX) AddTranslations(strDirU, lTrls); 132 lTrls.Sort(LanguageForm.CompareTrlItems); 133 134 foreach(KeyValuePair<string, KPTranslation> kvp in lTrls) 135 { 136 KPTranslationProperties p = kvp.Value.Properties; 137 string strName = p.NameEnglish + " (" + p.NameNative + ")"; 138 string strVer = PwDefs.GetTranslationDisplayVersion(p.ApplicationVersion); 139 bool bBuiltIn = ((kvp.Key.Length == 0) || (WinUtil.IsAppX && 140 kvp.Key.StartsWith(strDirASep, StrUtil.CaseIgnoreCmp))); 141 142 ListViewItem lvi = m_lvLanguages.Items.Add(strName, 0); 143 lvi.SubItems.Add(strVer); 144 lvi.SubItems.Add(p.AuthorName); 145 lvi.SubItems.Add(p.AuthorContact); 146 lvi.SubItems.Add(bBuiltIn ? KPRes.BuiltInU : kvp.Key); 147 lvi.Tag = kvp.Key; 148 149 // try 150 // { 151 // string nl = MessageService.NewLine; 152 // lvi.ToolTipText = strName + " " + strVer + nl + p.AuthorName + 153 // nl + p.AuthorContact + nl + nl + kvp.Key; 154 // } 155 // catch(Exception) { Debug.Assert(false); } // Too long? 156 157 // if(kvp.Key.Equals(Program.Config.Application.GetLanguageFilePath(), 158 // StrUtil.CaseIgnoreCmp)) 159 // UIUtil.SetFocusedItem(m_lvLanguages, lvi, true); 160 } 161 162 UIUtil.ResizeColumns(m_lvLanguages, new int[] { 5, 2, 5, 5, 3 }, true); 163 } 164 AddTranslations(string strDir, List<KeyValuePair<string, KPTranslation>> lTrls)165 private static void AddTranslations(string strDir, 166 List<KeyValuePair<string, KPTranslation>> lTrls) 167 { 168 try 169 { 170 List<string> lFiles = UrlUtil.GetFilePaths(strDir, "*." + 171 KPTranslation.FileExtension, SearchOption.TopDirectoryOnly); 172 foreach(string strFilePath in lFiles) 173 { 174 try 175 { 176 XmlSerializerEx xs = new XmlSerializerEx(typeof(KPTranslation)); 177 KPTranslation t = KPTranslation.Load(strFilePath, xs); 178 179 if(t != null) 180 lTrls.Add(new KeyValuePair<string, KPTranslation>( 181 strFilePath, t)); 182 else { Debug.Assert(false); } 183 } 184 catch(Exception ex) { MessageService.ShowWarning(ex); } 185 } 186 187 Debug.Assert(KPTranslation.FileExtension != KPTranslation.FileExtension1x); 188 189 lFiles = UrlUtil.GetFilePaths(strDir, "*." + 190 KPTranslation.FileExtension1x, SearchOption.TopDirectoryOnly); 191 foreach(string strFilePath in lFiles) 192 { 193 KPTranslation t = new KPTranslation(); 194 t.Properties.NameEnglish = UrlUtil.StripExtension( 195 UrlUtil.GetFileName(strFilePath)); 196 t.Properties.NameNative = KPRes.Incompatible; 197 t.Properties.ApplicationVersion = "1.x"; 198 t.Properties.AuthorName = "?"; 199 t.Properties.AuthorContact = "?"; 200 201 lTrls.Add(new KeyValuePair<string, KPTranslation>( 202 strFilePath, t)); 203 } 204 } 205 catch(Exception) { } // Directory might not exist or cause access violation 206 } 207 CompareTrlItems(KeyValuePair<string, KPTranslation> a, KeyValuePair<string, KPTranslation> b)208 private static int CompareTrlItems(KeyValuePair<string, KPTranslation> a, 209 KeyValuePair<string, KPTranslation> b) 210 { 211 KPTranslationProperties pA = a.Value.Properties; 212 KPTranslationProperties pB = b.Value.Properties; 213 214 int c = StrUtil.CompareNaturally(pA.NameEnglish, pB.NameEnglish); 215 if(c != 0) return c; 216 217 c = StrUtil.CompareNaturally(pA.NameNative, pB.NameNative); 218 if(c != 0) return c; 219 220 c = StrUtil.CompareNaturally(pA.ApplicationVersion, pB.ApplicationVersion); 221 if(c != 0) return ((c < 0) ? 1 : -1); // Descending 222 223 return string.Compare(a.Key, b.Key, StrUtil.CaseIgnoreCmp); 224 } 225 OnBtnClose(object sender, EventArgs e)226 private void OnBtnClose(object sender, EventArgs e) 227 { 228 } 229 OnLanguagesItemActivate(object sender, EventArgs e)230 private void OnLanguagesItemActivate(object sender, EventArgs e) 231 { 232 ListView.SelectedListViewItemCollection lvic = m_lvLanguages.SelectedItems; 233 if((lvic == null) || (lvic.Count != 1)) return; 234 235 string strSel = ((lvic[0].Tag as string) ?? string.Empty); 236 237 if(strSel.EndsWith("." + KPTranslation.FileExtension1x, StrUtil.CaseIgnoreCmp)) 238 { 239 string strMsg = strSel + MessageService.NewParagraph + KPRes.Lng1xSel + 240 MessageService.NewParagraph + KPRes.Lng2xWeb + MessageService.NewLine; 241 string strUrl = PwDefs.TranslationsUrl; 242 string strVtd = strMsg + VistaTaskDialog.CreateLink(strUrl, strUrl); 243 244 VistaTaskDialog vtd = new VistaTaskDialog(); 245 vtd.AddButton((int)DialogResult.Cancel, KPRes.Ok, null); 246 vtd.Content = strVtd; 247 vtd.DefaultButtonID = (int)DialogResult.Cancel; 248 vtd.EnableHyperlinks = true; 249 vtd.SetIcon(VtdIcon.Warning); 250 vtd.WindowTitle = PwDefs.ShortProductName; 251 252 if(!vtd.ShowDialog()) 253 MessageService.ShowWarning(strMsg + strUrl); 254 return; 255 } 256 257 // The following creates confusion when the configured language 258 // is different from the loaded language (which can occur when 259 // the language file has been deleted/moved) 260 // if(strSel.Equals(Program.Config.Application.GetLanguageFilePath(), 261 // StrUtil.CaseIgnoreCmp)) 262 // return; // Is active already, do not close the dialog 263 264 Program.Config.Application.SetLanguageFilePath(strSel); 265 this.DialogResult = DialogResult.OK; 266 } 267 OnFormClosed(object sender, FormClosedEventArgs e)268 private void OnFormClosed(object sender, FormClosedEventArgs e) 269 { 270 if(m_ilIcons != null) 271 { 272 m_lvLanguages.SmallImageList = null; 273 m_ilIcons.Dispose(); 274 m_ilIcons = null; 275 } 276 else { Debug.Assert(false); } 277 278 GlobalWindowManager.RemoveWindow(this); 279 } 280 OnBtnGetMore(object sender, EventArgs e)281 private void OnBtnGetMore(object sender, EventArgs e) 282 { 283 WinUtil.OpenUrl(PwDefs.TranslationsUrl, null); 284 this.DialogResult = DialogResult.Cancel; 285 } 286 OnBtnOpenFolder(object sender, EventArgs e)287 private void OnBtnOpenFolder(object sender, EventArgs e) 288 { 289 try 290 { 291 AceDir d = (WinUtil.IsAppX ? AceDir.User : AceDir.App); 292 293 // try 294 // { 295 // string strU = AceApplication.GetLanguagesDir(AceDir.User, false); 296 // List<string> l = UrlUtil.GetFilePaths(strU, "*." + 297 // KPTranslation.FileExtension, SearchOption.TopDirectoryOnly); 298 // if(l.Count > 0) d = AceDir.User; 299 // } 300 // catch(Exception) { } 301 302 string str = AceApplication.GetLanguagesDir(d, false); 303 if(!Directory.Exists(str)) Directory.CreateDirectory(str); 304 305 WinUtil.OpenUrlDirectly(str); 306 this.DialogResult = DialogResult.Cancel; 307 } 308 catch(Exception ex) { MessageService.ShowWarning(ex); } 309 } 310 } 311 } 312