├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── translation.md ├── .gitignore ├── EarlyUpdateCheck.sln ├── ExternalPluginUpdates ├── ExternalPluginUpdates.xml └── ExternalPluginUpdatesUser.xml ├── LICENSE ├── Translations ├── EarlyUpdateCheck.de.language.xml ├── EarlyUpdateCheck.fr.language.xml ├── EarlyUpdateCheck.it.language.xml ├── EarlyUpdateCheck.ja.language.xml ├── EarlyUpdateCheck.pt.language.xml ├── EarlyUpdateCheck.ru.language.xml ├── EarlyUpdateCheck.template.language.xml └── EarlyUpdateCheck.zh.language.xml ├── externalplugininfocopy.cmd ├── images ├── EarlyUpdateCheck KeePass Update.png ├── EarlyUpdateCheck One Click Update 1.png ├── EarlyUpdateCheck One Click Update 2.png ├── EarlyUpdateCheck One Click Update UAC.png ├── EarlyUpdateCheck checking.png └── EarlyUpdateCheck options.png ├── plgxcreate.cmd ├── plgxexclude.txt ├── readme.md ├── src ├── CheckedGroupBox.cs ├── EarlyUpdateCheck.cs ├── EarlyUpdateCheck.csproj ├── Options.Designer.cs ├── Options.cs ├── PluginUpdateInfo.cs ├── Properties │ └── AssemblyInfo.cs ├── TranslationUpdateForm.Designer.cs ├── TranslationUpdateForm.cs └── Utilities │ ├── Debug.cs │ ├── EUC_EventHelper.cs │ ├── PluginTranslation.cs │ ├── Tools_Controls.cs │ ├── Tools_Main.cs │ ├── Tools_Options.cs │ └── Util.cs ├── translationcopy.cmd └── version.info /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | custom: http://paypal.com/cgi-bin/webscr?cmd=_donations&business=rookiestyle%40gmx%2enet¤cy_code=EUR&lc=en_DE&item_name=EarlyUpdateCheck 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Found a bug? Report it to get it fixed 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Overview 11 | [TIP]: # (DO NOT include screenshots of your actual database) 12 | [TIP]: # (DO NOT post sensitive data of any kind) 13 | [NOTE]: # (Give a BRIEF summary about your problem) 14 | 15 | 16 | ## Steps to Reproduce 17 | [NOTE]: # (Provide a simple set of steps to reproduce this bug) 18 | 1. 19 | 2. 20 | 3. 21 | 22 | ## Expected Behavior 23 | [NOTE]: # (Describe how you expect the plugin to behave) 24 | 25 | 26 | ## Actual Behavior 27 | [NOTE]: # (Describe how the plugin actually behaves) 28 | 29 | 30 | ## Context 31 | [NOTE]: # (Provide any additional information you may have) 32 | OS: 33 | KeePass Version: 34 | Plugin Version: 35 | 36 | [NOTE]: # (If possible, please attach a debug file. Have a look at the wiki for details.) 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this plugin 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Summary 11 | [TIP]: # (DO NOT include screenshots of your actual database) 12 | [TIP]: # (DO NOT post sensitive data of any kind) 13 | [NOTE]: # (Provide a brief overview of what the new feature is all about) 14 | 15 | 16 | ## Added value 17 | [NOTE]: # (Describe how you and other users would benefit from this feature) 18 | 19 | 20 | ## Example 21 | [NOTE]: # (Show a picture or a mock-up if applicable) 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/translation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Translation 3 | about: New or updated translation 4 | title: 'Translation: ' 5 | labels: translation 6 | assignees: '' 7 | 8 | --- 9 | 10 | [NOTE]: # (Please do not forget to attach the translation file) 11 | Language: 12 | - [ ] New translation 13 | - [ ] Update existing translation 14 | - [ ] If updated: Only added missing Texts 15 | - [ ] All relevant texts translated 16 | 17 | [NOTE]: # (A text is relevant if the standard text in english language is NOT sufficient) 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ -------------------------------------------------------------------------------- /EarlyUpdateCheck.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30907.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EarlyUpdateCheck", "src\EarlyUpdateCheck.csproj", "{78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\_KeePass_Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{40E2AC4E-540E-4809-930E-0E9290D2A9F7}" 11 | ProjectSection(SolutionItems) = preProject 12 | ExternalPluginUpdates\ExternalPluginUpdates.xml = ExternalPluginUpdates\ExternalPluginUpdates.xml 13 | plgxcreate.cmd = plgxcreate.cmd 14 | version.info = version.info 15 | EndProjectSection 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | ReleasePlgx|Any CPU = ReleasePlgx|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}.ReleasePlgx|Any CPU.ActiveCfg = ReleasePlgx|Any CPU 26 | {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}.ReleasePlgx|Any CPU.Build.0 = ReleasePlgx|Any CPU 27 | {10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {10938016-DEE2-4A25-9A5A-8FD3444379CA}.ReleasePlgx|Any CPU.ActiveCfg = Release|Any CPU 30 | {10938016-DEE2-4A25-9A5A-8FD3444379CA}.ReleasePlgx|Any CPU.Build.0 = Release|Any CPU 31 | EndGlobalSection 32 | GlobalSection(SolutionProperties) = preSolution 33 | HideSolutionNode = FALSE 34 | EndGlobalSection 35 | GlobalSection(ExtensibilityGlobals) = postSolution 36 | SolutionGuid = {11D5832F-9BE1-4F98-82AA-B4A2547C0EDE} 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /ExternalPluginUpdates/ExternalPluginUpdates.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 22 14 | 15 | WebAutoType 16 | https://sourceforge.net/projects/webautotype/ 17 | https://sourceforge.net/projects/webautotype/files/latest/download 18 | ZipExtractPlgx 19 | True 20 | 21 | 22 | HotKeyEnabler 23 | https://sourceforge.net/projects/hotkeyenabler/ 24 | https://sourceforge.net/projects/hotkeyenabler/files/latest/download 25 | ZipExtractPlgx 26 | True 27 | 28 | 29 | KPEnhancedEntryView 30 | https://sourceforge.net/projects/kpenhentryview/ 31 | https://sourceforge.net/projects/kpenhentryview/files/latest/download 32 | ZipExtractPlgx 33 | True 34 | 35 | 36 | SourceForgeUpdateChecker 37 | https://sourceforge.net/projects/kpsfupdatechecker/ 38 | https://sourceforge.net/projects/kpsfupdatechecker/files/latest/download 39 | ZipExtractPlgx 40 | True 41 | 42 | 43 | KeeParanoia 44 | https://sourceforge.net/projects/keeparanoia/ 45 | https://sourceforge.net/projects/keeparanoia/files/latest/download 46 | ZipExtractPlgx 47 | True 48 | 49 | 50 | KeePass Pronounceable Password Generator 51 | https://sourceforge.net/projects/pronouncepwgen/ 52 | https://sourceforge.net/projects/pronouncepwgen/files/latest/download 53 | ZipExtractPlgx 54 | True 55 | 56 | 57 | KeeOtp2 58 | https://github.com/tiuub/KeeOtp2#keeotp2 59 | https://github.com/tiuub/KeeOtp2/releases/latest/download/KeeOtp2.plgx 60 | PlgxDirect 61 | False 62 | 63 | 64 | KeeTheme 65 | https://keepass.info/plugins.html#keetheme 66 | https://github.com/xatupal/KeeTheme/releases/latest/download/KeeTheme.plgx 67 | PlgxDirect 68 | False 69 | 70 | 71 | KoenZomers.KeePass.OneDriveSync 72 | https://github.com/KoenZomers/KeePassOneDriveSync#keepass-onedrive-sync 73 | https://github.com/KoenZomers/KeePassOneDriveSync/releases/latest/download/KeeOneDriveSync.plgx 74 | PlgxDirect 75 | False 76 | 77 | 78 | KeePass Sync For Google Drive 79 | https://github.com/walterpg/google-drive-sync/releases 80 | 81 | https://github.com/walterpg/google-drive-sync/releases/download/v4.0.6-beta/KPSyncForDrive-{major}.{minor}.{build}-beta.plgx 82 | PlgxDirect 83 | False 84 | 85 | 86 | KPSync For Google Drive 87 | https://github.com/walterpg/google-drive-sync/releases 88 | https://github.com/walterpg/google-drive-sync/releases/latest/download/KPSyncForDrive-{major}.{minor}.{build!}.plgx 89 | PlgxDirect 90 | False 91 | 92 | 93 | KeeAutoExec 94 | https://keepass.info/plugins.html#keeautoexec 95 | https://keepass.info/extensions/v2/keeautoexec/KeeAutoExec-{major}{.minor}{.build}.zip 96 | ZipExtractPlgx 97 | True 98 | 99 | 100 | HIBPOfflineCheck 101 | https://keepass.info/plugins.html#breachchk 102 | https://github.com/mihaifm/HIBPOfflineCheck/releases/latest/download/HIBPOfflineCheck.plgx 103 | PlgxDirect 104 | False 105 | 106 | 107 | KeePassQRCodeView 108 | https://keepass.info/plugins.html#qrcodeview 109 | https://github.com/JanisEst/KeePassQRCodeView/releases/latest/download/KeePassQRCodeView.plgx 110 | PlgxDirect 111 | False 112 | 113 | 114 | SftpSync 115 | https://github.com/shellster/keepass-sftp-sync#keepass-sftpsync 116 | https://github.com/shellster/keepass-sftp-sync/releases/latest/download/SftpSync.plgx 117 | PlgxDirect 118 | False 119 | 120 | 121 | Yet Another Favicon Downloader 122 | https://keepass.info/plugins.html#yafd 123 | https://github.com/navossoc/KeePass-Yet-Another-Favicon-Downloader/releases/latest/download/YetAnotherFaviconDownloader.plgx 124 | PlgxDirect 125 | False 126 | 127 | 128 | ExeIconPicker 129 | https://keepass.info/plugins.html#exeiconpicker 130 | https://github.com/Eveldee/KeePass-ExeIconPicker/releases/latest/download/ExeIconPicker.plgx 131 | PlgxDirect 132 | False 133 | 134 | 135 | KeeAnywhere 136 | https://keepass.info/plugins.html#keeanywhere 137 | https://github.com/Kyrodan/KeeAnywhere/releases/latest/download/KeeAnywhere-{major}.{minor}.{build}.plgx 138 | PlgxDirect 139 | False 140 | 141 | 142 | KeePassNatMsg 143 | https://keepass.info/plugins.html#keepassnatmsg 144 | https://github.com/smorks/keepassnatmsg/releases/latest/download/KeePassNatMsg.plgx 145 | PlgxDirect 146 | False 147 | 148 | 149 | KeePassRPC 150 | https://keepass.info/plugins.html#keepassrpc 151 | https://github.com/kee-org/keepassrpc/releases/latest/download/KeePassRPC.plgx 152 | PlgxDirect 153 | False 154 | 155 | 156 | KeeSetPriority 157 | https://github.com/jalorodri/KeeSetPriority/ 158 | https://github.com/jalorodri/KeeSetPriority/releases/latest/download/KeeSetPriority.plgx 159 | PlgxDirect 160 | False 161 | 162 | 163 | 164 | Entry Templates for KeePass 165 | https://keepass.info/plugins.html#kpentrytemplates 166 | https://github.com/mitchcapper/KPEntryTemplates/releases/latest/download/KPEntryTemplates.plgx 167 | PlgxDirect 168 | False 169 | 170 | 171 | 172 | KeePassWinHello 173 | https://github.com/sirAndros/KeePassWinHello/ 174 | https://github.com/sirAndros/KeePassWinHello/releases/latest/download/KeePassWinHelloPlugin.plgx 175 | PlgxDirect 176 | False 177 | 178 | 179 | 180 | KPSimpleBackup 181 | https://github.com/marvinweber/KPSimpleBackup/ 182 | https://github.com/marvinweber/KPSimpleBackup/releases/latest/download/KPSimpleBackup-v{major}.{minor}.{build!}.zip 183 | ZipExtractPlgx 184 | False 185 | 186 | 187 | 188 | DataBaseBackup 189 | https://keepass.info/plugins.html#databasebackup 190 | https://keepass.info/extensions/v2/databasebackup/DataBaseBackup-{major}.{minor}.{build}.{revision}.zip 191 | ZipExtractPlgx 192 | False 193 | 194 | 195 | 196 | Have I Been Pwned Plugin 197 | https://github.com/kapsiR/HaveIBeenPwnedKeePassPlugin 198 | https://github.com/kapsiR/HaveIBeenPwnedKeePassPlugin/releases/download/v{major}.{minor}.{build}/HaveIBeenPwnedPlugin.dll 199 | DllDirect 200 | False 201 | 202 | 203 | 204 | ITanMaster 205 | https://keepass.info/plugins.html#itanmaster 206 | https://keepass.info/extensions/v2/itanmaster/iTanMaster-{major}.{minor}.{build}.{revision}.zip 207 | ZipExtractPlgx 208 | False 209 | 210 | 211 | 212 | KeePassHIBP 213 | https://github.com/JanisEst/KeePassHIBP 214 | https://github.com/JanisEst/KeePassHIBP/releases/download/v{major}.{minor}/KeePassHIBP.plgx 215 | PlgxDirect 216 | False 217 | 218 | 219 | Title Display 220 | http://gogogadgetscott.info/keepass/titledisplay/ 221 | http://gogogadgetscott.info/keepass/titledisplay/TitleDisplay-{major}.{minor}.zip 222 | ZipExtractPlgx 223 | False 224 | 225 | 226 | KeeAgent 227 | https://github.com/dlech/KeeAgent/ 228 | https://github.com/dlech/KeeAgent/releases/latest/download/KeeAgent_v{MAJOR}.{MINOR}.{BUILD}.zip 229 | ZipExtractPlgx 230 | False 231 | 232 | 233 | 234 | KeePassDiceware 235 | https://github.com/cmdwtf/KeePassDiceware/ 236 | https://github.com/cmdwtf/KeePassDiceware/releases/latest/download/KeePassDiceware.dll 237 | DllDirect 238 | False 239 | 240 | 241 | 242 | The Disambiguator 243 | https://github.com/drventure/Disambiguator 244 | https://github.com/drventure/Disambiguator/releases/download/v{MAJOR}.{MINOR}.{BUILD}.{REVISION}/Disambiguator-v{MAJOR}.{MINOR}.{BUILD}.{REVISION}.zip 245 | ZipExtractPlgx 246 | True 247 | 248 | 249 | AutoTypeSearch 250 | https://keepass.info/plugins.html#atsearch 251 | https://sourceforge.net/projects/autotypesearch/files/latest/download 252 | ZipExtractPlgx 253 | False 254 | 255 | 256 | AutoTypeSplitter 257 | https://keepass.info/plugins.html#atsplit 258 | https://github.com/xatupal/AutoTypeSplitter/releases/latest/download/AutoTypeSplitter.plgx 259 | PlgxDirect 260 | False 261 | 262 | 263 | CheckPasswordBox 264 | https://keepass.info/plugins.html#chkpwbox 265 | https://sourceforge.net/projects/checkpasswordbox/files/latest/download 266 | ZipExtractPlgx 267 | False 268 | 269 | 270 | Custom Icon Dashboarder 271 | https://keepass.info/plugins.html#icondashb 272 | https://github.com/incognito1234/KeePass-Custom-Icon-Dashboarder/releases/latest/download/CustomIconDashboarder.plgx 273 | PlgxDirect 274 | False 275 | 276 | 277 | Fields Admin Console 278 | https://keepass.info/plugins.html#kpfieldsadmin 279 | https://sourceforge.net/projects/kpfieldsadminconsole/files/latest/download 280 | PlgxDirect 281 | False 282 | 283 | 284 | PasswordAgeColumn 285 | https://github.com/tiuub/PasswordAgeColumn 286 | https://github.com/tiuub/PasswordAgeColumn/releases/latest/download/PasswordAgeColumn.plgx 287 | PlgxDirect 288 | False 289 | 290 | 291 | AutoTypeShow 292 | https://sourceforge.net/projects/autotypeshow/ 293 | https://sourceforge.net/projects/autotypeshow/files/latest/download 294 | ZipExtractPlgx 295 | False 296 | 297 | 298 | EditEntryGroup 299 | https://sourceforge.net/projects/editentrygroup/ 300 | https://sourceforge.net/projects/editentrygroup/files/latest/download 301 | ZipExtractPlgx 302 | False 303 | 304 | 305 | KeeModifiedBy 306 | https://keepass.info/plugins.html#keemodifiedby 307 | https://keepass.info/extensions/v2/keemodifiedby/KeeModifiedBy-{major}{.minor}{.build}.zip 308 | ZipExtractPlgx 309 | True 310 | 311 | 312 | OtpKeyProv 313 | https://keepass.info/plugins.html#otpkeyprov 314 | https://keepass.info/extensions/v2/otpkeyprov/OtpKeyProv-{major}{.minor}{.build}.zip 315 | ZipExtractPlgx 316 | True 317 | 318 | 319 | TwoFactorQRCodeReader 320 | https://sourceforge.net/projects/twofactorqrcodereader/ 321 | https://sourceforge.net/projects/twofactorqrcodereader/files/latest/download 322 | ZipExtractPlgx 323 | False 324 | 325 | 326 | KeeResize 327 | https://keepass.info/extensions/v2/keeresize/ 328 | https://keepass.info/extensions/v2/keeresize/KeeResize-{major}{.minor}{.build}.zip 329 | ZipExtractAll 330 | True 331 | 332 | 333 | Readable Passphrase Plugin 334 | https://github.com/ligos/readablepassphrasegenerator 335 | https://github.com/ligos/readablepassphrasegenerator/releases/download/release-{major}.{minor}.{build}/ReadablePassphrase.{major}.{minor}.{build}.plgx 336 | PlgxDirect 337 | False 338 | 339 | 340 | KeeUIExt 341 | https://keepass.info/plugins.html#keeuiext 342 | https://keepass.info/extensions/v2/keeuiext/KeeUIExt-{major}{.minor}{.build}.zip 343 | ZipExtractPlgx 344 | True 345 | 346 | 347 | -------------------------------------------------------------------------------- /ExternalPluginUpdates/ExternalPluginUpdatesUser.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 22 | 23 | 24 | 30 | 31 | -------------------------------------------------------------------------------- /Translations/EarlyUpdateCheck.de.language.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 9 8 | 9 | Active 10 | Aktiv 11 | 12 | 13 | CheckSync 14 | Update-Überprüfung im Vordergrund durchführen 15 | 16 | 17 | CheckSyncDesc 18 | Wenn EarlyUpdateCheck aktiv ist, wird die Update-Überprüfung IMMER zum frühestmöglichen Zeitpunkt gestartet. 19 | 20 | Wenn diese Option aktiv ist, dann wird zusätzlich das Fenster 'Datenbank öffnen' erst nach Abschluss der Update-Überprüfung angezeigt. 21 | 22 | 23 | EnterBackgroundMode 24 | Im Hintergrund weitersuchen 25 | 26 | 27 | PluginUpdateOneClick 28 | Ein-Klick Plugin-Update 29 | 30 | 31 | PluginUpdateOneClickDesc 32 | Neue Versionen meiner Plugins können durch Klick auf das Plugin im Fenster 'Update-Überprüfung' installiert werden. 33 | Schreibzugriff auf den Plugin-Ordner von KeePass ist erforderlich. 34 | Um die neuen Versionen zu nutzen, muss KeePass neu gestartet werden. 35 | 36 | Pflege Datei ExternalPluginUpdates.xml um Plugins anderer Autoren automatisch zu aktualisieren. Im Wiki findest du mehr Informationen 37 | 38 | 39 | PluginUpdate 40 | Update 41 | 42 | 43 | PluginUpdateKeePass 44 | Aktualisiere KeePass 45 | 46 | 47 | PluginUpdateSelected 48 | Aktualisiere Plugins 49 | 50 | 51 | PluginUpdateCaption 52 | Early Update Check - Plugin Updater 53 | 54 | 55 | PluginUpdating 56 | Update von {0} läuft, bitte warten... 57 | 58 | 59 | PluginUpdateSuccess 60 | Das Update war erfolgreich. Neue Pluginversionen sind nach einem Neustart von KeePass aktiv. 61 | Jetzt neu starten? 62 | 63 | 64 | PluginUpdateFailed 65 | Die heruntergeladenen Dateien konnten nicht in den Plugin-Ordner verschoben werden. 66 | Temporären Ordner mit heruntergeladenen Dateien anzeigen? 67 | 68 | 69 | PluginUpdateFailedSpecific 70 | Plugin: {0} 71 | Das Update ist fehlgeschlagen. 72 | 73 | 74 | PluginTranslationUpdateFailed 75 | Plugin: {0} 76 | Das Update der Sprachdatei {1} ist fehlgeschlagen. 77 | 78 | 79 | TryUAC 80 | Das Update konnte nicht abgeschlossen werden. Alternative Möglichkeit versuchen? 81 | Die Windows Benutzerkontensteuerung wird eventuell angezeigt und muss bestätigt werden. 82 | 83 | 84 | OpenTempFolder 85 | Temporären Ordner mit heruntergeladenen Dateien anzeigen? 86 | 87 | 88 | TranslationDownload_Update 89 | Übersetzungen aktualisieren 90 | 91 | 92 | TranslationDownload_DownloadCurrent 93 | Immer Übersetzung für aktive Sprache aktualisieren: {0} 94 | 95 | 96 | TranslationUpdateForm 97 | Early Update Check - Übersetzungen aktualisieren 98 | 99 | 100 | SelectPluginsForTranslationUpdate 101 | Bitte wähle die Plugins aus, bei denen aktualisierte Übersetzungen installiert werden sollen. 102 | 103 | 104 | UpdateExternalInfo 105 | Eine neue Version von ExternalPluginUpdates.xml steht zur Verfügung. 106 | Herunterladen, um mehr Plugins automatisch aktualisieren zu können? 107 | 108 | 109 | UpdateExternalInfoInitialDownload 110 | EarlyUpdateCheck kann auch Plugins anderer Entwickler aktualisieren. 111 | Dazu ist die Datei ExternalPluginUpdates.xml erforderlich. 112 | Soll diese Datei jetzt geladen werden? 113 | 114 | Diese Frage wird nicht erneut gestellt. 115 | Wenn du diese Funktion jetzt nicht nutzen willst, dann kannst du die Datei auch später in den Option von EarlyUpdatecheck laden. 116 | 117 | 118 | UpdateExternalInfoDownload 119 | Download ExternalPluginUpdates.xml 120 | 121 | 122 | KeePassUpdate_InstallZip 123 | EarlyUpdateCheck hat die aktuellste portable Version von KeePass heruntergeladen. 124 | 125 | Die heruntergeladenen Dateien werden in einem neuen Fenster geöffnet. 126 | Zum Aktualisieren bitte KeePass schließen und die heruntergeladenen Dateien in deinen KeePass-Ordner kopieren. 127 | 128 | 129 | KeePassUpdate_InstallSetupOrMsi 130 | EarlyUpdateCheck hat die aktuellste Version von KeePass geladen. 131 | 132 | Zum Aktualisieren muss KeePass geschlossen werden. 133 | 134 | Klicke {0}, um das Update jetzt zu starten. 135 | Klicke {1}, um statt dessen den Ordner mit der heruntergeladenen Installationsdatei zu öffnen. 136 | 137 | 138 | KeePassUpdate_RequestInstallType 139 | EarlyUpdateCheck kann beim Aktualisieren von KeePass unterstützen. 140 | Bitte gib die aktuelle Installationsmethode an. 141 | 142 | KeePass bietet folgende Installationsmethoden: 143 | - Setup: KeePass-<Version>-Setup.exe 144 | - MSI: KeePass-<Version>.msi 145 | - Portabel: KeePass-<Version>.zip 146 | 147 | 148 | SecureDesktopMode 149 | EarlyUpdateCheck hat verfügbare Updates von Plugins und/oder KeePass erkannt. 150 | 151 | Da die Option '{0}' aktiv ist, kann das Updatefenster jetzt nicht angezeigt werden. 152 | Es wird angezeigt NACHDEM das '{1}' Fenster geschlossen wurde. 153 | 154 | -------------------------------------------------------------------------------- /Translations/EarlyUpdateCheck.fr.language.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | 5 | Active 6 | Actif 7 | 8 | 9 | CheckSync 10 | Vérification de la mise à jour au premier plan 11 | 12 | 13 | CheckSyncDesc 14 | EarlyUpdateCheck commencera toujours la vérification de la mise à jour le plus tôt possible. 15 | 16 | Si cette option est activé, EarlyUpdateCheck s'assurera en outre que la vérification de la mise à jour est terminée AVANT que la fenêtre "Ouvrir la base de données" ne s'affiche. 17 | Vous pouvez faire en sorte que la vérification de la mise à jour se poursuive en arrière-plan si vous ne voulez pas attendre qu'elle soit terminée. 18 | 19 | 20 | EnterBackgroundMode 21 | Continuer en arrière-plan 22 | 23 | 24 | PluginUpdateOneClick 25 | Mise à jour des plugins 'en un seul clic' 26 | 27 | 28 | PluginUpdateOneClickDesc 29 | Installez les nouvelles versions de mes plugins en cliquant sur le plugin dans la fenêtre "Vérifier les mises à jour". 30 | Cela nécessite un accès en écriture au dossier des plugins de KeePass. 31 | KeePass doit être redémarré par la suite afin de pouvoir utiliser la nouvelle version. 32 | 33 | 34 | PluginUpdate 35 | Mise à jour 36 | 37 | 38 | PluginUpdateSelected 39 | Démarrer la mise à jour 40 | 41 | 42 | PluginUpdateCaption 43 | Vérification anticipée des mises à jour - Mise à jour des plugins 44 | 45 | 46 | PluginUpdating 47 | Mise à jour {0}, merci de patienter... 48 | 49 | 50 | PluginUpdateSuccess 51 | La mise à jour a réussie, la ou les nouvelles versions seront activées après un redémarrage de KeePass. 52 | Redémarrer maintenant ? 53 | 54 | 55 | PluginUpdateFailed 56 | Le transfert des fichiers téléchargés a échoué. Ouvrir un dossier temporaire à la place ? 57 | 58 | 59 | PluginUpdateFailedSpecific 60 | Plugin: {0} 61 | La mise à jour a échoué 62 | 63 | 64 | PluginTranslationUpdateFailed 65 | Plugin: {0} 66 | Mise à jour du fichier de langue {1} a échoué 67 | 68 | 69 | TryUAC 70 | La mise à jour n'a pas pu être terminée. Essayez une autre méthode ? 71 | Cela pourrait faire apparaître l'invite de contrôle du compte d'utilisateur. 72 | 73 | 74 | OpenTempFolder 75 | Ouvrir le dossier temporaire contenant les fichiers mis à jour ? 76 | 77 | 78 | TranslationDownload_Update 79 | Mise à jour manuelle des traductions 80 | 81 | 82 | TranslationDownload_DownloadCurrent 83 | Toujours télécharger les traductions pour la langue active : {0} 84 | 85 | 86 | TranslationUpdateForm 87 | Vérification anticipée des mises à jour - Mise à jour des traductions 88 | 89 | 90 | SelectPluginsForTranslationUpdate 91 | Veuillez sélectionner les plugins pour lesquels les traductions seront mises à jour 92 | 93 | -------------------------------------------------------------------------------- /Translations/EarlyUpdateCheck.it.language.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | 5 | Active 6 | Attivo 7 | 8 | 9 | CheckSync 10 | Controlla aggiornamenti in primo piano 11 | 12 | 13 | CheckSyncDesc 14 | EarlyUpdateCheck inizierà sempre il controllo degli aggiornamenti il prima possibile. 15 | 16 | Se questa opzione è attiva, EarlyUpdateCheck si assicurerà che il controllo degli aggiornamenti sia completato PRIMA che la finestra 'Apri Database' sia mostrata. 17 | Potresti permettere al controllo degli aggiornamenti di continuare in background se non vuoi aspettare il suo completamento. 18 | 19 | 20 | EnterBackgroundMode 21 | Continua in background 22 | 23 | 24 | PluginUpdateOneClick 25 | Aggiornamento plugin One-Click 26 | 27 | 28 | PluginUpdateOneClickDesc 29 | Installa nuove versioni dei plugin cliccando su un plugin nella finestra 'Controllo Aggiornamenti'. 30 | Richiede permessi di scrittura nella cartella 'Plugins' di KeePass. 31 | È necessario un riavvio di KeePass per poter utilizzare la nuova versione. 32 | 33 | Aggiornare il file ExternalPluginUpdates.xml per poter includere plugin di altri autori. Visitare la wiki per maggiori dettagli 34 | 35 | 36 | PluginUpdate 37 | Aggiorna 38 | 39 | 40 | PluginUpdateSelected 41 | Avvia aggiornamento 42 | 43 | 44 | PluginUpdateCaption 45 | Early Update Check - Plugin Updater 46 | 47 | 48 | PluginUpdating 49 | Aggiornamento {0} in corso, attendere... 50 | 51 | 52 | PluginUpdateSuccess 53 | L'aggiornamento completato con successo, la/e nuova/e versione/i sarà/saranno attive dopo il riavvio di KeePass. 54 | Riavviare ora? 55 | 56 | 57 | PluginUpdateFailed 58 | Spostamento dei file scaricati fallito. Aprire la cartella temporanea? 59 | 60 | 61 | PluginUpdateFailedSpecific 62 | Plugin: {0} 63 | Aggiornamento fallito 64 | 65 | 66 | PluginTranslationUpdateFailed 67 | Plugin: {0} 68 | Aggiornamento del file della lingua {1} fallito 69 | 70 | 71 | TryUAC 72 | L'aggiornamento non può essere completato. Provare il metodo alternativo? 73 | Ciò potrebbe mostrare il prompt delle credenziali UAC. 74 | 75 | 76 | OpenTempFolder 77 | Aprire la cartella temporanea contenente i file aggiornati? 78 | 79 | 80 | TranslationDownload_Update 81 | Aggiornare manualmente le traduzioni 82 | 83 | 84 | TranslationDownload_DownloadCurrent 85 | Scaricare sempre le traduzioni per la lingua attiva: {0} 86 | 87 | 88 | TranslationUpdateForm 89 | Early Update Check - Aggiorna traduzioni 90 | 91 | 92 | SelectPluginsForTranslationUpdate 93 | Selezionare i plugin per i quali devono essere aggiornati i file della lingua 94 | 95 | 96 | UpdateExternalInfo 97 | È disponibile una nuova versione del file ExternalPluginUpdates.xml. 98 | Vuoi scaricarla così da aggiornare nuovi plugin di terze parti? 99 | 100 | -------------------------------------------------------------------------------- /Translations/EarlyUpdateCheck.ja.language.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | 5 | Active 6 | 有効 7 | 8 | 9 | CheckSync 10 | フォアグラウンドで更新の確認 11 | 12 | 13 | CheckSyncDesc 14 | EarlyUpdateCheck は、常に可能な限り早期に更新の確認を開始します。 15 | 16 | このオプションが有効なときは、EarlyUpdateCheck は “データベースを開く” ウィンドウが表示される前に更新の確認が完了していることを保証します。 17 | 更新の確認の完了を待たずに、バックグラウンドで更新の確認を続行できます。 18 | 19 | 20 | EnterBackgroundMode 21 | バックグラウンドで続行 22 | 23 | 24 | PluginUpdateOneClick 25 | ワンクリックでプラグインを更新 26 | 27 | 28 | PluginUpdateOneClickDesc 29 | “更新の確認” ウィンドウでプラグインをクリックして最新版をインストールします。 30 | これには KeePass のプラグインのフォルダーへの書き込み権限を必要とします。 31 | 新しいバージョンを使用するには、KeePass を再起動する必要があります。 32 | 33 | 他の作成者のプラグインを含めるためにファイル ExternalPluginUpdates.xml を維持しています。詳細については、wiki を参照してください。 34 | 35 | 36 | PluginUpdate 37 | 更新 38 | 39 | 40 | PluginUpdateSelected 41 | 更新を開始 42 | 43 | 44 | PluginUpdateCaption 45 | Early Update Check - プラグインの更新 46 | 47 | 48 | PluginUpdating 49 | {0} を更新しています。しばらくお待ちください... 50 | 51 | 52 | PluginUpdateSuccess 53 | 更新が成功しました。新しいバージョンは KeePass を再起動した後に利用できます。 54 | 再起動しますか? 55 | 56 | 57 | PluginUpdateFailed 58 | ダウンロードしたファイルの移動に失敗しました。一時フォルダーを開きますか? 59 | 60 | 61 | PluginUpdateFailedSpecific 62 | プラグイン: {0} 63 | 更新に失敗しました。 64 | 65 | 66 | PluginTranslationUpdateFailed 67 | プラグイン: {0} 68 | 言語ファイル {1} の更新に失敗しました。 69 | 70 | 71 | TryUAC 72 | 更新できませんでした。他の方法を試しますか? 73 | これにより、UAC プロンプトが表示される場合があります。 74 | 75 | 76 | OpenTempFolder 77 | 更新したファイルがある一時フォルダーを開きますか? 78 | 79 | 80 | TranslationDownload_Update 81 | 手動で言語を更新 82 | 83 | 84 | TranslationDownload_DownloadCurrent 85 | 常に設定された言語をダウンロードします: {0} 86 | 87 | 88 | TranslationUpdateForm 89 | Early Update Check - 言語の更新 90 | 91 | 92 | SelectPluginsForTranslationUpdate 93 | 言語を更新するプラグインを選択してください 94 | 95 | 96 | UpdateExternalInfo 97 | ExternalPluginUpdates.xml の新しいバージョンが利用できます。 98 | ダウンロードしてサードパーティー製のプラグインを更新しますか? 99 | 100 | -------------------------------------------------------------------------------- /Translations/EarlyUpdateCheck.pt.language.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3 4 | 5 | Active 6 | Ativo 7 | 8 | 9 | CheckSync 10 | Checar atualização em primeiro plano 11 | 12 | 13 | CheckSyncDesc 14 | EarlyUpdateCheck sempre iniciará a verificação de atualização o mais cedo possível. 15 | 16 | Se esta opção estiver ativa, EarlyUpdateCheck irá adicionalmente garantir que a verificação de atualização seja concluída ANTES que a janela 'Abrir Banco de Dados' seja exibida. 17 | Você pode fazer com que a verificação da atualização continue em segundo plano se não quiser esperar sua conclusão. 18 | 19 | 20 | EnterBackgroundMode 21 | Continue em segundo plano 22 | 23 | 24 | PluginUpdateOneClick 25 | Atualização do plugin em Um Clique 26 | 27 | 28 | PluginUpdateOneClickDesc 29 | Instale novas versões de plug-ins clicando no plug-in na janela 'Verificar atualização'. 30 | Isso requer acesso de gravação à pasta de plug-ins do KeePass. 31 | O KeePass precisa ser reiniciado posteriormente para usar a nova versão. 32 | 33 | Mantenha o arquivo ExternalPluginUpdates.xml para incluir plug-ins de outros autores, consulte o wiki para obter mais detalhes 34 | 35 | 36 | PluginUpdate 37 | Atualizar 38 | 39 | 40 | PluginUpdateKeePass 41 | Atualizar KeePass 42 | 43 | 44 | PluginUpdateSelected 45 | Atualizar plugins 46 | 47 | 48 | PluginUpdateCaption 49 | Verificação de atualização antecipada - atualizador de plugin 50 | 51 | 52 | PluginUpdating 53 | Atualizando {0}, aguarde... 54 | 55 | 56 | PluginUpdateSuccess 57 | A atualização foi bem-sucedida, a(s) nova(s) versão(ões) estarão ativas após a reinicialização do KeePass. 58 | Reiniciar agora? 59 | 60 | 61 | PluginUpdateFailed 62 | Falha ao mover os arquivos baixados. Abrir pasta temporária ao invés? 63 | 64 | 65 | PluginUpdateFailedSpecific 66 | Plugin: {0} 67 | A atualização falhou 68 | 69 | 70 | PluginTranslationUpdateFailed 71 | Plugin: {0} 72 | A atualização do arquivo de idioma {1} falhou 73 | 74 | 75 | TryUAC 76 | A atualização não pôde ser concluída. Tente um método alternativo? 77 | Isso pode mostrar o prompt do UAC. 78 | 79 | 80 | OpenTempFolder 81 | Abrir pasta temporária contendo os arquivos atualizados? 82 | 83 | 84 | TranslationDownload_Update 85 | Atualizar traduções manualmente 86 | 87 | 88 | TranslationDownload_DownloadCurrent 89 | Sempre baixe traduções para o idioma ativo: {0} 90 | 91 | 92 | TranslationUpdateForm 93 | Verificação de atualização antecipada - Atualizar traduções 94 | 95 | 96 | SelectPluginsForTranslationUpdate 97 | Selecione plugins para os quais as traduções devem ser atualizadas 98 | 99 | UpdateExternalInfo 100 | Uma nova versão de ExternalPluginUpdates.xml está disponível. 101 | Baixar para atualizar mais plugins de terceiros? 102 | 103 | 104 | UpdateExternalInfoInitialDownload 105 | EarlyUpdateCheck pode atualizar plugins de terceiros também. 106 | Isso facilitado por um arquivo chamado ExternalPluginUpdates.xml. 107 | Baixar esse arquivo agora para permitir a atualização desses plugins? 108 | 109 | Esta questão não irá ser perguntada novamente. 110 | Se você decidir não usar este recurso agora, você pode baixar esse arquivo nas opções EarlyUpdateCheck's. 111 | 112 | 113 | UpdateExternalInfoDownload 114 | Baixar ExternalPluginUpdates.xml 115 | 116 | 117 | KeePassUpdate_InstallZip 118 | EarlyUpdateCheck baixou a mais nova versão portátil do KeePass. 119 | 120 | Os arquivos baixados irão ser abertos em uma nova janela. 121 | Para executar a atualização, feche o KeePass e copiar esses arquivos no local atual do KeePass. 122 | 123 | 124 | KeePassUpdate_InstallSetupOrMsi 125 | EarlyUpdateCheck baixou a mais nova versão do KeePass. 126 | Para executar a atualização, você precisa fechar o KeePass. 127 | 128 | Clique {0} para executar a atualização agora. 129 | Clique {1} para abrir a pasta contendo o arquivo baixado ao invés. 130 | 131 | 132 | KeePassUpdate_RequestInstallType 133 | EarlyUpdateCheck pode ajudar na atualização do KeePass também. 134 | Desde que o KeePass pode ser instalado de diferentes formas, por favor, confirme o tipo da sua instalação. 135 | 136 | Diferentes tipos de instalação oferecidas: 137 | - Instalador: KeePass-<Versão>-Setup.exe é usado para instalar o KeePass 138 | - MSI: KeePass-<Versão>.msi é usado para instalar o KeePass 139 | - Portátil: KeePass-<Versão>.zip é usado para baixar e extrair o KeePass 140 | 141 | 142 | -------------------------------------------------------------------------------- /Translations/EarlyUpdateCheck.ru.language.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 2 5 | 6 | Active 7 | Включить 8 | 9 | 10 | CheckSync 11 | Выполнение проверки на переднем плане 12 | 13 | 14 | CheckSyncDesc 15 | Когда плагин включен, проверка обновлений всегда начинается в кратчайшие сроки. 16 | 17 | Если эта опция включена, плагин дополнительно гарантирует, что проверка обновлений завершена ДО отображения окна с открытой базой данных. 18 | Вы можете продолжить проверку обновлений в фоне, если не хотите ждать ее завершения. 19 | 20 | 21 | EnterBackgroundMode 22 | Продолжить в фоне 23 | 24 | 25 | PluginUpdateOneClick 26 | Обновление плагинов в один клик 27 | 28 | 29 | PluginUpdateOneClickDesc 30 | Установите новые версии моих плагинов щелчком по плагину в окне "Проверка обновлений". 31 | 32 | Требуется доступ на запись к каталогу плагинов KeePass. 33 | 34 | Для использования новой версии плагина KeePass необходимо перезапустить. 35 | 36 | 37 | PluginUpdate 38 | Можно обновить 39 | 40 | 41 | PluginUpdateSelected 42 | Обновить 43 | 44 | 45 | PluginUpdateCaption 46 | Early Update Check - Обновление плагинов 47 | 48 | 49 | PluginUpdating 50 | Обновляется {0}, пожалуйста, ждите... 51 | 52 | 53 | PluginUpdateSuccess 54 | Обновление завершилось успешно. Новые версии плагинов будут использоваться после перезапуска KeePass. 55 | Перезапустить сейчас? 56 | 57 | 58 | PluginUpdateFailed 59 | Перемещение загруженных файлов завершилось с ошибкой. Открыть каталог с временными файлами? 60 | 61 | 62 | PluginUpdateFailedSpecific 63 | Плагин: {0} 64 | Обновление завершилось с ошибкой. 65 | 66 | 67 | PluginTranslationUpdateFailed 68 | Плагин: {0} 69 | Обновление файла перевода {1} завершилось с ошибкой. 70 | 71 | 72 | TryUAC 73 | Обновление не может быть завершено. Попробовать альтернативный способ? 74 | Появится окно контроля учетных записей Windows (UAC) с запросом подтверждения дальнейших действий. 75 | 76 | 77 | OpenTempFolder 78 | Открыть каталог временных файлов с загруженными файлами? 79 | 80 | 81 | TranslationDownload_Update 82 | Обновление файлов переводов вручную 83 | 84 | 85 | TranslationDownload_DownloadCurrent 86 | Всегда загружать файл перевода для текущего языка: {0} 87 | 88 | 89 | TranslationUpdateForm 90 | Early Update Check - Обновить файлы переводов 91 | 92 | 93 | SelectPluginsForTranslationUpdate 94 | Пожалуйста, выберите плагины, для которых следует обновить файлы переводов 95 | 96 | -------------------------------------------------------------------------------- /Translations/EarlyUpdateCheck.template.language.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 0 8 | 9 | Active 10 | Active 11 | 12 | 13 | CheckSync 14 | Update check in foreground 15 | 16 | 17 | CheckSyncDesc 18 | EarlyUpdateCheck will always start the update check at the earliest possible time. 19 | 20 | If this option is active, EarlyUpdateCheck will additionally ensure the update check is finished BEFORE the 'Open Database' window is shown. 21 | You may have the upgrade check continue in background if you don't want to wait for its completion. 22 | 23 | 24 | EnterBackgroundMode 25 | Continue in background 26 | 27 | 28 | PluginUpdateOneClick 29 | One-Click plugin update 30 | 31 | 32 | PluginUpdateOneClickDesc 33 | Install new versions of plugins by clicking the plugin in the 'Update Check' window. 34 | This requires write access to KeePass' plugin folder. 35 | KeePass needs to be restarted afterwards in order to use the new version. 36 | 37 | Maintain file ExternalPluginUpdates.xml to include other authors' plugins, see the wiki for more details 38 | 39 | 40 | PluginUpdate 41 | Update 42 | 43 | 44 | PluginUpdateKeePass 45 | Update KeePass 46 | 47 | 48 | PluginUpdateSelected 49 | Update plugins 50 | 51 | 52 | PluginUpdateCaption 53 | Early Update Check - Plugin Updater 54 | 55 | 56 | PluginUpdating 57 | Updating {0}, please wait... 58 | 59 | 60 | PluginUpdateSuccess 61 | The update was successful, the new version(s) will be active after a restart of KeePass. 62 | Restart now? 63 | 64 | 65 | PluginUpdateFailed 66 | Moving downloaded files failed. Open temporary folder instead? 67 | 68 | 69 | PluginUpdateFailedSpecific 70 | Plugin: {0} 71 | The update failed 72 | 73 | 74 | PluginTranslationUpdateFailed 75 | Plugin: {0} 76 | Update of language file {1} failed 77 | 78 | 79 | TryUAC 80 | Update could not be finished. Try alternative method? 81 | This might show the UAC prompt. 82 | 83 | 84 | OpenTempFolder 85 | Open temporary folder containing the updated files? 86 | 87 | 88 | TranslationDownload_Update 89 | Manually update translations 90 | 91 | 92 | TranslationDownload_DownloadCurrent 93 | Always download translations for active language: {0} 94 | 95 | 96 | TranslationUpdateForm 97 | Early Update Check - Update translations 98 | 99 | 100 | SelectPluginsForTranslationUpdate 101 | Please select plugins for which translations shall be updated 102 | 103 | 104 | UpdateExternalInfo 105 | A new version of ExternalPluginUpdates.xml is available. 106 | Download to update more 3rd party plugins? 107 | 108 | 109 | UpdateExternalInfoInitialDownload 110 | EarlyUpdateCheck can update selected 3rd party plugins as well. 111 | This is facilitated by a file called ExternalPluginUpdates.xml. 112 | Download this file now to allow updating those plugins? 113 | 114 | This question will not be asked again. 115 | If you decide to not use this feature now, you can download this file in EarlyUpdateCheck's options. 116 | 117 | 118 | UpdateExternalInfoDownload 119 | Download ExternalPluginUpdates.xml 120 | 121 | 122 | KeePassUpdate_InstallZip 123 | EarlyUpdateCheck downloaded the newest portable version of KeePass. 124 | 125 | The downloaded files will open in a new window. 126 | To perform the update, close KeePass and copy these files to your current KeePass location. 127 | 128 | 129 | KeePassUpdate_InstallSetupOrMsi 130 | EarlyUpdateCheck downloaded the newest version of KeePass. 131 | To perform the update, you need to close KeePass. 132 | 133 | Click {0} to run the update now. 134 | Click {1} to open the folder containing the downloaded file instead. 135 | 136 | 137 | KeePassUpdate_RequestInstallType 138 | EarlyUpdateCheck can help in updating KeePass as well. 139 | Since KeePass can be installed in different ways, please confirm your installation type. 140 | 141 | Different installation types offered: 142 | - Setup: KeePass-<Version>-Setup.exe is used to install KeePass 143 | - MSI: KeePass-<Version>.msi is used to install KeePass 144 | - Portable: KeePass-<Version>.zip is used to download and extract KeePass 145 | 146 | 147 | SecureDesktopMode 148 | EarlyUpdateCheck detected available updates of plugins and/or KeePass. 149 | 150 | As option '{0}' is active, the update form cannot be displayed now. 151 | It will be shown AFTER you close the '{1}' form. 152 | 153 | -------------------------------------------------------------------------------- /Translations/EarlyUpdateCheck.zh.language.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2 4 | 5 | Active 6 | 活动 7 | 8 | 9 | CheckSync 10 | 前台显示更新 11 | 12 | 13 | CheckSyncDesc 14 | EarlyUpdateCheck 将始终尽早开始更新检查。 15 | 16 | 如果此选项处于活动状态,则在显示“打开数据库”窗口之前,EarlyUpdateCheck 将另外确保更新检查已完成。 17 | 如果不想等待升级检查完成,可以在后台继续进行升级检查。 18 | 19 | 20 | EnterBackgroundMode 21 | 在后台继续 22 | 23 | 24 | PluginUpdateOneClick 25 | 一键式插件更新 26 | 27 | 28 | PluginUpdateOneClickDesc 29 | 通过单击“更新检查”窗口中的插件来安装新版本的插件。 30 | 这需要对 KeePass 的 Plugins 文件夹的具有写访问权。 31 | 之后,必须重新启动 KeePass 才能使用新版本。 32 | 33 | 维护文件 ExternalPluginUpdates.xml 以包括其他作者的插件,有关更多详细信息,请参见Wiki。 34 | 35 | 36 | PluginUpdate 37 | 更新 38 | 39 | 40 | PluginUpdateKeePass 41 | 更新 KeePass 42 | 43 | 44 | PluginUpdateSelected 45 | 开始更新 46 | 47 | 48 | PluginUpdateCaption 49 | Early Update Check - 插件更新 50 | 51 | 52 | PluginUpdating 53 | 正在更新 {0}, 请稍候... 54 | 55 | 56 | PluginUpdateSuccess 57 | 更新成功,新版本将在KeePass重新启动后生效。 58 | 现在重启? 59 | 60 | 61 | PluginUpdateFailed 62 | 移动下载的文件失败。打开临时文件夹? 63 | 64 | 65 | PluginUpdateFailedSpecific 66 | 插件 {0} 67 | 更新失败 68 | 69 | 70 | PluginTranslationUpdateFailed 71 | 插件: {0} 72 | 语言文件 {1} 的更新失败 73 | 74 | 75 | TryUAC 76 | 更新无法完成。 尝试其他方法? 77 | 这可能会显示UAC提示。 78 | 79 | 80 | OpenTempFolder 81 | 打开包含更新文件的临时文件夹? 82 | 83 | 84 | TranslationDownload_Update 85 | 手动更新翻译 86 | 87 | 88 | TranslationDownload_DownloadCurrent 89 | 始终下载设置语言的翻译:{0} 90 | 91 | 92 | TranslationUpdateForm 93 | Early Update Check - 更新翻译 94 | 95 | 96 | SelectPluginsForTranslationUpdate 97 | 请选择需要更新翻译的插件 98 | 99 | 100 | UpdateExternalInfo 101 | 可以使用新版本的外部插件Updates.xml。 102 | 下载以更新更多的第三方插件? 103 | 104 | 105 | UpdateExternalInfoInitialDownload 106 | EarlyUpdateCheck可以更新其他开发者的插件。 107 | 为此,需要加载ExternalPluginUpdates.xml文件。 108 | 现在要加载这个文件吗? 109 | 110 | 这个问题不会再次提问。 111 | 如果你现在不想使用这个功能,你也可以稍后在EarlyUpdateCheck的选项中加载该文件。 112 | 113 | 114 | UpdateExternalInfoDownload 115 | 下载 ExternalPluginUpdates.xml 116 | 117 | 118 | KeePassUpdate_InstallZip 119 | EarlyUpdateCheck已经下载了最新的KeePass便携版。 120 | 121 | 下载的文件将在一个新窗口中打开。 122 | 要进行更新,请关闭KeePass并将下载的文件复制到你的KeePass文件夹中。 123 | 124 | 125 | KeePassUpdate_InstallSetupOrMsi 126 | EarlyUpdateCheck已经成功加载了最新版本的KeePass。 127 | 128 | 为了进行更新,请先关闭KeePass。 129 | 130 | 点击{0}开始进行更新。 131 | 点击{1}打开包含已下载安装文件的文件夹。 132 | 133 | 134 | KeePassUpdate_RequestInstallType 135 | EarlyUpdateCheck可以帮助你进行KeePass的更新。 136 | 请提供当前的安装方式。 137 | 138 | KeePass提供以下安装方式: 139 | - 安装程序:KeePass-<Version>-Setup.exe 140 | - MSI安装包: KeePass-<Version>.msi 141 | - 便携版: KeePass-<Version>.zip 142 | 143 | 144 | SecureDesktopMode 145 | EarlyUpdateCheck检测到插件和/或KeePass的可用更新。 146 | 147 | 由于选项“{0}”已激活,更新窗口现在无法显示。 148 | 它将在关闭“{1}”窗口后显示。 149 | 150 | 151 | -------------------------------------------------------------------------------- /externalplugininfocopy.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd %~dp0 3 | 4 | if "%1" == "Debug" ( 5 | xcopy /y /c /i ExternalPluginUpdates\*.xml "..\_KeePass_Debug\Plugins" 6 | ) 7 | if "%1" == "ReleasePlgx" ( 8 | xcopy /y /c /i ExternalPluginUpdates\*.xml "..\_KeePass_Release\Plugins" 9 | xcopy /y /c /i ExternalPluginUpdates\*.xml "..\_Releases" 10 | ) -------------------------------------------------------------------------------- /images/EarlyUpdateCheck KeePass Update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rookiestyle/EarlyUpdateCheck/b3e482555ba621ff9b0e07534cc35d0c40c38bd8/images/EarlyUpdateCheck KeePass Update.png -------------------------------------------------------------------------------- /images/EarlyUpdateCheck One Click Update 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rookiestyle/EarlyUpdateCheck/b3e482555ba621ff9b0e07534cc35d0c40c38bd8/images/EarlyUpdateCheck One Click Update 1.png -------------------------------------------------------------------------------- /images/EarlyUpdateCheck One Click Update 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rookiestyle/EarlyUpdateCheck/b3e482555ba621ff9b0e07534cc35d0c40c38bd8/images/EarlyUpdateCheck One Click Update 2.png -------------------------------------------------------------------------------- /images/EarlyUpdateCheck One Click Update UAC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rookiestyle/EarlyUpdateCheck/b3e482555ba621ff9b0e07534cc35d0c40c38bd8/images/EarlyUpdateCheck One Click Update UAC.png -------------------------------------------------------------------------------- /images/EarlyUpdateCheck checking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rookiestyle/EarlyUpdateCheck/b3e482555ba621ff9b0e07534cc35d0c40c38bd8/images/EarlyUpdateCheck checking.png -------------------------------------------------------------------------------- /images/EarlyUpdateCheck options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rookiestyle/EarlyUpdateCheck/b3e482555ba621ff9b0e07534cc35d0c40c38bd8/images/EarlyUpdateCheck options.png -------------------------------------------------------------------------------- /plgxcreate.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd %~dp0 3 | 4 | for %%* in (.) do set CurrDirName=%%~nx* 5 | echo Processing %CurrDirName% 6 | 7 | echo Copying PlgX to KeePass plugin folder 8 | copy "src\bin\Release\%CurrDirName%.plgx" "..\_KeePass_Release\Plugins\%CurrDirName%.plgx" 9 | 10 | echo Releasing PlgX 11 | move /y "src\bin\Release\%CurrDirName%.plgx" "..\_Releases\%CurrDirName%.plgx" 12 | -------------------------------------------------------------------------------- /plgxexclude.txt: -------------------------------------------------------------------------------- 1 | bin\ 2 | obj\ 3 | .vs 4 | .git 5 | .user 6 | .sln 7 | .suo 8 | .pdb -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # EarlyUpdateCheck 2 | [![Version](https://img.shields.io/github/release/rookiestyle/earlyupdatecheck)](https://github.com/rookiestyle/earlyupdatecheck/releases/latest) 3 | [![Releasedate](https://img.shields.io/github/release-date/rookiestyle/earlyupdatecheck)](https://github.com/rookiestyle/earlyupdatecheck/releases/latest) 4 | [![Downloads](https://img.shields.io/github/downloads/rookiestyle/earlyupdatecheck/total?color=%2300cc00)](https://github.com/rookiestyle/earlyupdatecheck/releases/latest/download/EarlyUpdateCheck.plgx)\ 5 | [![License: GPL v3](https://img.shields.io/github/license/rookiestyle/earlyupdatecheck)](https://www.gnu.org/licenses/gpl-3.0) 6 | 7 | Keepass performs its update check only after all initialization is done and - if configured - the most recently used database has been opened. 8 | 9 | EarlyUpdateCheck helps to run this checks for updates of KeePass and installed plugins BEFORE a database is opened. 10 | Additionally, it offers a handy one click update mode for all of my plugins integrated in KeePass' update check and also supports updating KeePass itself. 11 | This will invoke Windows UAC if required to copy the downloaded files into KeePass' plugin folder. 12 | Details can be found in the configuration settings. 13 | 14 | EarlyUpdateCheck can update other author's plugins as well. 15 | Please have a look at the [wiki](https://github.com/Rookiestyle/EarlyUpdateCheck/wiki/Update-other-plugins) for details. 16 | 17 | 18 | EarlyUpdateCheck will trigger KeePass' built-in update check only if all of the following criteria are met 19 | * *Check for update at KeePass startup* is active 20 | * *Remember and automatically open last used database on start* is active 21 | * *Start minimized and locked* is **not** active 22 | 23 | 24 | # Table of Contents 25 | - [Configuration](#configuration) 26 | - [One-click plugin update](#one-click-plugin-update) 27 | - [KeePass update](#keepass-update) 28 | - [Translations](#translations) 29 | - [Download & updates](#download--updates) 30 | - [Requirements](#requirements) 31 | 32 | # Configuration 33 | EarlyUpdateCheck integrates into KeePass' options form. 34 | ![Options](images/EarlyUpdateCheck%20options.png) 35 | 36 | The upper part defines whether the update check shall start even before a database is opened. 37 | In this case, the update check is triggered as early as possible. 38 | As the update check runs in a separate thread, it is still possible that you opened a database while the update check is still running. 39 | 40 | To avoid this, check *Update check in foregound*. KeePass will then wait for the update check to be finished. 41 | In case of network issues you may have this update check continue in background.\ 42 | ![Checking](images/EarlyUpdateCheck%20checking.png) 43 | 44 | # One-Click plugin update 45 | The lower part of the options screen allow you to update my plugins in a very easy way. 46 | If an update for any of my plugins is available, the *Update check* form will show an additional column. 47 | Select all plugins you wish to update and click *Start Update*.\ 48 | ![Update](images/EarlyUpdateCheck%20One%20Click%20Update%201.png) 49 | 50 | Once the plugins have been updated, you need to restart KeePass.\ 51 | ![Restart](images/EarlyUpdateCheck%20One%20Click%20Update%202.png) 52 | 53 | # KeePass update 54 | EarlyUpdateCheck can also update KeePass itself. 55 | KeePass is shipped in different variants and each of them requires a specific way of updating. 56 | - You can install KeePass using a KeePass-*Version*-Setup.exe - This is the default and linked at https://keepass.info/download.html as *Installer for Windows* 57 | - You can run KeePass using a portable version - This is also linked at https://keepass.info/download.html as *Portable* 58 | - You can install KeePass using a KeePass-*Version*.msi file which is not linked at https://keepass.info/download.html but on Sourceforge only 59 | 60 | EarlyUpdateCheck can detect the used installation variant and if it's correct, you only need to confirm and you're ready to go. 61 | ![KeePass update](images/EarlyUpdateCheck%20KeePass%20Update.png) 62 | 63 | When using the portable version, EarlyUpdateCheck will download the new zip package, extract it to a temporary folder and open this folder in explorer. 64 | To finish the update, you need to close KeePass and copy the downloaded files to your current KeePass folder. 65 | 66 | For the other two cases, EarlyUpdateCheck will download the required file. You can decide to open the folder containing the downloaded file or you can start the installation immediately. 67 | Don't forget to close KeePass in the latter case. 68 | 69 | Anytime, please ensure to have a working backup strategy. 70 | 71 | # Translations 72 | My plugins are provided with English language built-in and allow usage of translation files. 73 | These translation files need to be placed in a folder called *Translations* inside your plugin folder. 74 | If a text is missing in the translation file, it is backfilled with English text. 75 | You're welcome to add additional translation files by creating a pull request as described in the [wiki](https://github.com/Rookiestyle/EarlyUpdateCheck/wiki/Create-or-update-translations). 76 | 77 | Naming convention for translation files: `..language.xml`\ 78 | Example: `EarlyUpdateCheck.de.language.xml` 79 | 80 | The language identifier in the filename must match the language identifier inside the KeePass language that you can select using *View -> Change language...*\ 81 | This identifier is shown there as well. 82 | 83 | ## Download & updates 84 | Please follow these links to download the plugin file itself. 85 | - [Download newest release](https://github.com/rookiestyle/earlyupdatecheck/releases/latest/download/EarlyUpdateCheck.plgx) 86 | - [Download history](https://github.com/rookiestyle/earlyupdatecheck/releases) 87 | 88 | If you're interested in any of the available translations in addition, please download them from the [Translations](Translations) folder. 89 | 90 | In addition to the manual way of downloading the plugin, you can use [EarlyUpdateCheck](https://github.com/rookiestyle/earlyupdatecheck/) to update both the plugin and its translations automatically. 91 | See the [one click plugin update wiki](https://github.com/Rookiestyle/EarlyUpdateCheck/wiki/One-click-plugin-update) for more details. 92 | 93 | # Requirements 94 | * KeePass: 2.38 95 | -------------------------------------------------------------------------------- /src/CheckedGroupBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | 9 | namespace RookieUI 10 | { 11 | public class CheckedGroupCheckEventArgs : EventArgs 12 | { 13 | public bool GroupChecked { get; private set; } 14 | public bool BeforeDefaultHandling { get; private set; } 15 | public bool SkipDefaultHandling; 16 | 17 | public CheckedGroupCheckEventArgs(bool bGroupChecked, bool bBeforeDefaultHandling) 18 | { 19 | GroupChecked = bGroupChecked; 20 | BeforeDefaultHandling = bBeforeDefaultHandling; 21 | } 22 | } 23 | 24 | public class CheckedGroupBox : GroupBox 25 | { 26 | #region Members 27 | public override string Text 28 | { 29 | get 30 | { 31 | return DesignMode ? base.Text : " "; 32 | } 33 | set 34 | { 35 | if (!DesignMode) m_cbCheck.Text = value; 36 | base.Text = DesignMode ? value : " "; 37 | } 38 | } 39 | 40 | private CheckBox m_cbCheck = new CheckBox(); 41 | private Dictionary m_dControls = new Dictionary(); 42 | private bool m_bProcessCheck = false; 43 | 44 | private Point m_pCheckboxOffset = new Point(6, 0); 45 | [Category("Layout")] 46 | public Point CheckboxOffset 47 | { 48 | get { return m_pCheckboxOffset; } 49 | set { m_pCheckboxOffset = value; OnAdjustChechBoxPosition(null, null); } 50 | } 51 | 52 | public event EventHandler CheckedChanged; 53 | public bool Checked 54 | { 55 | get { return m_cbCheck.Checked; } 56 | set 57 | { 58 | m_cbCheck.Checked = value; 59 | OnCheckChanged(); 60 | } 61 | } 62 | 63 | private bool m_bDisableIfUnchecked = true; 64 | [Category("Behavior")] 65 | [DefaultValue(true)] 66 | public bool DisableControlsIfUnchecked 67 | { 68 | get { return m_bDisableIfUnchecked; } 69 | set { m_bDisableIfUnchecked = value; if (!Checked) OnCheckChanged(); } 70 | } 71 | 72 | private System.ComponentModel.IContainer components = null; 73 | #endregion 74 | 75 | #region Init 76 | public CheckedGroupBox() : base() 77 | { 78 | InitializeComponent(); 79 | OnAdjustChechBoxPosition(null, null); 80 | } 81 | 82 | private void InitializeComponent() 83 | { 84 | components = new System.ComponentModel.Container(); 85 | m_cbCheck.AutoSize = true; 86 | m_cbCheck.Checked = true; 87 | m_cbCheck.Parent = this; 88 | m_cbCheck.CheckedChanged += (o, e) => OnCheckChanged(); 89 | RightToLeftChanged += OnAdjustChechBoxPosition; 90 | ClientSizeChanged += OnAdjustChechBoxPosition; 91 | TabStop = true; 92 | components.Add(m_cbCheck); 93 | } 94 | #endregion 95 | 96 | #region Eventhandlers 97 | private void OnAdjustChechBoxPosition(object sender, EventArgs e) 98 | { 99 | if (RightToLeft == RightToLeft.Yes) 100 | { 101 | m_cbCheck.Left = ClientSize.Width - m_cbCheck.Width - CheckboxOffset.X; 102 | m_cbCheck.Top = CheckboxOffset.Y; 103 | } 104 | else if (RightToLeft == RightToLeft.No) 105 | { 106 | m_cbCheck.Left = CheckboxOffset.X; 107 | m_cbCheck.Top = CheckboxOffset.Y; 108 | } 109 | } 110 | 111 | private void OnCheckChanged() 112 | { 113 | if (CheckedChanged != null) 114 | { 115 | CheckedGroupCheckEventArgs c = new CheckedGroupCheckEventArgs(Checked, true); 116 | CheckedChanged(this, c); 117 | if (c.SkipDefaultHandling) return; 118 | } 119 | HandleCheckChange(); 120 | if (CheckedChanged != null) 121 | { 122 | CheckedGroupCheckEventArgs c = new CheckedGroupCheckEventArgs(Checked, false); 123 | CheckedChanged(this, c); 124 | } 125 | } 126 | #endregion 127 | 128 | #region Handle check/uncheck 129 | private void HandleCheckChange() 130 | { 131 | m_bProcessCheck = true; 132 | foreach (Control c in Controls) 133 | { 134 | if (c == m_cbCheck) continue; 135 | 136 | if (!m_dControls.ContainsKey(c)) 137 | { 138 | m_dControls[c] = c.Enabled; 139 | c.EnabledChanged += MySubControlEnabledChanged; 140 | c.Disposed += MySubControlEnabledChanged; 141 | } 142 | 143 | if (DisableControlsIfUnchecked) 144 | { 145 | if (!m_cbCheck.Checked) c.Enabled = false; 146 | if (m_cbCheck.Checked && m_dControls[c] && !c.Enabled) c.Enabled = true; 147 | } 148 | else 149 | { 150 | if (!c.Enabled) c.Enabled = m_dControls[c]; 151 | } 152 | } 153 | m_bProcessCheck = false; 154 | } 155 | 156 | private void MySubControlEnabledChanged(object sender, EventArgs e) 157 | { 158 | Control c = sender as Control; 159 | if ((c == null) || c.Disposing || c.IsDisposed) 160 | { 161 | m_dControls.Remove(c); 162 | RemoveControlsEventHandlers(c); 163 | return; 164 | } 165 | if (m_bProcessCheck) return; 166 | m_dControls[c] = c.Enabled; 167 | } 168 | 169 | private void RemoveControlsEventHandlers() 170 | { 171 | foreach (KeyValuePair c in m_dControls) 172 | RemoveControlsEventHandlers(c.Key); 173 | m_dControls.Clear(); 174 | } 175 | 176 | private void RemoveControlsEventHandlers(Control c) 177 | { 178 | if (c == null) return; 179 | c.EnabledChanged -= MySubControlEnabledChanged; 180 | c.Disposed -= MySubControlEnabledChanged; 181 | } 182 | #endregion 183 | 184 | #region Cleanup 185 | protected override void Dispose(bool disposing) 186 | { 187 | RightToLeftChanged -= OnAdjustChechBoxPosition; 188 | ClientSizeChanged -= OnAdjustChechBoxPosition; 189 | 190 | RemoveControlsEventHandlers(); 191 | if (disposing && (components != null)) 192 | { 193 | components.Dispose(); 194 | } 195 | base.Dispose(disposing); 196 | } 197 | #endregion 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/EarlyUpdateCheck.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 5 6 | 7 | 8 | 9 | 10 | 2.38 11 | $(TargetFrameworkVersion.Replace('v', '')) 12 | 13 | 14 | 15 | 16 | {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D} 17 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 18 | Debug 19 | AnyCPU 20 | 2.0 21 | Library 22 | EarlyUpdateCheck 23 | EarlyUpdateCheck 24 | v2.0 25 | Properties 26 | False 27 | False 28 | False 29 | OnBuildSuccess 30 | False 31 | False 32 | False 33 | obj\$(Configuration)\ 34 | 4 35 | 36 | 37 | 38 | AnyCPU 39 | 4194304 40 | False 41 | Auto 42 | 4096 43 | 44 | 45 | bin\Debug\ 46 | True 47 | Full 48 | False 49 | True 50 | DEBUG;TRACE 51 | Project 52 | 53 | 54 | none 55 | true 56 | bin\Release 57 | 58 | 59 | ..\..\_KeePass_Debug\Plugins\ 60 | false 61 | full 62 | 63 | 64 | 65 | 66 | 67 | Form 68 | 69 | 70 | TranslationUpdateForm.cs 71 | 72 | 73 | 74 | 75 | 76 | 77 | UserControl 78 | 79 | 80 | Options.cs 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | {10938016-dee2-4a25-9a5a-8fd3444379ca} 98 | KeePass 99 | 107 | bin\Release\Ionic.Zip.Reduced.dll 108 | 109 | 110 | 111 | 112 | 1.9.1.8 113 | 114 | 115 | 116 | 1.0.0 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /src/Options.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace EarlyUpdateCheck 2 | { 3 | partial class Options 4 | { 5 | /// 6 | /// Erforderliche Designervariable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Verwendete Ressourcen bereinigen. 12 | /// 13 | /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Vom Komponenten-Designer generierter Code 24 | 25 | /// 26 | /// Erforderliche Methode für die Designerunterstützung. 27 | /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.tcEUC = new System.Windows.Forms.TabControl(); 32 | this.tpEUCOptions = new System.Windows.Forms.TabPage(); 33 | this.tpEUC3rdParty = new System.Windows.Forms.TabPage(); 34 | this.bDownloadExternalPluginUpdates = new System.Windows.Forms.Button(); 35 | this.panel1 = new System.Windows.Forms.Panel(); 36 | this.tbFile = new System.Windows.Forms.TextBox(); 37 | this.lFile = new System.Windows.Forms.LinkLabel(); 38 | this.lv3rdPartyPlugins = new System.Windows.Forms.ListView(); 39 | this.tpKeePass = new System.Windows.Forms.TabPage(); 40 | this.gOneClickUpdate = new RookieUI.CheckedGroupBox(); 41 | this.bUpdateTranslations = new System.Windows.Forms.Button(); 42 | this.cbDownloadCurrentTranslation = new System.Windows.Forms.CheckBox(); 43 | this.tbOneClickUpdateDesc = new System.Windows.Forms.TextBox(); 44 | this.gCheckSync = new RookieUI.CheckedGroupBox(); 45 | this.tbCheckSyncDesc = new System.Windows.Forms.TextBox(); 46 | this.cbCheckSync = new System.Windows.Forms.CheckBox(); 47 | this.cgKeePassUpdate = new RookieUI.CheckedGroupBox(); 48 | this.cbKeePassInstallType = new System.Windows.Forms.ComboBox(); 49 | this.lKeePassInstallType = new System.Windows.Forms.Label(); 50 | this.tbKeePassFolder = new System.Windows.Forms.TextBox(); 51 | this.lKeePassFolder = new System.Windows.Forms.LinkLabel(); 52 | this.tbKeePassUpdateInfo = new System.Windows.Forms.TextBox(); 53 | this.tcEUC.SuspendLayout(); 54 | this.tpEUCOptions.SuspendLayout(); 55 | this.tpEUC3rdParty.SuspendLayout(); 56 | this.panel1.SuspendLayout(); 57 | this.tpKeePass.SuspendLayout(); 58 | this.gOneClickUpdate.SuspendLayout(); 59 | this.gCheckSync.SuspendLayout(); 60 | this.cgKeePassUpdate.SuspendLayout(); 61 | this.SuspendLayout(); 62 | // 63 | // tcEUC 64 | // 65 | this.tcEUC.Controls.Add(this.tpEUCOptions); 66 | this.tcEUC.Controls.Add(this.tpEUC3rdParty); 67 | this.tcEUC.Controls.Add(this.tpKeePass); 68 | this.tcEUC.Dock = System.Windows.Forms.DockStyle.Top; 69 | this.tcEUC.Location = new System.Drawing.Point(0, 0); 70 | this.tcEUC.Margin = new System.Windows.Forms.Padding(5); 71 | this.tcEUC.Name = "tcEUC"; 72 | this.tcEUC.SelectedIndex = 0; 73 | this.tcEUC.Size = new System.Drawing.Size(1339, 634); 74 | this.tcEUC.TabIndex = 12; 75 | // 76 | // tpEUCOptions 77 | // 78 | this.tpEUCOptions.Controls.Add(this.gOneClickUpdate); 79 | this.tpEUCOptions.Controls.Add(this.gCheckSync); 80 | this.tpEUCOptions.Location = new System.Drawing.Point(10, 48); 81 | this.tpEUCOptions.Margin = new System.Windows.Forms.Padding(5); 82 | this.tpEUCOptions.Name = "tpEUCOptions"; 83 | this.tpEUCOptions.Padding = new System.Windows.Forms.Padding(5); 84 | this.tpEUCOptions.Size = new System.Drawing.Size(1319, 576); 85 | this.tpEUCOptions.TabIndex = 0; 86 | this.tpEUCOptions.Text = "Options"; 87 | this.tpEUCOptions.UseVisualStyleBackColor = true; 88 | // 89 | // tpEUC3rdParty 90 | // 91 | this.tpEUC3rdParty.Controls.Add(this.bDownloadExternalPluginUpdates); 92 | this.tpEUC3rdParty.Controls.Add(this.panel1); 93 | this.tpEUC3rdParty.Controls.Add(this.lv3rdPartyPlugins); 94 | this.tpEUC3rdParty.Location = new System.Drawing.Point(10, 48); 95 | this.tpEUC3rdParty.Margin = new System.Windows.Forms.Padding(5); 96 | this.tpEUC3rdParty.Name = "tpEUC3rdParty"; 97 | this.tpEUC3rdParty.Padding = new System.Windows.Forms.Padding(18, 15, 18, 15); 98 | this.tpEUC3rdParty.Size = new System.Drawing.Size(1319, 576); 99 | this.tpEUC3rdParty.TabIndex = 1; 100 | this.tpEUC3rdParty.Text = "3rdParty"; 101 | this.tpEUC3rdParty.UseVisualStyleBackColor = true; 102 | this.tpEUC3rdParty.Resize += new System.EventHandler(this.OnShow3rdPartyTab); 103 | // 104 | // bDownloadExternalPluginUpdates 105 | // 106 | this.bDownloadExternalPluginUpdates.Dock = System.Windows.Forms.DockStyle.Top; 107 | this.bDownloadExternalPluginUpdates.Location = new System.Drawing.Point(18, 72); 108 | this.bDownloadExternalPluginUpdates.Name = "bDownloadExternalPluginUpdates"; 109 | this.bDownloadExternalPluginUpdates.Size = new System.Drawing.Size(1283, 50); 110 | this.bDownloadExternalPluginUpdates.TabIndex = 4; 111 | this.bDownloadExternalPluginUpdates.Text = "Download"; 112 | this.bDownloadExternalPluginUpdates.UseVisualStyleBackColor = true; 113 | this.bDownloadExternalPluginUpdates.Click += new System.EventHandler(this.bDownloadExternalPluginUpdates_Click); 114 | // 115 | // panel1 116 | // 117 | this.panel1.AutoSize = true; 118 | this.panel1.Controls.Add(this.tbFile); 119 | this.panel1.Controls.Add(this.lFile); 120 | this.panel1.Dock = System.Windows.Forms.DockStyle.Top; 121 | this.panel1.Location = new System.Drawing.Point(18, 15); 122 | this.panel1.Name = "panel1"; 123 | this.panel1.Size = new System.Drawing.Size(1283, 57); 124 | this.panel1.TabIndex = 3; 125 | // 126 | // tbFile 127 | // 128 | this.tbFile.Location = new System.Drawing.Point(65, 14); 129 | this.tbFile.Margin = new System.Windows.Forms.Padding(5); 130 | this.tbFile.Name = "tbFile"; 131 | this.tbFile.ReadOnly = true; 132 | this.tbFile.Size = new System.Drawing.Size(1216, 38); 133 | this.tbFile.TabIndex = 3; 134 | // 135 | // lFile 136 | // 137 | this.lFile.AutoSize = true; 138 | this.lFile.Location = new System.Drawing.Point(1, 23); 139 | this.lFile.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 140 | this.lFile.Name = "lFile"; 141 | this.lFile.Size = new System.Drawing.Size(69, 32); 142 | this.lFile.TabIndex = 2; 143 | this.lFile.TabStop = true; 144 | this.lFile.Text = "lFile"; 145 | // 146 | // lv3rdPartyPlugins 147 | // 148 | this.lv3rdPartyPlugins.Dock = System.Windows.Forms.DockStyle.Bottom; 149 | this.lv3rdPartyPlugins.FullRowSelect = true; 150 | this.lv3rdPartyPlugins.HideSelection = false; 151 | this.lv3rdPartyPlugins.Location = new System.Drawing.Point(18, 130); 152 | this.lv3rdPartyPlugins.Margin = new System.Windows.Forms.Padding(5); 153 | this.lv3rdPartyPlugins.Name = "lv3rdPartyPlugins"; 154 | this.lv3rdPartyPlugins.Size = new System.Drawing.Size(1283, 431); 155 | this.lv3rdPartyPlugins.TabIndex = 2; 156 | this.lv3rdPartyPlugins.UseCompatibleStateImageBehavior = false; 157 | this.lv3rdPartyPlugins.View = System.Windows.Forms.View.List; 158 | // 159 | // tpKeePass 160 | // 161 | this.tpKeePass.Controls.Add(this.cgKeePassUpdate); 162 | this.tpKeePass.Location = new System.Drawing.Point(10, 48); 163 | this.tpKeePass.Name = "tpKeePass"; 164 | this.tpKeePass.Padding = new System.Windows.Forms.Padding(18, 15, 18, 15); 165 | this.tpKeePass.Size = new System.Drawing.Size(1319, 576); 166 | this.tpKeePass.TabIndex = 2; 167 | this.tpKeePass.Text = "KeePass"; 168 | this.tpKeePass.UseVisualStyleBackColor = true; 169 | this.tpKeePass.ClientSizeChanged += new System.EventHandler(this.AdjustControls); 170 | // 171 | // gOneClickUpdate 172 | // 173 | this.gOneClickUpdate.CheckboxOffset = new System.Drawing.Point(5, 0); 174 | this.gOneClickUpdate.Checked = true; 175 | this.gOneClickUpdate.Controls.Add(this.bUpdateTranslations); 176 | this.gOneClickUpdate.Controls.Add(this.cbDownloadCurrentTranslation); 177 | this.gOneClickUpdate.Controls.Add(this.tbOneClickUpdateDesc); 178 | this.gOneClickUpdate.DisableControlsIfUnchecked = false; 179 | this.gOneClickUpdate.Dock = System.Windows.Forms.DockStyle.Top; 180 | this.gOneClickUpdate.Location = new System.Drawing.Point(5, 267); 181 | this.gOneClickUpdate.Margin = new System.Windows.Forms.Padding(5); 182 | this.gOneClickUpdate.Name = "gOneClickUpdate"; 183 | this.gOneClickUpdate.Padding = new System.Windows.Forms.Padding(27, 8, 27, 8); 184 | this.gOneClickUpdate.Size = new System.Drawing.Size(1309, 299); 185 | this.gOneClickUpdate.TabIndex = 11; 186 | this.gOneClickUpdate.TabStop = false; 187 | this.gOneClickUpdate.Text = "SimpleUpdate"; 188 | // 189 | // bUpdateTranslations 190 | // 191 | this.bUpdateTranslations.Dock = System.Windows.Forms.DockStyle.Top; 192 | this.bUpdateTranslations.Location = new System.Drawing.Point(27, 244); 193 | this.bUpdateTranslations.Margin = new System.Windows.Forms.Padding(5); 194 | this.bUpdateTranslations.Name = "bUpdateTranslations"; 195 | this.bUpdateTranslations.Size = new System.Drawing.Size(1255, 46); 196 | this.bUpdateTranslations.TabIndex = 7; 197 | this.bUpdateTranslations.Text = "Translation update"; 198 | this.bUpdateTranslations.UseVisualStyleBackColor = true; 199 | this.bUpdateTranslations.Click += new System.EventHandler(this.bUpdateTranslations_Click); 200 | // 201 | // cbDownloadCurrentTranslation 202 | // 203 | this.cbDownloadCurrentTranslation.Dock = System.Windows.Forms.DockStyle.Top; 204 | this.cbDownloadCurrentTranslation.Location = new System.Drawing.Point(27, 207); 205 | this.cbDownloadCurrentTranslation.Margin = new System.Windows.Forms.Padding(5); 206 | this.cbDownloadCurrentTranslation.Name = "cbDownloadCurrentTranslation"; 207 | this.cbDownloadCurrentTranslation.Size = new System.Drawing.Size(1255, 37); 208 | this.cbDownloadCurrentTranslation.TabIndex = 5; 209 | this.cbDownloadCurrentTranslation.Text = "Download selected language"; 210 | this.cbDownloadCurrentTranslation.UseVisualStyleBackColor = true; 211 | // 212 | // tbOneClickUpdateDesc 213 | // 214 | this.tbOneClickUpdateDesc.Dock = System.Windows.Forms.DockStyle.Top; 215 | this.tbOneClickUpdateDesc.Location = new System.Drawing.Point(27, 39); 216 | this.tbOneClickUpdateDesc.Margin = new System.Windows.Forms.Padding(5); 217 | this.tbOneClickUpdateDesc.Multiline = true; 218 | this.tbOneClickUpdateDesc.Name = "tbOneClickUpdateDesc"; 219 | this.tbOneClickUpdateDesc.ReadOnly = true; 220 | this.tbOneClickUpdateDesc.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; 221 | this.tbOneClickUpdateDesc.Size = new System.Drawing.Size(1255, 168); 222 | this.tbOneClickUpdateDesc.TabIndex = 6; 223 | // 224 | // gCheckSync 225 | // 226 | this.gCheckSync.CheckboxOffset = new System.Drawing.Point(5, 0); 227 | this.gCheckSync.Checked = true; 228 | this.gCheckSync.Controls.Add(this.tbCheckSyncDesc); 229 | this.gCheckSync.Controls.Add(this.cbCheckSync); 230 | this.gCheckSync.DisableControlsIfUnchecked = false; 231 | this.gCheckSync.Dock = System.Windows.Forms.DockStyle.Top; 232 | this.gCheckSync.Location = new System.Drawing.Point(5, 5); 233 | this.gCheckSync.Margin = new System.Windows.Forms.Padding(5); 234 | this.gCheckSync.Name = "gCheckSync"; 235 | this.gCheckSync.Padding = new System.Windows.Forms.Padding(27, 8, 27, 8); 236 | this.gCheckSync.Size = new System.Drawing.Size(1309, 262); 237 | this.gCheckSync.TabIndex = 10; 238 | this.gCheckSync.TabStop = false; 239 | this.gCheckSync.Text = "CheckSync"; 240 | // 241 | // tbCheckSyncDesc 242 | // 243 | this.tbCheckSyncDesc.Dock = System.Windows.Forms.DockStyle.Fill; 244 | this.tbCheckSyncDesc.Location = new System.Drawing.Point(27, 75); 245 | this.tbCheckSyncDesc.Margin = new System.Windows.Forms.Padding(5); 246 | this.tbCheckSyncDesc.Multiline = true; 247 | this.tbCheckSyncDesc.Name = "tbCheckSyncDesc"; 248 | this.tbCheckSyncDesc.ReadOnly = true; 249 | this.tbCheckSyncDesc.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; 250 | this.tbCheckSyncDesc.Size = new System.Drawing.Size(1255, 179); 251 | this.tbCheckSyncDesc.TabIndex = 3; 252 | // 253 | // cbCheckSync 254 | // 255 | this.cbCheckSync.AutoSize = true; 256 | this.cbCheckSync.Dock = System.Windows.Forms.DockStyle.Top; 257 | this.cbCheckSync.Location = new System.Drawing.Point(27, 39); 258 | this.cbCheckSync.Margin = new System.Windows.Forms.Padding(5); 259 | this.cbCheckSync.Name = "cbCheckSync"; 260 | this.cbCheckSync.Size = new System.Drawing.Size(1255, 36); 261 | this.cbCheckSync.TabIndex = 2; 262 | this.cbCheckSync.Text = "CheckSync"; 263 | this.cbCheckSync.UseVisualStyleBackColor = true; 264 | // 265 | // cgKeePassUpdate 266 | // 267 | this.cgKeePassUpdate.CheckboxOffset = new System.Drawing.Point(5, 0); 268 | this.cgKeePassUpdate.Checked = true; 269 | this.cgKeePassUpdate.Controls.Add(this.cbKeePassInstallType); 270 | this.cgKeePassUpdate.Controls.Add(this.lKeePassInstallType); 271 | this.cgKeePassUpdate.Controls.Add(this.tbKeePassFolder); 272 | this.cgKeePassUpdate.Controls.Add(this.lKeePassFolder); 273 | this.cgKeePassUpdate.Controls.Add(this.tbKeePassUpdateInfo); 274 | this.cgKeePassUpdate.Dock = System.Windows.Forms.DockStyle.Top; 275 | this.cgKeePassUpdate.Location = new System.Drawing.Point(18, 15); 276 | this.cgKeePassUpdate.Name = "cgKeePassUpdate"; 277 | this.cgKeePassUpdate.Padding = new System.Windows.Forms.Padding(27, 8, 27, 8); 278 | this.cgKeePassUpdate.Size = new System.Drawing.Size(1283, 508); 279 | this.cgKeePassUpdate.TabIndex = 0; 280 | this.cgKeePassUpdate.Text = "cgKeePassUpdate"; 281 | // 282 | // cbKeePassInstallType 283 | // 284 | this.cbKeePassInstallType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 285 | this.cbKeePassInstallType.FormattingEnabled = true; 286 | this.cbKeePassInstallType.Location = new System.Drawing.Point(130, 410); 287 | this.cbKeePassInstallType.Name = "cbKeePassInstallType"; 288 | this.cbKeePassInstallType.Size = new System.Drawing.Size(463, 39); 289 | this.cbKeePassInstallType.TabIndex = 5; 290 | // 291 | // lKeePassInstallType 292 | // 293 | this.lKeePassInstallType.AutoSize = true; 294 | this.lKeePassInstallType.Location = new System.Drawing.Point(27, 418); 295 | this.lKeePassInstallType.Name = "lKeePassInstallType"; 296 | this.lKeePassInstallType.Size = new System.Drawing.Size(93, 32); 297 | this.lKeePassInstallType.TabIndex = 4; 298 | this.lKeePassInstallType.Text = "label2"; 299 | // 300 | // tbKeePassFolder 301 | // 302 | this.tbKeePassFolder.Location = new System.Drawing.Point(130, 345); 303 | this.tbKeePassFolder.Name = "tbKeePassFolder"; 304 | this.tbKeePassFolder.ReadOnly = true; 305 | this.tbKeePassFolder.Size = new System.Drawing.Size(463, 38); 306 | this.tbKeePassFolder.TabIndex = 3; 307 | // 308 | // lKeePassFolder 309 | // 310 | this.lKeePassFolder.AutoSize = true; 311 | this.lKeePassFolder.Location = new System.Drawing.Point(27, 351); 312 | this.lKeePassFolder.Name = "lKeePassFolder"; 313 | this.lKeePassFolder.Size = new System.Drawing.Size(93, 32); 314 | this.lKeePassFolder.TabIndex = 2; 315 | this.lKeePassFolder.TabStop = true; 316 | this.lKeePassFolder.Text = "label1"; 317 | this.lKeePassFolder.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lKeePassFolder_LinkClicked); 318 | // 319 | // tbKeePassUpdateInfo 320 | // 321 | this.tbKeePassUpdateInfo.Dock = System.Windows.Forms.DockStyle.Top; 322 | this.tbKeePassUpdateInfo.Location = new System.Drawing.Point(27, 39); 323 | this.tbKeePassUpdateInfo.Margin = new System.Windows.Forms.Padding(5); 324 | this.tbKeePassUpdateInfo.Multiline = true; 325 | this.tbKeePassUpdateInfo.Name = "tbKeePassUpdateInfo"; 326 | this.tbKeePassUpdateInfo.ReadOnly = true; 327 | this.tbKeePassUpdateInfo.Size = new System.Drawing.Size(1229, 281); 328 | this.tbKeePassUpdateInfo.TabIndex = 1; 329 | // 330 | // Options 331 | // 332 | this.AutoScaleDimensions = new System.Drawing.SizeF(16F, 31F); 333 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 334 | this.Controls.Add(this.tcEUC); 335 | this.Margin = new System.Windows.Forms.Padding(5); 336 | this.Name = "Options"; 337 | this.Size = new System.Drawing.Size(1339, 744); 338 | this.Load += new System.EventHandler(this.Options_Load); 339 | this.tcEUC.ResumeLayout(false); 340 | this.tpEUCOptions.ResumeLayout(false); 341 | this.tpEUC3rdParty.ResumeLayout(false); 342 | this.tpEUC3rdParty.PerformLayout(); 343 | this.panel1.ResumeLayout(false); 344 | this.panel1.PerformLayout(); 345 | this.tpKeePass.ResumeLayout(false); 346 | this.gOneClickUpdate.ResumeLayout(false); 347 | this.gOneClickUpdate.PerformLayout(); 348 | this.gCheckSync.ResumeLayout(false); 349 | this.gCheckSync.PerformLayout(); 350 | this.cgKeePassUpdate.ResumeLayout(false); 351 | this.cgKeePassUpdate.PerformLayout(); 352 | this.ResumeLayout(false); 353 | 354 | } 355 | 356 | #endregion 357 | 358 | internal RookieUI.CheckedGroupBox gCheckSync; 359 | private System.Windows.Forms.TextBox tbCheckSyncDesc; 360 | internal System.Windows.Forms.CheckBox cbCheckSync; 361 | internal RookieUI.CheckedGroupBox gOneClickUpdate; 362 | private System.Windows.Forms.Button bUpdateTranslations; 363 | internal System.Windows.Forms.CheckBox cbDownloadCurrentTranslation; 364 | private System.Windows.Forms.TextBox tbOneClickUpdateDesc; 365 | private System.Windows.Forms.TabControl tcEUC; 366 | private System.Windows.Forms.TabPage tpEUCOptions; 367 | private System.Windows.Forms.TabPage tpEUC3rdParty; 368 | private System.Windows.Forms.ListView lv3rdPartyPlugins; 369 | private System.Windows.Forms.Panel panel1; 370 | private System.Windows.Forms.TextBox tbFile; 371 | private System.Windows.Forms.LinkLabel lFile; 372 | private System.Windows.Forms.Button bDownloadExternalPluginUpdates; 373 | private System.Windows.Forms.TabPage tpKeePass; 374 | internal RookieUI.CheckedGroupBox cgKeePassUpdate; 375 | internal System.Windows.Forms.ComboBox cbKeePassInstallType; 376 | private System.Windows.Forms.Label lKeePassInstallType; 377 | internal System.Windows.Forms.TextBox tbKeePassFolder; 378 | private System.Windows.Forms.LinkLabel lKeePassFolder; 379 | private System.Windows.Forms.TextBox tbKeePassUpdateInfo; 380 | } 381 | } 382 | -------------------------------------------------------------------------------- /src/Options.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | using KeePass.Resources; 9 | using PluginTranslation; 10 | 11 | namespace EarlyUpdateCheck 12 | { 13 | public partial class Options : UserControl 14 | { 15 | public EarlyUpdateCheckExt Plugin = null; 16 | 17 | internal KeePassLib.Delegates.GAction UpdateExternalPluginUpdates; 18 | 19 | internal KeePass_Update.KeePassInstallType kpit 20 | { 21 | get 22 | { 23 | if (cbKeePassInstallType.SelectedIndex == 0) return KeePass_Update.KeePassInstallType.Setup; 24 | if (cbKeePassInstallType.SelectedIndex == 1) return KeePass_Update.KeePassInstallType.MSI; 25 | return KeePass_Update.KeePassInstallType.Portable; 26 | } 27 | set 28 | { 29 | if (value == KeePass_Update.KeePassInstallType.Setup) cbKeePassInstallType.SelectedIndex = 0; 30 | else if (value == KeePass_Update.KeePassInstallType.MSI) cbKeePassInstallType.SelectedIndex = 1; 31 | else cbKeePassInstallType.SelectedIndex = 2; 32 | } 33 | } 34 | 35 | public Options() 36 | { 37 | InitializeComponent(); 38 | gCheckSync.Text = PluginTranslate.Active; 39 | cbCheckSync.Text = PluginTranslate.CheckSync; 40 | tbCheckSyncDesc.Lines = PluginTranslate.CheckSyncDesc.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); 41 | gOneClickUpdate.Text = PluginTranslate.PluginUpdateOneClick; 42 | tbOneClickUpdateDesc.Lines = PluginTranslate.PluginUpdateOneClickDesc.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); 43 | if (string.IsNullOrEmpty(KeePass.Program.Translation.Properties.Iso6391Code)) 44 | cbDownloadCurrentTranslation.Text = string.Format(PluginTranslate.TranslationDownload_DownloadCurrent, "English"); 45 | else 46 | cbDownloadCurrentTranslation.Text = string.Format(PluginTranslate.TranslationDownload_DownloadCurrent, KeePass.Program.Translation.Properties.NameNative); 47 | bUpdateTranslations.Text = PluginTranslate.TranslationDownload_Update; 48 | if (PluginUpdateHandler.MustShieldify) KeePass.UI.UIUtil.SetShield(bUpdateTranslations, true); 49 | bDownloadExternalPluginUpdates.Text = PluginTranslate.UpdateExternalInfoDownload; 50 | 51 | tpKeePass.Text = PluginTranslate.PluginUpdateKeePass; 52 | cgKeePassUpdate.Text = PluginTranslate.Active; 53 | tbKeePassUpdateInfo.Lines = PluginTranslate.KeePassUpdate_RequestInstallType.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); 54 | tbKeePassFolder.Text = KeePassLib.Utility.UrlUtil.GetFileDirectory(KeePass.Util.WinUtil.GetExecutable(), true, true); 55 | cbKeePassInstallType.Items.Add(KeePass_Update.KeePassInstallType.Setup); 56 | cbKeePassInstallType.Items.Add(KeePass_Update.KeePassInstallType.MSI); 57 | cbKeePassInstallType.Items.Add(KeePass_Update.KeePassInstallType.Portable); 58 | lKeePassFolder.Text = KPRes.Folder + ":"; 59 | 60 | var t = typeof(KPRes).GetProperty("Type"); 61 | if (t != null) lKeePassInstallType.Text = t.GetValue(null, null) + ":"; 62 | else lKeePassInstallType.Text = "Type:"; 63 | } 64 | 65 | private void bUpdateTranslations_Click(object sender, EventArgs e) 66 | { 67 | List lPlugins = new List(); 68 | foreach (PluginUpdate pu in PluginUpdateHandler.Plugins) 69 | { 70 | OwnPluginUpdate opu = pu as OwnPluginUpdate; 71 | if (opu == null) continue; 72 | if (!PluginUpdateHandler.VersionsEqual(pu.VersionInstalled, pu.VersionAvailable)) continue; 73 | if (opu.Translations.Count == 0) continue; 74 | if (!lPlugins.Contains(opu)) lPlugins.Add(opu); 75 | } 76 | if (lPlugins.Count == 0) 77 | { 78 | PluginTools.PluginDebug.AddInfo("No plugins where translations can be updated", 0); 79 | return; 80 | } 81 | using (TranslationUpdateForm t = new TranslationUpdateForm()) 82 | { 83 | t.InitEx(lPlugins); 84 | if (t.ShowDialog() == DialogResult.OK) 85 | { 86 | Plugin.UpdatePluginTranslations(PluginConfig.DownloadActiveLanguage, t.SelectedPlugins); 87 | } 88 | } 89 | } 90 | 91 | private void gCheckSync_CheckedChanged(object sender, RookieUI.CheckedGroupCheckEventArgs e) 92 | { 93 | cbCheckSync.Enabled = gCheckSync.Checked; 94 | } 95 | 96 | private void Options_Load(object sender, EventArgs e) 97 | { 98 | tpEUCOptions.Text = KPRes.Options; 99 | tpEUC3rdParty.Text = KPRes.More; 100 | lFile.Text = KPRes.File; 101 | tbFile.Text = UpdateInfoExternParser.PluginInfoFile; 102 | RefreshPluginList(); 103 | } 104 | 105 | private void RefreshPluginList() 106 | { 107 | if (System.IO.File.Exists(UpdateInfoExternParser.PluginInfoFile)) 108 | { 109 | lFile.Links.Add(0, lFile.Text.Length); 110 | lFile.LinkClicked += LFile_LinkClicked; 111 | } 112 | else lFile.LinkArea = new LinkArea(0, 0); 113 | lv3rdPartyPlugins.Items.Clear(); 114 | foreach (var p in PluginUpdateHandler.Plugins) 115 | { 116 | string s = p.Title + (p is OtherPluginUpdate ? " - " + p.UpdateMode.ToString() : string.Empty); 117 | if (p.Ignore) 118 | { 119 | ListViewItem lvi = new ListViewItem(p.Title); 120 | lvi.Font = new Font(lvi.Font, lvi.Font.Style | FontStyle.Strikeout); 121 | lv3rdPartyPlugins.Items.Add(lvi); 122 | } 123 | else lv3rdPartyPlugins.Items.Add(s); 124 | } 125 | bDownloadExternalPluginUpdates.Visible = UpdateInfoExternParser.VersionInstalled < 0; 126 | } 127 | 128 | private void OnShow3rdPartyTab(object sender, EventArgs e) 129 | { 130 | tbFile.Width = tbFile.Parent.ClientSize.Width - 2 * tbFile.Parent.Padding.Left - 2 * lFile.Left - lFile.Width - 20; 131 | tbFile.Left = lFile.Left + lFile.Width + 10; 132 | } 133 | 134 | private void LFile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 135 | { 136 | PluginTools.Tools.OpenUrl(UpdateInfoExternParser.PluginInfoFile); 137 | } 138 | 139 | private void bDownloadExternalPluginUpdates_Click(object sender, EventArgs e) 140 | { 141 | UpdateExternalPluginUpdates(EarlyUpdateCheckExt.UpdateFlags.ExternalUpdateInfo, true, null); 142 | RefreshPluginList(); 143 | } 144 | 145 | internal void AdjustControls(object sender, EventArgs e) 146 | { 147 | int iDelta = lKeePassFolder.Width; 148 | if (lKeePassInstallType.Width > iDelta) iDelta = lKeePassInstallType.Width; 149 | iDelta += lKeePassFolder.Left + 10; 150 | tbKeePassFolder.Left = cbKeePassInstallType.Left = iDelta; 151 | tbKeePassFolder.Width = tbKeePassUpdateInfo.Width - iDelta + 20; 152 | cbKeePassInstallType.Width = tbKeePassFolder.Width; 153 | } 154 | 155 | internal void ActivateKeePassUpdateTab(object sender, EventArgs e) 156 | { 157 | TabControl tcMain = null; 158 | TabControl tcPluginOptions = null; 159 | TabPage tpEUC = null; 160 | TabPage tpOptions = null; 161 | Control c = tcEUC.Parent; 162 | while (c != null) 163 | { 164 | if (c is TabPage) 165 | { 166 | if (tpEUC == null) tpEUC = c as TabPage; 167 | else if (tpOptions == null) tpOptions = c as TabPage; 168 | } 169 | else if (c is TabControl) 170 | { 171 | if (tcPluginOptions == null) tcPluginOptions = c as TabControl; 172 | else if (tcMain == null) tcMain = c as TabControl; 173 | } 174 | c = c.Parent; 175 | } 176 | if (tcMain != null && tpOptions != null) tcMain.SelectedTab = tpOptions; 177 | if (tcPluginOptions != null && tpEUC != null) tcPluginOptions.SelectedTab = tpEUC; 178 | tcEUC.SelectedTab = tpKeePass; 179 | } 180 | 181 | private void lKeePassFolder_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 182 | { 183 | PluginTools.Tools.OpenUrl(tbKeePassFolder.Text); 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #region Using directives 2 | using System; 3 | using System.Reflection; 4 | using System.Runtime.InteropServices; 5 | 6 | #endregion 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("Early update check")] 11 | [assembly: AssemblyDescription(@"Perform KeePass update check BEFORE opening a database 12 | 13 | One-click update for both KeePass and plugins")] 14 | [assembly: AssemblyConfiguration("")] 15 | [assembly: AssemblyCompany("rookiestyle")] 16 | [assembly: AssemblyProduct("KeePass Plugin")] 17 | [assembly: AssemblyCopyright("Copyright 2021-2025")] 18 | [assembly: AssemblyTrademark("")] 19 | [assembly: AssemblyCulture("")] 20 | // This sets the default COM visibility of types in the assembly to invisible. 21 | // If you need to expose a type to COM, use [ComVisible(true)] on that type. 22 | [assembly: ComVisible(false)] 23 | // The assembly version has following format : 24 | // 25 | // Major.Minor.Build.Revision 26 | // 27 | // You can specify all the values or you can use the default the Revision and 28 | // Build Numbers by using the '*' as shown below: 29 | [assembly: AssemblyVersion("4.2.4")] 30 | [assembly: AssemblyFileVersion("4.2.4")] 31 | [assembly: Guid("672570AF-CC57-4980-86F9-D48FD1CC707D")] 32 | -------------------------------------------------------------------------------- /src/TranslationUpdateForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace EarlyUpdateCheck 2 | { 3 | partial class TranslationUpdateForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); 32 | this.panel1 = new System.Windows.Forms.Panel(); 33 | this.bCancel = new System.Windows.Forms.Button(); 34 | this.bOK = new System.Windows.Forms.Button(); 35 | this.clbPlugins = new System.Windows.Forms.CheckedListBox(); 36 | this.lSelectPlugins = new System.Windows.Forms.Label(); 37 | this.tableLayoutPanel1.SuspendLayout(); 38 | this.panel1.SuspendLayout(); 39 | this.SuspendLayout(); 40 | // 41 | // tableLayoutPanel1 42 | // 43 | this.tableLayoutPanel1.ColumnCount = 1; 44 | this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); 45 | this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 2); 46 | this.tableLayoutPanel1.Controls.Add(this.clbPlugins, 0, 1); 47 | this.tableLayoutPanel1.Controls.Add(this.lSelectPlugins, 0, 0); 48 | this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; 49 | this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); 50 | this.tableLayoutPanel1.Name = "tableLayoutPanel1"; 51 | this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(10, 5, 10, 5); 52 | this.tableLayoutPanel1.RowCount = 3; 53 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); 54 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); 55 | this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); 56 | this.tableLayoutPanel1.Size = new System.Drawing.Size(800, 450); 57 | this.tableLayoutPanel1.TabIndex = 0; 58 | // 59 | // panel1 60 | // 61 | this.panel1.Controls.Add(this.bCancel); 62 | this.panel1.Controls.Add(this.bOK); 63 | this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; 64 | this.panel1.Location = new System.Drawing.Point(13, 398); 65 | this.panel1.Name = "panel1"; 66 | this.panel1.Size = new System.Drawing.Size(774, 44); 67 | this.panel1.TabIndex = 0; 68 | // 69 | // bCancel 70 | // 71 | this.bCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 72 | this.bCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 73 | this.bCancel.Location = new System.Drawing.Point(671, 10); 74 | this.bCancel.Name = "bCancel"; 75 | this.bCancel.Size = new System.Drawing.Size(100, 30); 76 | this.bCancel.TabIndex = 1; 77 | this.bCancel.Text = "Cancel"; 78 | this.bCancel.UseVisualStyleBackColor = true; 79 | // 80 | // bOK 81 | // 82 | this.bOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 83 | this.bOK.AutoSize = true; 84 | this.bOK.DialogResult = System.Windows.Forms.DialogResult.OK; 85 | this.bOK.Location = new System.Drawing.Point(551, 10); 86 | this.bOK.Name = "bOK"; 87 | this.bOK.Size = new System.Drawing.Size(100, 30); 88 | this.bOK.TabIndex = 0; 89 | this.bOK.Text = "OK"; 90 | this.bOK.UseVisualStyleBackColor = true; 91 | // 92 | // clbPlugins 93 | // 94 | this.clbPlugins.CheckOnClick = true; 95 | this.clbPlugins.Dock = System.Windows.Forms.DockStyle.Fill; 96 | this.clbPlugins.FormattingEnabled = true; 97 | this.clbPlugins.Location = new System.Drawing.Point(13, 58); 98 | this.clbPlugins.Name = "clbPlugins"; 99 | this.clbPlugins.Size = new System.Drawing.Size(774, 334); 100 | this.clbPlugins.TabIndex = 1; 101 | this.clbPlugins.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.clbPlugins_ItemCheck); 102 | // 103 | // lSelectPlugins 104 | // 105 | this.lSelectPlugins.AutoSize = true; 106 | this.lSelectPlugins.Location = new System.Drawing.Point(13, 5); 107 | this.lSelectPlugins.Name = "lSelectPlugins"; 108 | this.lSelectPlugins.Size = new System.Drawing.Size(108, 20); 109 | this.lSelectPlugins.TabIndex = 2; 110 | this.lSelectPlugins.Text = "Select plugins"; 111 | // 112 | // TranslationUpdateForm 113 | // 114 | this.AcceptButton = this.bOK; 115 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); 116 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 117 | this.CancelButton = this.bCancel; 118 | this.ClientSize = new System.Drawing.Size(800, 450); 119 | this.Controls.Add(this.tableLayoutPanel1); 120 | this.MaximizeBox = false; 121 | this.MinimizeBox = false; 122 | this.Name = "TranslationUpdateForm"; 123 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 124 | this.Text = "TranslationUpdateForm"; 125 | this.Load += new System.EventHandler(this.TranslationUpdateForm_Load); 126 | this.tableLayoutPanel1.ResumeLayout(false); 127 | this.tableLayoutPanel1.PerformLayout(); 128 | this.panel1.ResumeLayout(false); 129 | this.panel1.PerformLayout(); 130 | this.ResumeLayout(false); 131 | 132 | } 133 | 134 | #endregion 135 | 136 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; 137 | private System.Windows.Forms.Panel panel1; 138 | private System.Windows.Forms.CheckedListBox clbPlugins; 139 | private System.Windows.Forms.Label lSelectPlugins; 140 | private System.Windows.Forms.Button bCancel; 141 | private System.Windows.Forms.Button bOK; 142 | } 143 | } -------------------------------------------------------------------------------- /src/TranslationUpdateForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | using KeePass.Resources; 9 | using PluginTranslation; 10 | 11 | namespace EarlyUpdateCheck 12 | { 13 | public partial class TranslationUpdateForm : Form 14 | { 15 | public TranslationUpdateForm() 16 | { 17 | InitializeComponent(); 18 | } 19 | 20 | internal void InitEx(List lPlugins) 21 | { 22 | Text = PluginTranslate.TranslationUpdateForm; 23 | lSelectPlugins.Text = PluginTranslate.SelectPluginsForTranslationUpdate; 24 | bOK.Text = PluginTranslate.TranslationDownload_Update; 25 | bOK.Text = PluginTranslate.PluginUpdateSelected; 26 | bCancel.Text = KPRes.Cancel; 27 | 28 | clbPlugins.Items.Clear(); 29 | lPlugins.Sort(SortOwnPluginUpdate); 30 | foreach (OwnPluginUpdate plugin in lPlugins) 31 | clbPlugins.Items.Add(plugin.Name, PluginUpdateHandler.VersionsEqual(plugin.VersionInstalled, plugin.VersionAvailable) ? CheckState.Checked : CheckState.Indeterminate); 32 | } 33 | 34 | private int SortOwnPluginUpdate(OwnPluginUpdate a, OwnPluginUpdate b) 35 | { 36 | return -1 * string.Compare(a.Name, b.Name); 37 | } 38 | 39 | public List SelectedPlugins 40 | { 41 | get 42 | { 43 | List lPlugins = new List(); 44 | foreach (int i in clbPlugins.CheckedIndices) 45 | { 46 | if (clbPlugins.GetItemCheckState(i) == CheckState.Checked) lPlugins.Add(clbPlugins.Items[i] as string); 47 | } 48 | return lPlugins; 49 | } 50 | } 51 | 52 | private void clbPlugins_ItemCheck(object sender, ItemCheckEventArgs e) 53 | { 54 | if (e.CurrentValue == CheckState.Indeterminate) 55 | { 56 | e.NewValue = CheckState.Indeterminate; 57 | } 58 | bool bChecked = e.NewValue == CheckState.Checked; 59 | foreach (int i in clbPlugins.CheckedIndices) 60 | { 61 | if (i == e.Index) continue; 62 | else bChecked |= clbPlugins.GetItemCheckState(i) == CheckState.Checked; 63 | if (bChecked) break; 64 | } 65 | bOK.Enabled = bChecked; // (e.NewValue == CheckState.Checked) || (clbPlugins.CheckedItems.Count > 1); 66 | } 67 | 68 | private void TranslationUpdateForm_Load(object sender, EventArgs e) 69 | { 70 | bOK.Left = bCancel.Left - bOK.Width - 15; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Utilities/Debug.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Reflection; 5 | using System.Windows.Forms; 6 | using KeePass.Forms; 7 | using KeePass.UI; 8 | using KeePassLib.Utility; 9 | using Microsoft.Win32; 10 | 11 | namespace PluginTools 12 | { 13 | public static class PluginDebug 14 | { 15 | [Flags] 16 | public enum LogLevelFlags 17 | { 18 | None = 0, 19 | Info = 1, 20 | Warning = 2, 21 | Error = 4, 22 | Success = 8, 23 | All = Info | Warning | Error | Success 24 | } 25 | 26 | public static string DebugFile { get; private set; } 27 | public static LogLevelFlags LogLevel = LogLevelFlags.All; 28 | 29 | private static bool AutoSave = false; 30 | private static bool AutoOpen = false; 31 | private static bool AskOpen = true; 32 | private static List m_DebugEntries = new List(); 33 | private static string PluginName = string.Empty; 34 | private static string PluginVersion; 35 | private static bool m_DebugMode = false; 36 | public static bool DebugMode 37 | { 38 | get { return m_DebugMode; } 39 | set { m_DebugMode = value; } 40 | } 41 | private static Dictionary m_plugins = new Dictionary(); 42 | public static Version DotNetVersion { get; private set; } 43 | private static int m_DotNetRelease = 0; 44 | 45 | private static DateTime m_Start = DateTime.UtcNow; 46 | 47 | //Init 48 | static PluginDebug() 49 | { 50 | PluginName = Assembly.GetExecutingAssembly().GetName().Name; 51 | PluginVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); 52 | 53 | ulong uInst = KeePass.Util.WinUtil.GetMaxNetFrameworkVersion(); 54 | DotNetVersion = new Version(StrUtil.VersionToString(uInst)); 55 | try 56 | { 57 | RegistryKey rkRel = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full", false); 58 | m_DotNetRelease = (int)rkRel.GetValue("Release"); 59 | if (rkRel != null) rkRel.Close(); 60 | } 61 | catch { } 62 | 63 | DebugFile = System.IO.Path.GetTempPath() + "Debug_" + PluginName + "_" + m_Start.ToString("yyyyMMddTHHmmssZ") + ".xml"; 64 | 65 | string level = KeePass.Program.CommandLineArgs["debuglevel"]; 66 | if (string.IsNullOrEmpty(level)) 67 | level = LogLevelFlags.All.ToString(); 68 | try 69 | { 70 | LogLevel = (LogLevelFlags)Enum.Parse(LogLevel.GetType(), level); 71 | } 72 | catch { } 73 | AutoSave = KeePass.Program.CommandLineArgs["debugautosave"] != null; 74 | AutoOpen = KeePass.Program.CommandLineArgs["debugautoopen"] != null; 75 | AskOpen = KeePass.Program.CommandLineArgs["debugsaveonly"] == null; 76 | 77 | DebugMode = KeePass.Program.CommandLineArgs[KeePass.App.AppDefs.CommandLineOptions.Debug] != null; 78 | if (!DebugMode && (KeePass.Program.CommandLineArgs["debugplugin"] != null)) 79 | { 80 | try 81 | { 82 | string[] plugins = KeePass.Program.CommandLineArgs["debugplugin"].ToLowerInvariant().Split(new char[] { ',' }); 83 | DebugMode |= Array.Find(plugins, x => x.Trim() == PluginName.ToLowerInvariant()) != null; 84 | DebugMode |= Array.Find(plugins, x => x.Trim() == "all") != null; 85 | } 86 | catch { } 87 | } 88 | KeePass.Program.MainForm.FormLoadPost += LoadPluginNames; 89 | if (AutoSave) 90 | AddInfo("AutoSave mode active", 0); 91 | } 92 | 93 | #region Handle debug messages 94 | public static void AddInfo(string msg) 95 | { 96 | AddMessage(LogLevelFlags.Info, msg, 5, null); 97 | } 98 | 99 | public static void AddInfo(string msg, params string[] parameters) 100 | { 101 | AddMessage(LogLevelFlags.Info, msg, 5, parameters); 102 | } 103 | 104 | public static void AddInfo(string msg, int CallstackFrames) 105 | { 106 | AddMessage(LogLevelFlags.Info, msg, CallstackFrames, null); 107 | } 108 | 109 | public static void AddInfo(string msg, int CallstackFrames, params string[] parameters) 110 | { 111 | AddMessage(LogLevelFlags.Info, msg, CallstackFrames, parameters); 112 | } 113 | 114 | public static void AddWarning(string msg) 115 | { 116 | AddMessage(LogLevelFlags.Warning, msg, 5, null); 117 | } 118 | 119 | public static void AddWarning(string msg, params string[] parameters) 120 | { 121 | AddMessage(LogLevelFlags.Warning, msg, 5, parameters); 122 | } 123 | 124 | public static void AddWarning(string msg, int CallstackFrames) 125 | { 126 | AddMessage(LogLevelFlags.Warning, msg, CallstackFrames, null); 127 | } 128 | 129 | public static void AddWarning(string msg, int CallstackFrames, params string[] parameters) 130 | { 131 | AddMessage(LogLevelFlags.Warning, msg, CallstackFrames, parameters); 132 | } 133 | 134 | public static void AddError(string msg) 135 | { 136 | AddMessage(LogLevelFlags.Error, msg, 5, null); 137 | } 138 | 139 | public static void AddError(string msg, params string[] parameters) 140 | { 141 | AddMessage(LogLevelFlags.Error, msg, 5, parameters); 142 | } 143 | 144 | public static void AddError(string msg, int CallstackFrames) 145 | { 146 | AddMessage(LogLevelFlags.Error, msg, CallstackFrames, null); 147 | } 148 | 149 | public static void AddError(string msg, int CallstackFrames, params string[] parameters) 150 | { 151 | AddMessage(LogLevelFlags.Error, msg, CallstackFrames, parameters); 152 | } 153 | 154 | public static void AddSuccess(string msg) 155 | { 156 | AddMessage(LogLevelFlags.Success, msg, 5, null); 157 | } 158 | 159 | public static void AddSuccess(string msg, params string[] parameters) 160 | { 161 | AddMessage(LogLevelFlags.Success, msg, 5, parameters); 162 | } 163 | 164 | public static void AddSuccess(string msg, int CallstackFrames) 165 | { 166 | AddMessage(LogLevelFlags.Success, msg, CallstackFrames, null); 167 | } 168 | 169 | public static void AddSuccess(string msg, int CallstackFrames, params string[] parameters) 170 | { 171 | AddMessage(LogLevelFlags.Success, msg, CallstackFrames, parameters); 172 | } 173 | 174 | private static void AddMessage(LogLevelFlags severity, string msg, int CallstackFrames, string[] parameters) 175 | { 176 | if (m_Saving || !DebugMode || ((severity & LogLevel) != severity)) return; 177 | if (m_DebugEntries.Count > 0) 178 | { 179 | DebugEntry prev = m_DebugEntries[m_DebugEntries.Count - 1]; 180 | if ((prev.severity == severity) && (prev.msg == msg) && ParamsEqual(prev.parameters, parameters)) 181 | { 182 | m_DebugEntries[m_DebugEntries.Count - 1].counter++; 183 | return; 184 | } 185 | } 186 | DebugEntry m = new DebugEntry(); 187 | m.severity = severity; 188 | m.msg = msg; 189 | m.utc = DateTime.UtcNow; 190 | m.counter = 1; 191 | m.parameters = parameters; 192 | if (CallstackFrames != 0) 193 | { 194 | System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(true); 195 | for (int i = 0; i < st.FrameCount; i++) 196 | { 197 | if (m.sf.Count == CallstackFrames) break; 198 | System.Diagnostics.StackFrame sf = st.GetFrame(i); 199 | if (sf.GetMethod().DeclaringType.FullName != "PluginTools.PluginDebug") 200 | m.sf.Add(sf); 201 | } 202 | } 203 | m_DebugEntries.Add(m); 204 | if (AutoSave) SaveDebugMessages(); 205 | } 206 | 207 | private static bool ParamsEqual(string[] a, string[] b) 208 | { 209 | if ((a == null) && (b == null)) return true; 210 | if ((a == null) && (b != null)) return false; 211 | if ((a != null) && (b == null)) return false; 212 | if (a.Length != b.Length) return false; 213 | for (int i = 0; i < a.Length; i++) 214 | if (a[i] != b[i]) return false; 215 | return true; 216 | } 217 | 218 | public static bool HasMessage(LogLevelFlags severity, string msg) 219 | { 220 | return m_DebugEntries.Find(x => (x.severity == severity) && (x.msg == msg)) != null; 221 | } 222 | #endregion 223 | 224 | public static void SaveOrShow() 225 | { 226 | if (m_DebugEntries.Count == 0) return; 227 | SaveDebugMessages(); 228 | if (AutoOpen || (AskOpen && Tools.AskYesNo("DebugFile: " + DebugFile + "\n\nOpen debug file?") == DialogResult.Yes)) 229 | { 230 | try 231 | { 232 | System.Diagnostics.Process.Start(DebugFile); 233 | } 234 | catch 235 | { 236 | if (KeePassLib.Native.NativeLib.IsUnix()) //The above is broken on mono 237 | { 238 | System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(); 239 | psi.Arguments = DebugFile; 240 | psi.FileName = "xdg-open"; 241 | System.Diagnostics.Process.Start(psi); 242 | } 243 | } 244 | } 245 | } 246 | 247 | private static System.Xml.XmlWriter m_xw = null; 248 | private static System.IO.StringWriter m_sw = null; 249 | private static void StartXml() 250 | { 251 | m_sw = new System.IO.StringWriter(); 252 | System.Xml.XmlWriterSettings ws = new System.Xml.XmlWriterSettings(); 253 | ws.OmitXmlDeclaration = true; 254 | ws.Indent = true; 255 | ws.IndentChars = "\t"; 256 | m_xw = System.Xml.XmlWriter.Create(m_sw, ws); 257 | } 258 | 259 | private static string Xml 260 | { 261 | get 262 | { 263 | if (m_xw == null) return string.Empty; 264 | m_sw.Flush(); 265 | m_xw.Flush(); 266 | string s = m_sw.ToString(); 267 | m_xw = null; 268 | m_sw = null; 269 | return s; 270 | } 271 | } 272 | 273 | public static string DebugMessages 274 | { 275 | get 276 | { 277 | StartXml(); 278 | LoadPluginNames(null, null); 279 | string sEncoding = "\n"; 280 | m_xw.WriteStartElement("DebugInfo"); 281 | #region General info 282 | m_xw.WriteStartElement("General"); 283 | m_xw.WriteStartElement("Plugin"); 284 | m_xw.WriteElementString("PluginName", PluginName); 285 | m_xw.WriteElementString("PluginVersion", PluginVersion); 286 | m_xw.WriteEndElement(); 287 | m_xw.WriteStartElement("DebugTime"); 288 | m_xw.WriteElementString("DebugStart", m_Start.ToString("yyyyMMddTHHmmssZ")); 289 | m_xw.WriteElementString("DebugEnd", DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ")); 290 | m_xw.WriteEndElement(); 291 | m_xw.WriteElementString("LogLevel", LogLevel.ToString()); 292 | 293 | #region Add OS info 294 | string os = string.Empty; 295 | if (KeePass.Util.WinUtil.IsWindows9x) 296 | os = "Windows 9x"; 297 | else if (KeePass.Util.WinUtil.IsWindows2000) 298 | os = "Windows 2000"; 299 | else if (KeePass.Util.WinUtil.IsWindowsXP) 300 | os = "Windows XP"; 301 | else 302 | { 303 | if (KeePass.Util.WinUtil.IsAtLeastWindows10) 304 | os = ">= Windows 10"; 305 | else if (KeePass.Util.WinUtil.IsAtLeastWindows8) 306 | os = ">= Windows 8"; 307 | else if (KeePass.Util.WinUtil.IsAtLeastWindows7) 308 | os = ">= Windows 7"; 309 | else if (KeePass.Util.WinUtil.IsAtLeastWindowsVista) 310 | os = ">= Windows Vista"; 311 | else if (KeePass.Util.WinUtil.IsAtLeastWindows2000) 312 | os = ">= Windows 2000"; 313 | else os = "Unknown"; 314 | } 315 | if (KeePass.Util.WinUtil.IsAppX) 316 | os += " (AppX)"; 317 | os += " - " + Environment.OSVersion.ToString(); 318 | m_xw.WriteElementString("OS", KeePass.Util.WinUtil.GetOSStr() + " " + os); 319 | #endregion 320 | m_xw.WriteElementString("DotNet", DotNetVersion.ToString() + (m_DotNetRelease > 0 ? " (" + m_DotNetRelease.ToString() + ")" : string.Empty)); 321 | m_xw.WriteElementString("KeePass", Tools.KeePassVersion.ToString()); 322 | 323 | m_xw.WriteStartElement("LoadedPlugins"); 324 | foreach (KeyValuePair kvp in m_plugins) 325 | { 326 | m_xw.WriteStartElement("Plugin"); 327 | m_xw.WriteElementString("PluginName", kvp.Key); 328 | m_xw.WriteElementString("PluginVersion", kvp.Value.ToString()); 329 | m_xw.WriteEndElement(); 330 | } 331 | m_xw.WriteEndElement(); 332 | m_xw.WriteEndElement(); 333 | #endregion 334 | 335 | if (m_DebugEntries.Count == 0) 336 | m_xw.WriteElementString("DebugMessages", null); 337 | else 338 | { 339 | m_xw.WriteStartElement("DebugMessages"); 340 | foreach (var m in m_DebugEntries) 341 | m.GetXml(m_xw); 342 | m_xw.WriteEndElement(); 343 | } 344 | 345 | m_xw.WriteEndElement(); 346 | return sEncoding + Xml; 347 | } 348 | } 349 | 350 | private static bool m_Saving = false; 351 | public static void SaveDebugMessages() 352 | { 353 | if (m_Saving) return; 354 | m_Saving = true; 355 | try 356 | { 357 | System.IO.File.WriteAllText(DebugFile, DebugMessages); 358 | } 359 | catch (Exception ex) 360 | { 361 | Tools.ShowError("Can't save debug file: " + DebugFile + "\n\n" + ex.Message); 362 | } 363 | m_Saving = false; 364 | } 365 | 366 | private static bool m_bAllPluginsLoaded = false; 367 | private static void LoadPluginNames(object sender, EventArgs e) 368 | { 369 | if (m_bAllPluginsLoaded) return; 370 | m_plugins = Tools.GetLoadedPluginsName(); 371 | if (sender == null) return; 372 | m_bAllPluginsLoaded = true; 373 | KeePass.Program.MainForm.FormLoadPost -= LoadPluginNames; 374 | } 375 | 376 | private class DebugEntry 377 | { 378 | public LogLevelFlags severity; 379 | public string msg; 380 | public DateTime utc; 381 | public int counter; 382 | public List sf = new List(); 383 | public string[] parameters = null; 384 | 385 | public void GetXml(System.Xml.XmlWriter xw) 386 | { 387 | xw.WriteStartElement("DebugEntry"); 388 | xw.WriteElementString("Message", msg); 389 | xw.WriteElementString("Counter", counter.ToString()); 390 | xw.WriteElementString("Severity", severity.ToString()); 391 | xw.WriteElementString("DateTimeUtc", utc.ToString("yyyyMMddTHHmmssZ")); 392 | if ((parameters == null) || parameters.Length == 0) 393 | xw.WriteElementString("Parameters", null); 394 | else 395 | { 396 | xw.WriteStartElement("Parameters"); 397 | foreach (string p in parameters) 398 | xw.WriteElementString("Param", p); 399 | xw.WriteEndElement(); 400 | } 401 | if (sf.Count == 0) 402 | xw.WriteElementString("StackFrames", null); 403 | else 404 | { 405 | xw.WriteStartElement("StackFrames"); 406 | foreach (var f in sf) 407 | { 408 | xw.WriteStartElement("StackFrame"); 409 | xw.WriteElementString("Method", f.GetMethod().Name + " (" + f.GetMethod().DeclaringType.FullName + ")"); 410 | xw.WriteElementString("FileName", System.IO.Path.GetFileName(f.GetFileName())); 411 | xw.WriteElementString("Line", f.GetFileLineNumber().ToString()); 412 | xw.WriteEndElement(); 413 | } 414 | xw.WriteEndElement(); 415 | } 416 | xw.WriteEndElement(); 417 | } 418 | } 419 | } 420 | } 421 | -------------------------------------------------------------------------------- /src/Utilities/EUC_EventHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Reflection; 5 | using System.Windows.Forms; 6 | using KeePass.UI; 7 | 8 | namespace PluginTools 9 | { 10 | public static class EventHelper 11 | { 12 | private static Dictionary> m_dicEventFieldInfos = new Dictionary>(); 13 | 14 | private const BindingFlags AllBindings = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; 15 | private const string EVENTNAME_ItemActivate = "ItemActivate"; 16 | private const string EVENTNAME_FormLoadPost = "FormLoadPost"; 17 | private static Type tListView = typeof(ListView); 18 | private static Type tMainform = typeof(KeePass.Forms.MainForm); 19 | 20 | private static FieldInfo GetEventField(string e, Type t) 21 | { 22 | EventInfo ei = t.GetEvent(e, AllBindings); 23 | FieldInfo fi = t.GetField(e, AllBindings); 24 | if (fi == null) fi = t.GetField("Event" + ei.Name, AllBindings); 25 | 26 | if (fi == null) fi = t.GetField(ei.Name + "Event", AllBindings); 27 | 28 | if (fi == null) fi = t.GetField("on" + ei.Name, AllBindings); 29 | 30 | return fi; 31 | } 32 | 33 | private static EventHandlerList GetStaticEventHandlerList(object obj) 34 | { 35 | MethodInfo mi = tListView.GetMethod("get_Events", AllBindings); 36 | if (mi == null) return null; 37 | return (EventHandlerList)mi.Invoke(obj, new object[] { }); 38 | } 39 | 40 | internal static void RemoveItemActivateEventHandlers(CustomListViewEx lvPlugins, List m_lEventHandlerItemActivate) 41 | { 42 | FieldInfo fi = GetEventField(EVENTNAME_ItemActivate, tListView); 43 | if (fi == null) return; 44 | EventInfo ei = tListView.GetEvent(EVENTNAME_ItemActivate, AllBindings); 45 | if (ei == null) ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); 46 | if (ei == null) return; 47 | 48 | foreach (Delegate del in m_lEventHandlerItemActivate) ei.RemoveEventHandler(lvPlugins, del); 49 | } 50 | 51 | internal static List GetItemActivateHandlers(CustomListViewEx lvPlugins) 52 | { 53 | List lResult = new List(); 54 | FieldInfo fi = GetEventField(EVENTNAME_ItemActivate, tListView); 55 | if (fi == null) return lResult; 56 | if (fi.IsStatic) //Unix (Mono) 57 | { 58 | EventHandlerList static_event_handlers = GetStaticEventHandlerList(lvPlugins); 59 | 60 | object idx = fi.GetValue(lvPlugins); 61 | Delegate eh = static_event_handlers[idx]; 62 | if (eh != null) 63 | { 64 | Delegate[] dels = eh.GetInvocationList(); 65 | if (dels != null) lResult.AddRange(dels); 66 | } 67 | } 68 | else //Windows 69 | { 70 | EventInfo ei = tListView.GetEvent(EVENTNAME_ItemActivate, AllBindings); //Windows 71 | if (ei != null) 72 | { 73 | object val = fi.GetValue(lvPlugins); 74 | Delegate mdel = (val as Delegate); 75 | if (mdel != null) lResult.AddRange(mdel.GetInvocationList()); 76 | } 77 | } 78 | return lResult; 79 | } 80 | 81 | internal static List GetFormLoadPostHandlers() 82 | { 83 | List lResult = new List(); 84 | FieldInfo fi = GetEventField(EVENTNAME_FormLoadPost, tMainform); 85 | if (fi == null) return lResult; 86 | if (fi.IsStatic) //Unix (Mono) 87 | { 88 | EventHandlerList static_event_handlers = GetStaticEventHandlerList(KeePass.Program.MainForm); 89 | 90 | object idx = fi.GetValue(KeePass.Program.MainForm); 91 | Delegate eh = static_event_handlers[idx]; 92 | if (eh != null) 93 | { 94 | Delegate[] dels = eh.GetInvocationList(); 95 | if (dels != null) lResult.AddRange(dels); 96 | } 97 | } 98 | else //Windows 99 | { 100 | EventInfo ei = tMainform.GetEvent(EVENTNAME_FormLoadPost, AllBindings); //Windows 101 | if (ei != null) 102 | { 103 | object val = fi.GetValue(KeePass.Program.MainForm); 104 | Delegate mdel = (val as Delegate); 105 | if (mdel != null) lResult.AddRange(mdel.GetInvocationList()); 106 | } 107 | } 108 | return lResult; 109 | } 110 | 111 | internal static void RemoveFormLoadPostEventHandlers(List handlers) 112 | { 113 | FieldInfo fi = GetEventField(EVENTNAME_FormLoadPost, tMainform); 114 | if (fi == null) return; 115 | EventInfo ei = tMainform.GetEvent(EVENTNAME_ItemActivate, AllBindings); 116 | if (ei == null) ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); 117 | if (ei == null) return; 118 | 119 | if (KeePass.Program.MainForm != null) 120 | lock (KeePass.Program.MainForm) 121 | { 122 | foreach (Delegate del in handlers) ei.RemoveEventHandler(KeePass.Program.MainForm, del); 123 | } 124 | } 125 | 126 | internal static void RestoreFormLoadPostEventHandlers(List handlers) 127 | { 128 | FieldInfo fi = GetEventField(EVENTNAME_FormLoadPost, tMainform); 129 | if (fi == null) return; 130 | 131 | if (fi.IsStatic) 132 | { 133 | EventInfo ei = tMainform.GetEvent(fi.Name, AllBindings); 134 | if (ei == null) 135 | ei = tMainform.GetEvent(EVENTNAME_FormLoadPost, AllBindings); 136 | if (ei == null) 137 | ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); 138 | if (ei == null) 139 | ei = fi.DeclaringType.GetEvent(EVENTNAME_FormLoadPost, AllBindings); 140 | if (ei == null) return; 141 | 142 | foreach (var del in handlers) 143 | ei.AddEventHandler(KeePass.Program.MainForm, del); 144 | } 145 | else 146 | { 147 | EventInfo ei = tMainform.GetEvent(fi.Name, AllBindings); 148 | if (ei == null) 149 | ei = tMainform.GetEvent(EVENTNAME_FormLoadPost, AllBindings); 150 | if (ei == null) 151 | ei = fi.DeclaringType.GetEvent(fi.Name, AllBindings); 152 | if (ei == null) 153 | ei = fi.DeclaringType.GetEvent(EVENTNAME_FormLoadPost, AllBindings); 154 | if (ei != null) 155 | { 156 | foreach (var del in handlers) 157 | ei.AddEventHandler(KeePass.Program.MainForm, del); 158 | } 159 | } 160 | } 161 | } 162 | } 163 | 164 | namespace System.Runtime.CompilerServices 165 | { 166 | [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class 167 | | AttributeTargets.Method)] 168 | public sealed class ExtensionAttribute : Attribute { } 169 | } 170 | -------------------------------------------------------------------------------- /src/Utilities/PluginTranslation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Windows.Forms; 6 | using System.Xml; 7 | using System.Xml.Serialization; 8 | using KeePass.Plugins; 9 | using KeePass.Util; 10 | using KeePassLib.Utility; 11 | using PluginTools; 12 | 13 | namespace PluginTranslation 14 | { 15 | public class TranslationChangedEventArgs : EventArgs 16 | { 17 | public string OldLanguageIso6391 = string.Empty; 18 | public string NewLanguageIso6391 = string.Empty; 19 | 20 | public TranslationChangedEventArgs(string OldLanguageIso6391, string NewLanguageIso6391) 21 | { 22 | this.OldLanguageIso6391 = OldLanguageIso6391; 23 | this.NewLanguageIso6391 = NewLanguageIso6391; 24 | } 25 | } 26 | 27 | public static class PluginTranslate 28 | { 29 | public static long TranslationVersion = 0; 30 | public static event EventHandler TranslationChanged = null; 31 | private static string LanguageIso6391 = string.Empty; 32 | #region Definitions of translated texts go here 33 | public const string PluginName = "Early Update Check"; 34 | /// 35 | /// Active 36 | /// 37 | public static readonly string Active = @"Active"; 38 | /// 39 | /// Update check in foreground 40 | /// 41 | public static readonly string CheckSync = @"Update check in foreground"; 42 | /// 43 | /// EarlyUpdateCheck will always start the update check at the earliest possible time. 44 | /// 45 | /// If this option is active, EarlyUpdateCheck will additionally ensure the update check is finished BEFORE the 'Open Database' window is shown. 46 | /// You may have the upgrade check continue in background if you don't want to wait for its completion. 47 | /// 48 | public static readonly string CheckSyncDesc = @"EarlyUpdateCheck will always start the update check at the earliest possible time. 49 | 50 | If this option is active, EarlyUpdateCheck will additionally ensure the update check is finished BEFORE the 'Open Database' window is shown. 51 | You may have the upgrade check continue in background if you don't want to wait for its completion."; 52 | /// 53 | /// Continue in background 54 | /// 55 | public static readonly string EnterBackgroundMode = @"Continue in background"; 56 | /// 57 | /// One-Click plugin update 58 | /// 59 | public static readonly string PluginUpdateOneClick = @"One-Click plugin update"; 60 | /// 61 | /// Install new versions of plugins by clicking the plugin in the 'Update Check' window. 62 | /// This requires write access to KeePass' plugin folder. 63 | /// KeePass needs to be restarted afterwards in order to use the new version. 64 | /// 65 | /// Maintain file ExternalPluginUpdates.xml to include other authors' plugins, see the wiki for more details 66 | /// 67 | public static readonly string PluginUpdateOneClickDesc = @"Install new versions of plugins by clicking the plugin in the 'Update Check' window. 68 | This requires write access to KeePass' plugin folder. 69 | KeePass needs to be restarted afterwards in order to use the new version. 70 | 71 | Maintain file ExternalPluginUpdates.xml to include other authors' plugins, see the wiki for more details"; 72 | /// 73 | /// Update 74 | /// 75 | public static readonly string PluginUpdate = @"Update"; 76 | /// 77 | /// Update KeePass 78 | /// 79 | public static readonly string PluginUpdateKeePass = @"Update KeePass"; 80 | /// 81 | /// Update plugins 82 | /// 83 | public static readonly string PluginUpdateSelected = @"Update plugins"; 84 | /// 85 | /// Early Update Check - Plugin Updater 86 | /// 87 | public static readonly string PluginUpdateCaption = @"Early Update Check - Plugin Updater"; 88 | /// 89 | /// Updating {0}, please wait... 90 | /// 91 | public static readonly string PluginUpdating = @"Updating {0}, please wait..."; 92 | /// 93 | /// The update was successful, the new version(s) will be active after a restart of KeePass. 94 | /// Restart now? 95 | /// 96 | public static readonly string PluginUpdateSuccess = @"The update was successful, the new version(s) will be active after a restart of KeePass. 97 | Restart now?"; 98 | /// 99 | /// Moving downloaded files failed. Open temporary folder instead? 100 | /// 101 | public static readonly string PluginUpdateFailed = @"Moving downloaded files failed. Open temporary folder instead?"; 102 | /// 103 | /// Plugin: {0} 104 | /// The update failed 105 | /// 106 | public static readonly string PluginUpdateFailedSpecific = @"Plugin: {0} 107 | The update failed"; 108 | /// 109 | /// Plugin: {0} 110 | /// Update of language file {1} failed 111 | /// 112 | public static readonly string PluginTranslationUpdateFailed = @"Plugin: {0} 113 | Update of language file {1} failed"; 114 | /// 115 | /// Update could not be finished. Try alternative method? 116 | /// This might show the UAC prompt. 117 | /// 118 | public static readonly string TryUAC = @"Update could not be finished. Try alternative method? 119 | This might show the UAC prompt."; 120 | /// 121 | /// Open temporary folder containing the updated files? 122 | /// 123 | public static readonly string OpenTempFolder = @"Open temporary folder containing the updated files?"; 124 | /// 125 | /// Manually update translations 126 | /// 127 | public static readonly string TranslationDownload_Update = @"Manually update translations"; 128 | /// 129 | /// Always download translations for active language: {0} 130 | /// 131 | public static readonly string TranslationDownload_DownloadCurrent = @"Always download translations for active language: {0}"; 132 | /// 133 | /// Early Update Check - Update translations 134 | /// 135 | public static readonly string TranslationUpdateForm = @"Early Update Check - Update translations"; 136 | /// 137 | /// Please select plugins for which translations shall be updated 138 | /// 139 | public static readonly string SelectPluginsForTranslationUpdate = @"Please select plugins for which translations shall be updated"; 140 | /// 141 | /// A new version of ExternalPluginUpdates.xml is available. 142 | /// Download to update more 3rd party plugins? 143 | /// 144 | public static readonly string UpdateExternalInfo = @"A new version of ExternalPluginUpdates.xml is available. 145 | Download to update more 3rd party plugins?"; 146 | /// 147 | /// EarlyUpdateCheck can update selected 3rd party plugins as well. 148 | /// This is facilitated by a file called ExternalPluginUpdates.xml. 149 | /// Download this file now to allow updating those plugins? 150 | /// 151 | /// This question will not be asked again. 152 | /// If you decide to not use this feature now, you can download this file in EarlyUpdateCheck's options. 153 | /// 154 | public static readonly string UpdateExternalInfoInitialDownload = @"EarlyUpdateCheck can update selected 3rd party plugins as well. 155 | This is facilitated by a file called ExternalPluginUpdates.xml. 156 | Download this file now to allow updating those plugins? 157 | 158 | This question will not be asked again. 159 | If you decide to not use this feature now, you can download this file in EarlyUpdateCheck's options."; 160 | /// 161 | /// Download ExternalPluginUpdates.xml 162 | /// 163 | public static readonly string UpdateExternalInfoDownload = @"Download ExternalPluginUpdates.xml"; 164 | /// 165 | /// EarlyUpdateCheck downloaded the newest portable version of KeePass. 166 | /// 167 | /// The downloaded files will open in a new window. 168 | /// To perform the update, close KeePass and copy these files to your current KeePass location. 169 | /// 170 | public static readonly string KeePassUpdate_InstallZip = @"EarlyUpdateCheck downloaded the newest portable version of KeePass. 171 | 172 | The downloaded files will open in a new window. 173 | To perform the update, close KeePass and copy these files to your current KeePass location."; 174 | /// 175 | /// EarlyUpdateCheck downloaded the newest version of KeePass. 176 | /// To perform the update, you need to close KeePass. 177 | /// 178 | /// Click {0} to run the update now. 179 | /// Click {1} to open the folder containing the downloaded file instead. 180 | /// 181 | public static readonly string KeePassUpdate_InstallSetupOrMsi = @"EarlyUpdateCheck downloaded the newest version of KeePass. 182 | To perform the update, you need to close KeePass. 183 | 184 | Click {0} to run the update now. 185 | Click {1} to open the folder containing the downloaded file instead."; 186 | /// 187 | /// EarlyUpdateCheck can help in updating KeePass as well. 188 | /// Since KeePass can be installed in different ways, please confirm your installation type. 189 | /// 190 | /// Different installation types offered: 191 | /// - Setup: KeePass--Setup.exe is used to install KeePass 192 | /// - MSI: KeePass-.msi is used to install KeePass 193 | /// - Portable: KeePass-.zip is used to download and extract KeePass 194 | /// 195 | public static readonly string KeePassUpdate_RequestInstallType = @"EarlyUpdateCheck can help in updating KeePass as well. 196 | Since KeePass can be installed in different ways, please confirm your installation type. 197 | 198 | Different installation types offered: 199 | - Setup: KeePass--Setup.exe is used to install KeePass 200 | - MSI: KeePass-.msi is used to install KeePass 201 | - Portable: KeePass-.zip is used to download and extract KeePass"; 202 | /// 203 | /// EarlyUpdateCheck detected available updates of plugins and/or KeePass. 204 | /// 205 | /// As option '{0}' is active, the update form cannot be displayed now. 206 | /// It will be shown AFTER you close the '{1}' form. 207 | /// 208 | public static readonly string SecureDesktopMode = @"EarlyUpdateCheck detected available updates of plugins and/or KeePass. 209 | 210 | As option '{0}' is active, the update form cannot be displayed now. 211 | It will be shown AFTER you close the '{1}' form."; 212 | #endregion 213 | 214 | #region NO changes in this area 215 | private static StringDictionary m_translation = new StringDictionary(); 216 | 217 | public static void Init(Plugin plugin, string LanguageCodeIso6391) 218 | { 219 | List lDebugStrings = new List(); 220 | m_translation.Clear(); 221 | bool bError = true; 222 | LanguageCodeIso6391 = InitTranslation(plugin, lDebugStrings, LanguageCodeIso6391, out bError); 223 | if (bError && (LanguageCodeIso6391.Length > 2)) 224 | { 225 | LanguageCodeIso6391 = LanguageCodeIso6391.Substring(0, 2); 226 | lDebugStrings.Add("Trying fallback: " + LanguageCodeIso6391); 227 | LanguageCodeIso6391 = InitTranslation(plugin, lDebugStrings, LanguageCodeIso6391, out bError); 228 | } 229 | if (bError) 230 | { 231 | PluginDebug.AddError("Reading translation failed", 0, lDebugStrings.ToArray()); 232 | LanguageCodeIso6391 = "en"; 233 | } 234 | else 235 | { 236 | List lTranslatable = new List( 237 | typeof(PluginTranslate).GetFields(BindingFlags.Static | BindingFlags.Public) 238 | ).FindAll(x => x.IsInitOnly); 239 | lDebugStrings.Add("Parsing complete"); 240 | lDebugStrings.Add("Translated texts read: " + m_translation.Count.ToString()); 241 | lDebugStrings.Add("Translatable texts: " + lTranslatable.Count.ToString()); 242 | foreach (FieldInfo f in lTranslatable) 243 | { 244 | if (m_translation.ContainsKey(f.Name)) 245 | { 246 | lDebugStrings.Add("Key found: " + f.Name); 247 | f.SetValue(null, m_translation[f.Name]); 248 | } 249 | else 250 | lDebugStrings.Add("Key not found: " + f.Name); 251 | } 252 | PluginDebug.AddInfo("Reading translations finished", 0, lDebugStrings.ToArray()); 253 | } 254 | if (TranslationChanged != null) 255 | { 256 | TranslationChanged(null, new TranslationChangedEventArgs(LanguageIso6391, LanguageCodeIso6391)); 257 | } 258 | LanguageIso6391 = LanguageCodeIso6391; 259 | lDebugStrings.Clear(); 260 | } 261 | 262 | private static string InitTranslation(Plugin plugin, List lDebugStrings, string LanguageCodeIso6391, out bool bError) 263 | { 264 | if (string.IsNullOrEmpty(LanguageCodeIso6391)) 265 | { 266 | lDebugStrings.Add("No language identifier supplied, using 'en' as fallback"); 267 | LanguageCodeIso6391 = "en"; 268 | } 269 | string filename = GetFilename(plugin.GetType().Namespace, LanguageCodeIso6391); 270 | lDebugStrings.Add("Translation file: " + filename); 271 | 272 | if (!File.Exists(filename)) //If e. g. 'plugin.zh-tw.language.xml' does not exist, try 'plugin.zh.language.xml' 273 | { 274 | lDebugStrings.Add("File does not exist"); 275 | bError = true; 276 | return LanguageCodeIso6391; 277 | } 278 | else 279 | { 280 | string translation = string.Empty; 281 | try { translation = File.ReadAllText(filename); } 282 | catch (Exception ex) 283 | { 284 | lDebugStrings.Add("Error reading file: " + ex.Message); 285 | LanguageCodeIso6391 = "en"; 286 | bError = true; 287 | return LanguageCodeIso6391; 288 | } 289 | XmlSerializer xs = new XmlSerializer(m_translation.GetType()); 290 | lDebugStrings.Add("File read, parsing content"); 291 | try 292 | { 293 | m_translation = (StringDictionary)xs.Deserialize(new StringReader(translation)); 294 | } 295 | catch (Exception ex) 296 | { 297 | string sException = ex.Message; 298 | if (ex.InnerException != null) sException += "\n" + ex.InnerException.Message; 299 | lDebugStrings.Add("Error parsing file: " + sException); 300 | LanguageCodeIso6391 = "en"; 301 | MessageBox.Show("Error parsing translation file\n\n" + sException, PluginName, MessageBoxButtons.OK, MessageBoxIcon.Error); 302 | bError = true; 303 | return LanguageCodeIso6391; 304 | } 305 | bError = false; 306 | return LanguageCodeIso6391; 307 | } 308 | } 309 | 310 | private static string GetFilename(string plugin, string lang) 311 | { 312 | string filename = UrlUtil.GetFileDirectory(WinUtil.GetExecutable(), true, true); 313 | filename += KeePass.App.AppDefs.PluginsDir + UrlUtil.LocalDirSepChar + "Translations" + UrlUtil.LocalDirSepChar; 314 | filename += plugin + "." + lang + ".language.xml"; 315 | return filename; 316 | } 317 | #endregion 318 | } 319 | 320 | #region NO changes in this area 321 | [XmlRoot("Translation")] 322 | public class StringDictionary : Dictionary, IXmlSerializable 323 | { 324 | public System.Xml.Schema.XmlSchema GetSchema() 325 | { 326 | return null; 327 | } 328 | 329 | public void ReadXml(XmlReader reader) 330 | { 331 | bool wasEmpty = reader.IsEmptyElement; 332 | reader.Read(); 333 | if (wasEmpty) return; 334 | bool bFirst = true; 335 | while (reader.NodeType != XmlNodeType.EndElement) 336 | { 337 | if (bFirst) 338 | { 339 | bFirst = false; 340 | try 341 | { 342 | reader.ReadStartElement("TranslationVersion"); 343 | PluginTranslate.TranslationVersion = reader.ReadContentAsLong(); 344 | reader.ReadEndElement(); 345 | } 346 | catch { } 347 | } 348 | reader.ReadStartElement("item"); 349 | reader.ReadStartElement("key"); 350 | string key = reader.ReadContentAsString(); 351 | reader.ReadEndElement(); 352 | reader.ReadStartElement("value"); 353 | string value = reader.ReadContentAsString(); 354 | reader.ReadEndElement(); 355 | this.Add(key, value); 356 | reader.ReadEndElement(); 357 | reader.MoveToContent(); 358 | } 359 | reader.ReadEndElement(); 360 | } 361 | 362 | public void WriteXml(XmlWriter writer) 363 | { 364 | writer.WriteStartElement("TranslationVersion"); 365 | writer.WriteString(PluginTranslate.TranslationVersion.ToString()); 366 | writer.WriteEndElement(); 367 | foreach (string key in this.Keys) 368 | { 369 | writer.WriteStartElement("item"); 370 | writer.WriteStartElement("key"); 371 | writer.WriteString(key); 372 | writer.WriteEndElement(); 373 | writer.WriteStartElement("value"); 374 | writer.WriteString(this[key]); 375 | writer.WriteEndElement(); 376 | writer.WriteEndElement(); 377 | } 378 | } 379 | } 380 | #endregion 381 | } 382 | -------------------------------------------------------------------------------- /src/Utilities/Tools_Controls.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection; 3 | using System.Windows.Forms; 4 | 5 | namespace PluginTools 6 | { 7 | public static partial class Tools 8 | { 9 | public static object GetField(string field, object obj) 10 | { 11 | BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; 12 | return GetField(field, obj, bf); 13 | } 14 | 15 | public static object GetField(string field, object obj, BindingFlags bf) 16 | { 17 | if (obj == null) return null; 18 | FieldInfo fi = obj.GetType().GetField(field, bf); 19 | if (fi == null) return null; 20 | return fi.GetValue(obj); 21 | } 22 | 23 | public static Control GetControl(string control) 24 | { 25 | return GetControl(control, KeePass.Program.MainForm); 26 | } 27 | 28 | public static Control GetControl(string control, Control form) 29 | { 30 | if (form == null) return null; 31 | if (string.IsNullOrEmpty(control)) return null; 32 | Control[] cntrls = form.Controls.Find(control, true); 33 | if (cntrls.Length == 0) return null; 34 | return cntrls[0]; 35 | } 36 | 37 | public static ToolStripMenuItem FindToolStripMenuItem(ToolStripItemCollection tsic, string key, bool searchAllChildren) 38 | { 39 | if (tsic == null) return null; 40 | ToolStripItem[] tsi = FindToolStripMenuItems(tsic, key, searchAllChildren); 41 | if (tsi.Length > 0) return tsi[0] as ToolStripMenuItem; 42 | return null; 43 | } 44 | 45 | public static ToolStripItem[] FindToolStripMenuItems(ToolStripItemCollection tsic, string key, bool searchAllChildren) 46 | { 47 | if (tsic == null) return new ToolStripItem[] { }; 48 | ToolStripItem[] tsi = tsic.Find(key, searchAllChildren); 49 | if (!MonoWorkaroundRequired || !searchAllChildren) return tsi; 50 | 51 | //Mono does not support 'searchAllChildren' for ToolStripItemCollection 52 | //Iterate over all items and search for given item 53 | List lItems = new List(tsi); 54 | foreach (var item in tsic) 55 | { 56 | ToolStripMenuItem tsmi = item as ToolStripMenuItem; 57 | if (tsmi == null) continue; 58 | lItems.AddRange(FindToolStripMenuItems(tsmi.DropDownItems, key, searchAllChildren)); 59 | } 60 | return lItems.ToArray(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Utilities/Tools_Main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using KeePass.UI; 4 | 5 | namespace PluginTools 6 | { 7 | public static partial class Tools 8 | { 9 | public static Version KeePassVersion { get; private set; } 10 | public static string DefaultCaption = string.Empty; 11 | public static string PluginURL = string.Empty; 12 | public static string KeePassLanguageIso6391 { get; private set; } 13 | 14 | private static bool MonoWorkaroundRequired = KeePassLib.Native.NativeLib.IsUnix(); 15 | 16 | static Tools() 17 | { 18 | KeePass.UI.GlobalWindowManager.WindowAdded += OnWindowAdded; 19 | KeePass.UI.GlobalWindowManager.WindowRemoved += OnWindowRemoved; 20 | KeePassVersion = typeof(KeePass.Program).Assembly.GetName().Version; 21 | KeePassLanguageIso6391 = KeePass.Program.Translation.Properties.Iso6391Code; 22 | if (string.IsNullOrEmpty(KeePassLanguageIso6391)) KeePassLanguageIso6391 = "en"; 23 | m_sPluginClassname = typeof(Tools).Assembly.GetName().Name + "Ext"; 24 | } 25 | 26 | public static void OpenUrl(string sURL) 27 | { 28 | OpenUrl(sURL, null); 29 | } 30 | 31 | public static void OpenUrl(string sURL, KeePassLib.PwEntry pe) 32 | { 33 | //Use KeePass built-in logic instead of System.Diagnostics.Process.Start 34 | //For details see: https://sourceforge.net/p/keepass/discussion/329221/thread/f399b6d74b/#4801 35 | KeePass.Util.WinUtil.OpenUrl(sURL, pe, true); 36 | } 37 | 38 | #region MessageBox shortcuts 39 | public static DialogResult ShowError(string msg) 40 | { 41 | return ShowError(msg, DefaultCaption); 42 | } 43 | 44 | public static DialogResult ShowInfo(string msg) 45 | { 46 | return ShowInfo(msg, DefaultCaption); 47 | } 48 | 49 | public static DialogResult AskYesNo(string msg) 50 | { 51 | return AskYesNo(msg, DefaultCaption); 52 | } 53 | 54 | public static DialogResult ShowError(string msg, string caption) 55 | { 56 | PluginDebug.AddError("Show error", 6, caption, msg); 57 | return MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); 58 | } 59 | 60 | public static DialogResult ShowInfo(string msg, string caption) 61 | { 62 | PluginDebug.AddInfo("Show info", 6, caption, msg); 63 | return MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Information); 64 | } 65 | 66 | public static DialogResult AskYesNo(string msg, string caption) 67 | { 68 | DialogResult result = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question); 69 | PluginDebug.AddInfo("Ask question", 6, caption, msg, "Result: " + result.ToString()); 70 | return result; 71 | } 72 | #endregion 73 | 74 | #region GlobalWindowManager 75 | public static void GlobalWindowManager(Form form) 76 | { 77 | if ((form == null) || (form.IsDisposed)) return; 78 | form.Load += FormLoaded; 79 | form.FormClosed += FormClosed; 80 | } 81 | 82 | private static void FormLoaded(object sender, EventArgs e) 83 | { 84 | KeePass.UI.GlobalWindowManager.AddWindow(sender as Form, sender as IGwmWindow); 85 | } 86 | 87 | private static void FormClosed(object sender, FormClosedEventArgs e) 88 | { 89 | KeePass.UI.GlobalWindowManager.RemoveWindow(sender as Form); 90 | } 91 | #endregion 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Utilities/Tools_Options.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Reflection; 5 | using System.Windows.Forms; 6 | using KeePass.Forms; 7 | 8 | namespace PluginTools 9 | { 10 | public static partial class Tools 11 | { 12 | public static object GetPluginInstance(string PluginName) 13 | { 14 | string comp = PluginName + "." + PluginName + "Ext"; 15 | BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; 16 | try 17 | { 18 | var PluginManager = GetField("m_pluginManager", KeePass.Program.MainForm); 19 | var PluginList = GetField("m_vPlugins", PluginManager); 20 | if (PluginList == null) PluginList = GetField("m_lPlugins", PluginManager); 21 | MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); 22 | IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); 23 | while (PluginIterator.MoveNext()) 24 | { 25 | object result = GetField("m_pluginInterface", PluginIterator.Current); 26 | if (comp == result.GetType().ToString()) return result; 27 | } 28 | } 29 | 30 | catch (Exception) { } 31 | return null; 32 | } 33 | 34 | public static Dictionary GetLoadedPluginsName() 35 | { 36 | Dictionary dPlugins = new Dictionary(); 37 | BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; 38 | try 39 | { 40 | var PluginManager = GetField("m_pluginManager", KeePass.Program.MainForm); 41 | var PluginList = GetField("m_vPlugins", PluginManager); 42 | if (PluginList == null) PluginList = GetField("m_lPlugins", PluginManager); 43 | MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); 44 | IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); 45 | while (PluginIterator.MoveNext()) 46 | { 47 | object result = GetField("m_pluginInterface", PluginIterator.Current); 48 | var x = result.GetType().Assembly; 49 | object[] v = x.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), true); 50 | Version ver = null; 51 | if ((v != null) && (v.Length > 0)) 52 | ver = new Version(((AssemblyFileVersionAttribute)v[0]).Version); 53 | else 54 | ver = result.GetType().Assembly.GetName().Version; 55 | if (ver.Build < 0) ver = new Version(ver.Major, ver.Minor, 0, 0); 56 | if (ver.Revision < 0) ver = new Version(ver.Major, ver.Minor, ver.Build, 0); 57 | dPlugins[result.GetType().FullName] = ver; 58 | } 59 | } 60 | catch (Exception) { } 61 | return dPlugins; 62 | } 63 | 64 | public static event EventHandler OptionsFormShown; 65 | public static event EventHandler OptionsFormClosed; 66 | 67 | private static bool OptionsEnabled = (KeePass.Program.Config.UI.UIFlags & (ulong)KeePass.App.Configuration.AceUIFlags.DisableOptions) != (ulong)KeePass.App.Configuration.AceUIFlags.DisableOptions; 68 | private static bool m_ActivatePluginTab = false; 69 | private static string m_sPluginClassname = string.Empty; 70 | private static OptionsForm m_of = null; 71 | private const string c_tabRookiestyle = "m_tabRookiestyle"; 72 | private const string c_tabControlRookiestyle = "m_tabControlRookiestyle"; 73 | private static string m_TabPageName = string.Empty; 74 | private static bool m_OptionsShown = false; 75 | private static bool m_PluginContainerShown = false; 76 | 77 | public static void AddPluginToOptionsForm(KeePass.Plugins.Plugin p, UserControl uc) 78 | { 79 | m_OptionsShown = m_PluginContainerShown = false; 80 | TabPage tPlugin = new TabPage(DefaultCaption); 81 | tPlugin.CreateControl(); 82 | tPlugin.Name = m_TabPageName = c_tabRookiestyle + p.GetType().Name; 83 | uc.Dock = DockStyle.Fill; 84 | uc.Padding = new Padding(15, 10, 15, 10); 85 | tPlugin.Controls.Add(uc); 86 | PluginDebug.AddInfo("Adding/Searching " + c_tabControlRookiestyle); 87 | TabControl tcPlugins = AddPluginTabContainer(); 88 | int i = 0; 89 | bool insert = false; 90 | for (int j = 0; j < tcPlugins.TabPages.Count; j++) 91 | { 92 | if (string.Compare(tPlugin.Text, tcPlugins.TabPages[j].Text, StringComparison.CurrentCultureIgnoreCase) < 0) 93 | { 94 | i = j; 95 | insert = true; 96 | break; 97 | } 98 | } 99 | if (!insert) 100 | { 101 | i = tcPlugins.TabPages.Count; 102 | PluginDebug.AddInfo(p.GetType().Name + " tab index : " + i.ToString() + " - insert!", 0); 103 | } 104 | else PluginDebug.AddInfo(p.GetType().Name + " tab index : " + i.ToString(), 0); 105 | tcPlugins.TabPages.Insert(i, tPlugin); 106 | AddPluginToOverview(tPlugin.Name.Replace(c_tabRookiestyle, string.Empty), tcPlugins); 107 | if (p.SmallIcon != null) 108 | { 109 | tcPlugins.ImageList.Images.Add(tPlugin.Name, p.SmallIcon); 110 | tPlugin.ImageKey = tPlugin.Name; 111 | } 112 | TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; 113 | if (!string.IsNullOrEmpty(PluginURL)) AddPluginLink(uc); 114 | } 115 | 116 | public static void AddPluginToOverview(string sPluginName) 117 | { 118 | AddPluginToOverview(sPluginName, null); 119 | } 120 | 121 | private static void AddPluginToOverview(string sPluginName, TabControl tcPlugins) 122 | { 123 | if (tcPlugins == null) tcPlugins = AddPluginTabContainer(); 124 | TabPage tpOverview = null; 125 | ListView lv = null; 126 | string sTabName = c_tabRookiestyle + "_PluginOverview"; 127 | string sListViewName = c_tabRookiestyle + "_PluginOverviewListView"; 128 | if (tcPlugins.TabPages.ContainsKey(sTabName)) 129 | { 130 | tpOverview = tcPlugins.TabPages[sTabName]; 131 | lv = (ListView)tpOverview.Controls.Find(sListViewName, true)[0]; 132 | PluginDebug.AddInfo("Found " + sTabName, 0, "Listview: " + (lv == null ? "null" : lv.Items.Count.ToString() + " /" + lv.Name.ToString())); 133 | } 134 | else 135 | { 136 | tpOverview = new TabPage("Overview"); 137 | tpOverview.CreateControl(); 138 | tpOverview.Name = sTabName; 139 | UserControl uc = new UserControl(); 140 | uc.Dock = DockStyle.Fill; 141 | uc.Padding = new Padding(15, 10, 15, 10); 142 | tpOverview.Controls.Add(uc); 143 | lv = new ListView(); 144 | lv.Name = sListViewName; 145 | lv.Dock = DockStyle.Fill; 146 | lv.View = View.Details; 147 | lv.Columns.Add("Plugin"); 148 | lv.Columns.Add("Version"); 149 | lv.CheckBoxes = true; 150 | tpOverview.Layout += TpOverview_Layout; 151 | Label lInfo = new Label(); 152 | lInfo.AutoSize = true; 153 | lInfo.Text = "Use the checkbox to activate/deactivate debug mode"; 154 | lInfo.Dock = DockStyle.Bottom; 155 | uc.Controls.Add(lv); 156 | uc.Controls.Add(lInfo); 157 | } 158 | lv.ItemCheck += Lv_ItemCheck; 159 | lv.Sorting = SortOrder.Ascending; 160 | lv.FullRowSelect = true; 161 | ListViewItem lvi = new ListViewItem(); 162 | lvi.Name = sPluginName; 163 | lvi.Checked = PluginDebug.DebugMode; 164 | lvi.Text = DefaultCaption; 165 | Version v = new Version(0, 0); 166 | GetLoadedPluginsName().TryGetValue(sPluginName.Replace("Ext", string.Empty) + "." + sPluginName, out v); 167 | if (v == null) PluginDebug.AddError("Could not get loaded plugins' data", 0); 168 | string ver = (v == null) ? "???" : v.ToString(); 169 | if (ver.EndsWith(".0")) ver = ver.Substring(0, ver.Length - 2); 170 | else ver += " (Dev)"; 171 | lvi.SubItems.Add(ver); 172 | lv.Items.Add(lvi); 173 | tcPlugins.TabPages.Remove(tpOverview); 174 | tcPlugins.TabPages.Add(tpOverview); 175 | PluginDebug.AddInfo("Added " + sTabName, 0, "Listview: " + (lv == null ? "null" : lv.Items.Count.ToString() + " /" + lv.Name.ToString())); 176 | } 177 | 178 | private static void TpOverview_Layout(object sender, LayoutEventArgs e) 179 | { 180 | string sListViewName = c_tabRookiestyle + "_PluginOverviewListView"; 181 | ListView lv = (sender as TabPage).Controls.Find(sListViewName, true)[0] as ListView; 182 | lv.BeginUpdate(); 183 | lv.Columns[1].DisplayIndex = 0; 184 | lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); 185 | int w = lv.Columns[1].Width; 186 | lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); 187 | lv.Columns[1].Width = Math.Max(w, lv.Columns[1].Width); 188 | lv.Columns[0].Width = lv.ClientSize.Width - lv.Columns[1].Width; 189 | if (lv.Columns[0].Width < 150) 190 | { 191 | lv.Columns[1].Width = 100; 192 | lv.Columns[0].Width = lv.ClientSize.Width - lv.Columns[1].Width; 193 | } 194 | lv.Columns[1].DisplayIndex = 1; 195 | lv.EndUpdate(); 196 | } 197 | 198 | private static void Lv_ItemCheck(object sender, ItemCheckEventArgs e) 199 | { 200 | ListViewItem lvi = (sender as ListView).Items[e.Index]; 201 | if (lvi == null) return; 202 | if (lvi.Text != DefaultCaption) return; 203 | PluginDebug.DebugMode = e.NewValue == CheckState.Checked; 204 | } 205 | 206 | private static void OnPluginTabsSelected(object sender, TabControlEventArgs e) 207 | { 208 | m_OptionsShown |= (e.TabPage.Name == m_TabPageName); 209 | m_PluginContainerShown |= (m_OptionsShown || (e.TabPage.Name == c_tabRookiestyle)); 210 | } 211 | 212 | public static UserControl GetPluginFromOptions(KeePass.Plugins.Plugin p, out bool PluginOptionsShown) 213 | { 214 | PluginOptionsShown = m_OptionsShown && m_PluginContainerShown; 215 | TabPage tPlugin = Tools.GetControl(c_tabRookiestyle + p.GetType().Name, m_of) as TabPage; 216 | if (tPlugin == null) return null; 217 | return tPlugin.Controls[0] as UserControl; 218 | } 219 | 220 | public static void ShowOptions() 221 | { 222 | m_ActivatePluginTab = true; 223 | if (OptionsEnabled) 224 | KeePass.Program.MainForm.ToolsMenu.DropDownItems["m_menuToolsOptions"].PerformClick(); 225 | else 226 | { 227 | m_of = new OptionsForm(); 228 | m_of.InitEx(KeePass.Program.MainForm.ClientIcons); 229 | m_of.ShowDialog(); 230 | } 231 | } 232 | 233 | private static void AddPluginLink(UserControl uc) 234 | { 235 | LinkLabel llUrl = new LinkLabel(); 236 | llUrl.Links.Add(0, PluginURL.Length, PluginURL); 237 | llUrl.Text = PluginURL; 238 | uc.Controls.Add(llUrl); 239 | llUrl.Dock = DockStyle.Bottom; 240 | llUrl.AutoSize = true; 241 | llUrl.LinkClicked += new LinkLabelLinkClickedEventHandler(PluginURLClicked); 242 | } 243 | 244 | private static void PluginURLClicked(object sender, LinkLabelLinkClickedEventArgs e) 245 | { 246 | string target = e.Link.LinkData as string; 247 | OpenUrl(target); 248 | } 249 | 250 | private static void OnOptionsFormShown(object sender, EventArgs e) 251 | { 252 | m_of.Shown -= OnOptionsFormShown; 253 | TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; 254 | if (!tcMain.TabPages.ContainsKey(c_tabRookiestyle)) return; 255 | TabPage tPlugins = tcMain.TabPages[c_tabRookiestyle]; 256 | TabControl tcPlugins = Tools.GetControl(c_tabControlRookiestyle, tPlugins) as TabControl; 257 | if (m_ActivatePluginTab) 258 | { 259 | tcMain.SelectedIndex = tcMain.TabPages.IndexOfKey(c_tabRookiestyle); 260 | KeePass.Program.Config.Defaults.OptionsTabIndex = (uint)tcMain.SelectedIndex; 261 | tcPlugins.SelectedIndex = tcPlugins.TabPages.IndexOfKey(c_tabRookiestyle + m_sPluginClassname); 262 | } 263 | m_ActivatePluginTab = false; 264 | tcMain.Selected += OnPluginTabsSelected; 265 | tcPlugins.Selected += OnPluginTabsSelected; 266 | tcMain.ImageList.Images.Add(c_tabRookiestyle + "Icon", (Image)KeePass.Program.Resources.GetObject("B16x16_BlockDevice")); 267 | tPlugins.ImageKey = c_tabRookiestyle + "Icon"; 268 | m_PluginContainerShown |= tcMain.SelectedTab == tPlugins; 269 | m_OptionsShown |= (tcPlugins.SelectedTab.Name == m_TabPageName); 270 | CheckKeeTheme(tPlugins); 271 | } 272 | 273 | private static void CheckKeeTheme(Control c) 274 | { 275 | Control check = GetControl("Rookiestyle_KeeTheme_Check", m_of); 276 | if (check != null) return; 277 | PluginDebug.AddInfo("Checking for KeeTheme"); 278 | check = new Control(); 279 | check.Name = "Rookiestyle_KeeTheme_Check"; 280 | check.Visible = false; 281 | m_of.Controls.Add(check); 282 | KeePass.Plugins.Plugin p = (KeePass.Plugins.Plugin)GetPluginInstance("KeeTheme"); 283 | if (p == null) return; 284 | var t = GetField("_theme", p); 285 | if (t == null) return; 286 | bool bKeeThemeEnabled = (bool)t.GetType().GetProperty("Enabled").GetValue(t, null); 287 | if (!bKeeThemeEnabled) return; 288 | var v = GetField("_controlVisitor", p); 289 | if (v == null) return; 290 | MethodInfo miVisit = v.GetType().GetMethod("Visit", new Type[] { typeof(Control) }); 291 | if (miVisit == null) return; 292 | miVisit.Invoke(v, new object[] { c }); 293 | } 294 | 295 | private static void OnWindowAdded(object sender, KeePass.UI.GwmWindowEventArgs e) 296 | { 297 | if (OptionsFormShown == null) return; 298 | if (e.Form is OptionsForm) 299 | { 300 | m_of = e.Form as OptionsForm; 301 | m_of.Shown += OnOptionsFormShown; 302 | OptionsFormsEventArgs o = new OptionsFormsEventArgs(m_of); 303 | OptionsFormShown(sender, o); 304 | } 305 | } 306 | 307 | private static void OnWindowRemoved(object sender, KeePass.UI.GwmWindowEventArgs e) 308 | { 309 | if (OptionsFormClosed == null) return; 310 | if (e.Form is OptionsForm) 311 | { 312 | OptionsFormsEventArgs o = new OptionsFormsEventArgs(m_of); 313 | OptionsFormClosed(sender, o); 314 | } 315 | } 316 | 317 | private static TabControl AddPluginTabContainer() 318 | { 319 | if (m_of == null) 320 | { 321 | PluginDebug.AddError("Could not identify KeePass options form", 0); 322 | return null; 323 | } 324 | TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; 325 | if (tcMain == null) 326 | { 327 | PluginDebug.AddError("Could not locate m_tabMain", 0); 328 | return null; 329 | } 330 | TabPage tPlugins = null; 331 | TabControl tcPlugins = null; 332 | if (tcMain.TabPages.ContainsKey(c_tabRookiestyle)) 333 | { 334 | tPlugins = tcMain.TabPages[c_tabRookiestyle]; 335 | tcPlugins = (TabControl)tPlugins.Controls[c_tabControlRookiestyle]; 336 | if (tcPlugins == null) 337 | { 338 | PluginDebug.AddError("Could not locate " + c_tabControlRookiestyle, 0); 339 | return null; 340 | } 341 | tcPlugins.Multiline = false; //Older version of PluginTools might still be used by other plugins 342 | PluginDebug.AddInfo("Found " + c_tabControlRookiestyle, 0); 343 | return tcPlugins; 344 | } 345 | tPlugins = new TabPage(KeePass.Resources.KPRes.Plugin + " " + m_of.Text); 346 | tPlugins.Name = c_tabRookiestyle; 347 | tPlugins.CreateControl(); 348 | if (!OptionsEnabled) 349 | { 350 | while (tcMain.TabCount > 0) 351 | tcMain.TabPages.RemoveAt(0); 352 | PluginDebug.AddInfo("Removed tab pages from KeePass options form", 0); 353 | } 354 | tcMain.TabPages.Add(tPlugins); 355 | tcPlugins = new TabControl(); 356 | tcPlugins.Name = c_tabControlRookiestyle; 357 | tcPlugins.Dock = DockStyle.Fill; 358 | tcPlugins.Multiline = false; 359 | tcPlugins.CreateControl(); 360 | if (tcPlugins.ImageList == null) 361 | tcPlugins.ImageList = new ImageList(); 362 | tPlugins.Controls.Add(tcPlugins); 363 | PluginDebug.AddInfo("Added " + c_tabControlRookiestyle, 0); 364 | return tcPlugins; 365 | } 366 | 367 | public class OptionsFormsEventArgs : EventArgs 368 | { 369 | public Form form; 370 | 371 | public OptionsFormsEventArgs(Form form) 372 | { 373 | this.form = form; 374 | } 375 | } 376 | } 377 | } 378 | -------------------------------------------------------------------------------- /src/Utilities/Util.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Threading; 4 | using System.Windows.Forms; 5 | using PluginTools; 6 | 7 | namespace EarlyUpdateCheck 8 | { 9 | internal enum UpdateCheckType 10 | { 11 | NotRequired = 0, 12 | Required = 1, 13 | OnlyTranslations = 2, 14 | } 15 | 16 | internal enum UpdateCheckStatus 17 | { 18 | NotChecked, 19 | Checking, 20 | Checked, 21 | Error 22 | }; 23 | 24 | internal static class PluginConfig 25 | { 26 | private static KeePass.App.Configuration.AceCustomConfig Config = KeePass.Program.Config.CustomConfig; 27 | internal static bool Active = true; 28 | internal static bool CheckSync = true; 29 | internal static bool OneClickUpdate = true; 30 | internal static bool DownloadActiveLanguage = true; 31 | 32 | //Check for initial download of ExternPluginUpdates.xml 33 | // 34 | internal static bool ExternalUpdateFileAskedForInitialDownload 35 | { 36 | get 37 | { 38 | return Config.GetBool("EarlyUpdateCheck.ExternalUpdateFileAskedForInitialDownload", false); 39 | } 40 | set 41 | { 42 | Config.SetBool("EarlyUpdateCheck.ExternalUpdateFileAskedForInitialDownload", value); 43 | } 44 | } 45 | internal static int RestoreMutexThreshold 46 | { 47 | get 48 | { 49 | int t = (int)Config.GetLong("EarlyUpdateCheck.RestoreMutexThreshold", 2000); 50 | Config.SetLong("EarlyUpdateCheck.RestoreMutexThreshold", t); 51 | return t; 52 | } 53 | } 54 | 55 | internal static bool KeePassUpdateActive 56 | { 57 | get 58 | { 59 | return Config.GetBool("EarlyUpdateCheck.KeePassUpdateActive", true); 60 | } 61 | set 62 | { 63 | Config.SetBool("EarlyUpdateCheck.KeePassUpdateActive", value); 64 | } 65 | } 66 | 67 | public static bool KeePassInstallTypeConfigured 68 | { 69 | get { return Config.GetString("EarlyUpdateCheck.KeePassInstallType", "Unknown") != "Unknown"; } 70 | } 71 | 72 | public static KeePass_Update.KeePassInstallType KeePassInstallType 73 | { 74 | get 75 | { 76 | string sType = Config.GetString("EarlyUpdateCheck.KeePassInstallType", "Unknown"); 77 | KeePass_Update.KeePassInstallType kpit = KeePass_Update.KeePassInstallType.Portable; 78 | try { kpit = (KeePass_Update.KeePassInstallType)Enum.Parse(kpit.GetType(), sType); } 79 | catch { kpit = VerifyKeePassInstallType(); } 80 | return kpit; 81 | } 82 | set 83 | { 84 | Config.SetString("EarlyUpdateCheck.KeePassInstallType", value.ToString()); 85 | } 86 | } 87 | 88 | public static KeePass_Update.KeePassInstallType VerifyKeePassInstallType() 89 | { 90 | //By default, KeePass-Setup.exe installs to Program Files\KeePass Password Safe 2 / Program Files (x86)\KeePass Password Safe 2 91 | //By default, KeePass.msi installs to Program Files\KeePass2x / Program Files (x86)\KeePass2x 92 | 93 | var lSpecialFolders = new System.Collections.Generic.List(); 94 | string sFolder = Environment.GetEnvironmentVariable("ProgramFiles(x86)"); 95 | if (!string.IsNullOrEmpty(sFolder)) lSpecialFolders.Add(sFolder); 96 | 97 | try 98 | { 99 | //Environment.SpecialFolder.ProgramFilesX86 100 | sFolder = Environment.GetFolderPath((Environment.SpecialFolder)42); 101 | if (!string.IsNullOrEmpty(sFolder)) lSpecialFolders.Add(sFolder); 102 | } 103 | catch { } 104 | 105 | sFolder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); 106 | if (!string.IsNullOrEmpty(sFolder)) lSpecialFolders.Add(sFolder); 107 | 108 | sFolder = KeePassLib.Utility.UrlUtil.GetFileDirectory(KeePass.Util.WinUtil.GetExecutable(), true, true); 109 | 110 | var lMsg = new System.Collections.Generic.List(); 111 | lMsg.AddRange(lSpecialFolders); 112 | lMsg.Add("KeePass path: " + sFolder); 113 | sFolder = sFolder.ToLowerInvariant(); 114 | 115 | var result = KeePass_Update.KeePassInstallType.Portable; 116 | if (string.IsNullOrEmpty(lSpecialFolders.Find(x => sFolder.StartsWith(x.ToLowerInvariant())))) result = KeePass_Update.KeePassInstallType.Portable; 117 | else if (sFolder.Contains("keepass password safe 2")) result = KeePass_Update.KeePassInstallType.Setup; 118 | else if (sFolder.Contains("keepass2x")) result = KeePass_Update.KeePassInstallType.MSI; 119 | 120 | lMsg.Add(result.ToString()); 121 | 122 | PluginDebug.AddInfo("Verify KeePass install type", 0, lMsg.ToArray()); 123 | 124 | return result; 125 | } 126 | 127 | internal static void Read() 128 | { 129 | PluginConfig.Active = Config.GetBool("EarlyUpdateCheck.Active", PluginConfig.Active); 130 | PluginConfig.CheckSync = Config.GetBool("EarlyUpdateCheck.CheckSync", PluginConfig.CheckSync); 131 | PluginConfig.OneClickUpdate = Config.GetBool("EarlyUpdateCheck.OneClickUpdate", PluginConfig.OneClickUpdate); 132 | PluginConfig.DownloadActiveLanguage = Config.GetBool("EarlyUpdateCheck.DownloadActiveLanguage", PluginConfig.DownloadActiveLanguage); 133 | } 134 | 135 | internal static void Write() 136 | { 137 | Config.SetBool("EarlyUpdateCheck.Active", PluginConfig.Active); 138 | Config.SetBool("EarlyUpdateCheck.CheckSync", PluginConfig.CheckSync); 139 | Config.SetBool("EarlyUpdateCheck.OneClickUpdate", PluginConfig.OneClickUpdate); 140 | Config.SetBool("EarlyUpdateCheck.DownloadActiveLanguage", PluginConfig.DownloadActiveLanguage); 141 | } 142 | } 143 | 144 | internal static class FileCopier 145 | { 146 | [DllImport("shell32.dll", CharSet = CharSet.Unicode)] 147 | private static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp); 148 | 149 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 150 | private struct SHFILEOPSTRUCT 151 | { 152 | internal IntPtr hwnd; 153 | internal FILE_OP_TYPE wFunc; 154 | [MarshalAs(UnmanagedType.LPWStr)] 155 | internal string pFrom; 156 | [MarshalAs(UnmanagedType.LPWStr)] 157 | internal string pTo; 158 | internal FILE_OP_FLAGS fFlags; 159 | [MarshalAs(UnmanagedType.Bool)] 160 | internal bool fAnyOperationsAborted; 161 | internal IntPtr hNameMappings; 162 | [MarshalAs(UnmanagedType.LPWStr)] 163 | internal string lpszProgressTitle; 164 | } 165 | 166 | private enum FILE_OP_TYPE : uint 167 | { 168 | FO_MOVE = 0x0001, 169 | FO_COPY = 0x0002, 170 | FO_DELETE = 0x0003, 171 | FO_RENAME = 0x0004, 172 | } 173 | 174 | [Flags] 175 | private enum FILE_OP_FLAGS : ushort 176 | { 177 | FOF_MULTIDESTFILES = 0x0001, 178 | FOF_CONFIRMMOUSE = 0x0002, 179 | FOF_SILENT = 0x0004, 180 | FOF_RENAMEONCOLLISION = 0x0008, 181 | FOF_NOCONFIRMATION = 0x0010, 182 | FOF_WANTMAPPINGHANDLE = 0x0020, 183 | FOF_ALLOWUNDO = 0x0040, 184 | FOF_FILESONLY = 0x0080, 185 | FOF_SIMPLEPROGRESS = 0x0100, 186 | FOF_NOCONFIRMMKDIR = 0x0200, 187 | FOF_NOERRORUI = 0x0400, 188 | FOF_NOCOPYSECURITYATTRIBS = 0x0800, 189 | FOF_NORECURSION = 0x1000, 190 | FOF_NO_CONNECTED_ELEMENTS = 0x2000, 191 | FOF_WANTNUKEWARNING = 0x4000, 192 | FOF_NORECURSEREPARSE = 0x8000, 193 | } 194 | 195 | internal static int MoveFilesToTemp(params string[] files) 196 | { 197 | // 0 = success 198 | // -1 = aborted by user 199 | // other value = error 200 | 201 | string from = string.Empty; 202 | foreach (string file in files) 203 | from += file + "\0"; 204 | from += "\0"; 205 | 206 | string sTemp = PluginUpdateHandler.GetTempFolder() + "\0\0"; 207 | 208 | SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT(); 209 | lpFileOp.hwnd = IntPtr.Zero; 210 | lpFileOp.wFunc = FILE_OP_TYPE.FO_MOVE; 211 | lpFileOp.pFrom = from; 212 | lpFileOp.pTo = sTemp; 213 | lpFileOp.fFlags = FILE_OP_FLAGS.FOF_NOCONFIRMMKDIR | FILE_OP_FLAGS.FOF_NOCONFIRMATION | FILE_OP_FLAGS.FOF_ALLOWUNDO; 214 | lpFileOp.fAnyOperationsAborted = false; 215 | lpFileOp.hNameMappings = IntPtr.Zero; 216 | lpFileOp.lpszProgressTitle = string.Empty; 217 | 218 | int result = SHFileOperation(ref lpFileOp); 219 | if (result == 0 && lpFileOp.fAnyOperationsAborted) result = -1; 220 | PluginDebug.AddInfo("Move in UAC mode: " + result.ToString()); 221 | return result; 222 | } 223 | 224 | internal static int DeleteFiles(params string[] files) 225 | { 226 | // 0 = success 227 | // -1 = aborted by user 228 | // other value = error 229 | 230 | string from = string.Empty; 231 | foreach (string file in files) 232 | from += file + "\0"; 233 | from += "\0"; 234 | 235 | SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT(); 236 | lpFileOp.hwnd = IntPtr.Zero; 237 | lpFileOp.wFunc = FILE_OP_TYPE.FO_DELETE; 238 | lpFileOp.pFrom = from; 239 | lpFileOp.pTo = "\0\0"; 240 | lpFileOp.fFlags = FILE_OP_FLAGS.FOF_NOCONFIRMATION | FILE_OP_FLAGS.FOF_ALLOWUNDO; 241 | lpFileOp.fAnyOperationsAborted = false; 242 | lpFileOp.hNameMappings = IntPtr.Zero; 243 | lpFileOp.lpszProgressTitle = string.Empty; 244 | 245 | int result = SHFileOperation(ref lpFileOp); 246 | if (result == 0 && lpFileOp.fAnyOperationsAborted) result = -1; 247 | PluginDebug.AddInfo("Delete in UAC mode: " + result.ToString()); 248 | return result; 249 | } 250 | 251 | internal static bool CopyFiles(string from, string to) 252 | { 253 | bool success = false; 254 | 255 | from += "*\0\0"; 256 | to += "\0\0"; 257 | 258 | SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT(); 259 | lpFileOp.hwnd = IntPtr.Zero; 260 | lpFileOp.wFunc = FILE_OP_TYPE.FO_COPY; 261 | lpFileOp.pFrom = from; 262 | lpFileOp.pTo = to; 263 | lpFileOp.fFlags = FILE_OP_FLAGS.FOF_NOCONFIRMATION; 264 | lpFileOp.fAnyOperationsAborted = false; 265 | lpFileOp.hNameMappings = IntPtr.Zero; 266 | lpFileOp.lpszProgressTitle = string.Empty; 267 | 268 | int result = SHFileOperation(ref lpFileOp); 269 | if (result == 0) 270 | success = !lpFileOp.fAnyOperationsAborted; 271 | PluginDebug.AddInfo("Copy in UAC mode: " + success.ToString()); 272 | return success; 273 | } 274 | } 275 | 276 | internal static class NativeMethods 277 | { 278 | [DllImport("kernel32")] 279 | internal static extern uint GetCurrentThreadId(); 280 | 281 | internal delegate bool EnumWindowsProcedure(IntPtr windowHandle, IntPtr param); 282 | [DllImport("user32")] 283 | internal static extern bool EnumChildWindows(IntPtr windowHandle, EnumWindowsProcedure enumProc, IntPtr param); 284 | 285 | [DllImport("user32")] 286 | internal static extern bool EnumThreadWindows(uint threadId, EnumWindowsProcedure enumProc, IntPtr param); 287 | 288 | [DllImport("user32", EntryPoint = "GetClassNameW", SetLastError = true, CharSet = CharSet.Unicode)] 289 | internal static extern int GetClassName(IntPtr windowHandle, System.Text.StringBuilder buffer, int bufferSize); 290 | 291 | [DllImport("user32", EntryPoint = "GetDlgCtrlID")] 292 | internal static extern int GetDialogControlId(IntPtr windowHandle); 293 | 294 | [DllImport("user32")] 295 | internal static extern uint SendMessage(IntPtr param, uint message, uint wParam, uint lParam); 296 | 297 | //Credits go to Falahati: https://github.com/falahati/UACHelper - file WinForm.cs 298 | internal static DialogResult ShieldifyNativeDialog(DialogResult button, KeePassLib.Delegates.GFunc dialogShowCode) 299 | { 300 | var callingThreadId = NativeMethods.GetCurrentThreadId(); 301 | var thread = new Thread(() => 302 | { 303 | try 304 | { 305 | var found = false; 306 | while (!found) 307 | { 308 | Thread.Sleep(100); 309 | NativeMethods.EnumThreadWindows(callingThreadId, (wnd, param) => 310 | { 311 | var buffer = new System.Text.StringBuilder(256); 312 | NativeMethods.GetClassName(wnd, buffer, buffer.Capacity); 313 | if (buffer.ToString() == @"#32770") 314 | { 315 | ShieldifyNativeDialog(button, wnd); 316 | found = true; 317 | return false; 318 | } 319 | return true; 320 | }, IntPtr.Zero); 321 | } 322 | } 323 | catch { } 324 | }); 325 | thread.IsBackground = true; 326 | thread.Start(); 327 | var result = dialogShowCode(); 328 | thread.Abort(); 329 | return result; 330 | } 331 | 332 | internal static bool ShieldifyNativeDialog(DialogResult button, IntPtr windowHandle) 333 | { 334 | int numberOfItems = 0; 335 | bool notFound = NativeMethods.EnumChildWindows(windowHandle, (wnd, param) => 336 | { 337 | var buffer = new System.Text.StringBuilder(256); 338 | NativeMethods.GetClassName(wnd, buffer, buffer.Capacity); 339 | numberOfItems++; 340 | if (buffer.ToString().ToLower().Contains(@"button")) 341 | { 342 | if (NativeMethods.GetDialogControlId(wnd) == (int)button) 343 | { 344 | NativeMethods.SendMessage(wnd, 0x160C, 0, 0xFFFFFFFF); 345 | return false; 346 | } 347 | } 348 | else 349 | { 350 | if (ShieldifyNativeDialog(button, wnd)) 351 | { 352 | return false; 353 | } 354 | } 355 | return true; 356 | }, IntPtr.Zero); 357 | 358 | return !notFound && numberOfItems > 0; 359 | } 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /translationcopy.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd %~dp0 3 | 4 | if "%1" == "Debug" ( 5 | xcopy /y /c /i Translations\*.xml "..\_KeePass_Debug\Plugins\Translations" /EXCLUDE:..\translationsnocopy.txt 6 | ) 7 | if "%1" == "ReleasePlgx" ( 8 | xcopy /y /c /i Translations\*.xml "..\_KeePass_Release\Plugins\Translations" /EXCLUDE:..\translationsnocopy.txt 9 | xcopy /y /c /i Translations\*.xml "..\_Releases\Translations" /EXCLUDE:..\translationsnocopy.txt 10 | ) -------------------------------------------------------------------------------- /version.info: -------------------------------------------------------------------------------- 1 | : 2 | Early update check:4.2.4 3 | Early update check!de:9 4 | Early update check!ru:2 5 | Early update check!fr:1 6 | Early update check!pt:3 7 | Early update check!it:1 8 | Early update check!zh:2 9 | Early update check!ja:1 10 | ExternalPluginUpdates:22 11 | : 12 | --------------------------------------------------------------------------------