From bc3461fa997166fcc9d7dfe530c435d7f3aede77 Mon Sep 17 00:00:00 2001 From: Rookiestyle Date: Fri, 22 May 2020 15:20:03 +0200 Subject: [PATCH] Initial commit Migrate from Sourceforge Bump version Show language code in LanguageForm --- .github/FUNDING.yml | 3 + .gitignore | 352 ++++++ EarlyUpdateCheck.sln | 25 + LICENSE | 674 +++++++++++ Translations/EarlyUpdateCheck.de.language.xml | 85 ++ Translations/EarlyUpdateCheck.ru.language.xml | 96 ++ .../EarlyUpdateCheck.template.language.xml | 93 ++ .../EarlyUpdateCheck One Click Update 1.png | Bin 0 -> 67293 bytes .../EarlyUpdateCheck One Click Update 2.png | Bin 0 -> 11169 bytes images/EarlyUpdateCheck checking.png | Bin 0 -> 8269 bytes images/EarlyUpdateCheck options.png | Bin 0 -> 102216 bytes readme.md | 49 + src/CheckedGroupBox.cs | 199 ++++ src/EarlyUpdateCheck.cs | 1060 +++++++++++++++++ src/EarlyUpdateCheck.csproj | 122 ++ src/Options.Designer.cs | 187 +++ src/Options.cs | 55 + src/PluginTools.cs | 885 ++++++++++++++ src/PluginTranslation.cs | 232 ++++ src/Properties/AssemblyInfo.cs | 29 + src/TranslationUpdateForm.Designer.cs | 143 +++ src/TranslationUpdateForm.cs | 55 + src/Util.cs | 234 ++++ version.info | 5 + 24 files changed, 4583 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .gitignore create mode 100644 EarlyUpdateCheck.sln create mode 100644 LICENSE create mode 100644 Translations/EarlyUpdateCheck.de.language.xml create mode 100644 Translations/EarlyUpdateCheck.ru.language.xml create mode 100644 Translations/EarlyUpdateCheck.template.language.xml create mode 100644 images/EarlyUpdateCheck One Click Update 1.png create mode 100644 images/EarlyUpdateCheck One Click Update 2.png create mode 100644 images/EarlyUpdateCheck checking.png create mode 100644 images/EarlyUpdateCheck options.png create mode 100644 readme.md create mode 100644 src/CheckedGroupBox.cs create mode 100644 src/EarlyUpdateCheck.cs create mode 100644 src/EarlyUpdateCheck.csproj create mode 100644 src/Options.Designer.cs create mode 100644 src/Options.cs create mode 100644 src/PluginTools.cs create mode 100644 src/PluginTranslation.cs create mode 100644 src/Properties/AssemblyInfo.cs create mode 100644 src/TranslationUpdateForm.Designer.cs create mode 100644 src/TranslationUpdateForm.cs create mode 100644 src/Util.cs create mode 100644 version.info diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..f590de7 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +custom: http://paypal.com/cgi-bin/webscr?cmd=_donations&business=rookiestyle%40gmx%2enet¤cy_code=EUR&lc=en_DE&item_name=EarlyUpdateCheck diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88da412 --- /dev/null +++ b/.gitignore @@ -0,0 +1,352 @@ +translationcopy.cmd + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ \ No newline at end of file diff --git a/EarlyUpdateCheck.sln b/EarlyUpdateCheck.sln new file mode 100644 index 0000000..7a33a51 --- /dev/null +++ b/EarlyUpdateCheck.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2048 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EarlyUpdateCheck", "src\EarlyUpdateCheck.csproj", "{78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}.Release|Any CPU.ActiveCfg = ReleasePlgx|Any CPU + {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D}.Release|Any CPU.Build.0 = ReleasePlgx|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {11D5832F-9BE1-4F98-82AA-B4A2547C0EDE} + EndGlobalSection +EndGlobal diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Translations/EarlyUpdateCheck.de.language.xml b/Translations/EarlyUpdateCheck.de.language.xml new file mode 100644 index 0000000..507634a --- /dev/null +++ b/Translations/EarlyUpdateCheck.de.language.xml @@ -0,0 +1,85 @@ + + + 3 + + Active + Aktiv + + + CheckSync + Update-Überprüfung im Vordergrund durchführen + + + CheckSyncDesc + Wenn EarlyUpdateCheck aktiv ist, wird die Update-Überprüfung IMMER zum frühestmöglichen Zeitpunkt gestartet. + +Wenn diese Option aktiv ist, dann wird zusätzlich das Fenster 'Datenbank öffnen' erst nach Abschluss der Update-Überprüfung angezeigt. + + + EnterBackgroundMode + Im Hintergrund weitersuchen + + + PluginUpdateOneClick + Ein-Klick Plugin-Update + + + PluginUpdateOneClickDesc + Neue Versionen meiner Plugins können durch Klick auf das Plugin im Fenster 'Update-Überprüfung' installiert werden. +Schreibzugriff auf den Plugin-Ordner von KeePass ist erforderlich. +Um die neuen Versionen zu nutzen, muss KeePass neu gestartet werden. + + + PluginUpdateSelected + Update starten + + + PluginUpdating + Update von {0} läuft, bitte warten... + + + PluginUpdateSuccess + Das Update war erfolgreich. Neue Pluginversionen sind nach einem Neustart von KeePass aktiv. +Jetzt neu starten? + + + PluginUpdateFailed + Die heruntergeladenen Dateien konnten nicht in den Plugin-Ordner verschoben werden. +Temporären Ordner mit heruntergeladenen Dateien anzeigen? + + + PluginUpdateFailedSpecific + Plugin: {0} +Das Update ist fehlgeschlagen. + + + PluginTranslationUpdateFailed + Plugin: {0} +Das Update der Sprachdatei {1} ist fehlgeschlagen. + + + TryUAC + Das Update konnte nicht abgeschlossen werden. Alternative Möglichkeit versuchen? +Die Windows Benutzerkontensteuerung wird eventuell angezeigt und muss bestätigt werden. + + + OpenTempFolder + Temporären Ordner mit heruntergeladenen Dateien anzeigen? + + + TranslationDownload_Update + Übersetzungen aktualisieren + + + TranslationDownload_DownloadCurrent + Immer Übesetzung für aktive Sprache aktualisieren: {0} + + + TranslationUpdateForm + Early Update Check - Übersetzungen aktualisieren + + + SelectPluginsForTranslationUpdate + Bitte wähle die Plugins aus, bei denen aktualisierte Übersetzungen installiert werden sollen. + + \ No newline at end of file diff --git a/Translations/EarlyUpdateCheck.ru.language.xml b/Translations/EarlyUpdateCheck.ru.language.xml new file mode 100644 index 0000000..1ae3030 --- /dev/null +++ b/Translations/EarlyUpdateCheck.ru.language.xml @@ -0,0 +1,96 @@ + + + + 2 + + Active + Включить + + + CheckSync + Выполнение проверки на переднем плане + + + CheckSyncDesc + Когда плагин включен, проверка обновлений всегда начинается в кратчайшие сроки. + +Если эта опция включена, плагин дополнительно гарантирует, что проверка обновлений завершена ДО отображения окна с открытой базой данных. +Вы можете продолжить проверку обновлений в фоне, если не хотите ждать ее завершения. + + + EnterBackgroundMode + Продолжить в фоне + + + PluginUpdateOneClick + Обновление плагинов в один клик + + + PluginUpdateOneClickDesc + Установите новые версии моих плагинов щелчком по плагину в окне "Проверка обновлений". + +Требуется доступ на запись к каталогу плагинов KeePass. + +Для использования новой версии плагина KeePass необходимо перезапустить. + + + PluginUpdate + Можно обновить + + + PluginUpdateSelected + Обновить + + + PluginUpdateCaption + Early Update Check - Обновление плагинов + + + PluginUpdating + Обновляется {0}, пожалуйста, ждите... + + + PluginUpdateSuccess + Обновление завершилось успешно. Новые версии плагинов будут использоваться после перезапуска KeePass. +Перезапустить сейчас? + + + PluginUpdateFailed + Перемещение загруженных файлов завершилось с ошибкой. Открыть каталог с временными файлами? + + + PluginUpdateFailedSpecific + Плагин: {0} +Обновление завершилось с ошибкой. + + + PluginTranslationUpdateFailed + Плагин: {0} +Обновление файла перевода {1} завершилось с ошибкой. + + + TryUAC + Обновление не может быть завершено. Попробовать альтернативный способ? +Появится окно контроля учетных записей Windows (UAC) с запросом подтверждения дальнейших действий. + + + OpenTempFolder + Открыть каталог временных файлов с загруженными файлами? + + + TranslationDownload_Update + Обновление файлов переводов вручную + + + TranslationDownload_DownloadCurrent + Всегда загружать файл перевода для текущего языка: {0} + + + TranslationUpdateForm + Early Update Check - Обновить файлы переводов + + + SelectPluginsForTranslationUpdate + Пожалуйста, выберите плагины, для которых следует обновить файлы переводов + + \ No newline at end of file diff --git a/Translations/EarlyUpdateCheck.template.language.xml b/Translations/EarlyUpdateCheck.template.language.xml new file mode 100644 index 0000000..4827502 --- /dev/null +++ b/Translations/EarlyUpdateCheck.template.language.xml @@ -0,0 +1,93 @@ + + + 0 + + Active + Active + + + CheckSync + Update check in foreground + + + CheckSyncDesc + EarlyUpdateCheck will always start the update check at the earliest possible time. + +If this option is active, EarlyUpdateCheck will additionally ensure the update check is finished BEFORE the 'Open Database' window is shown. +You may have the upgrade check continue in background if you don't want to wait for its completion. + + + EnterBackgroundMode + Continue in background + + + PluginUpdateOneClick + One-Click plugin update + + + PluginUpdateOneClickDesc + Install new versions of my plugins by clicking the plugin in the 'Update Check' window. +This requires write access to KeePass' plugin folder. +KeePass needs to be restarted afterwards in order to use the new version. + + + PluginUpdate + Update + + + PluginUpdateSelected + Start update + + + PluginUpdateCaption + Early Update Check - Plugin Updater + + + PluginUpdating + Updating {0}, please wait... + + + PluginUpdateSuccess + The update was successful, the new version(s) will be active after a restart of KeePass. +Restart now? + + + PluginUpdateFailed + Moving downloaded files failed. Open temporary folder instead? + + + PluginUpdateFailedSpecific + Plugin: {0} +The update failed + + + PluginTranslationUpdateFailed + Plugin: {0} +Update of language file {1} failed + + + TryUAC + Update could not be finished. Try alternative method? +This might show the UAC prompt. + + + OpenTempFolder + Open temporary folder containing the updated files? + + + TranslationDownload_Update + Manually update translations + + + TranslationDownload_DownloadCurrent + Always download translations for active language: {0} + + + TranslationUpdateForm + Early Update Check - Update translations + + + SelectPluginsForTranslationUpdate + Please select plugins for which translations shall be updated + + \ No newline at end of file diff --git a/images/EarlyUpdateCheck One Click Update 1.png b/images/EarlyUpdateCheck One Click Update 1.png new file mode 100644 index 0000000000000000000000000000000000000000..3c8d4854ecb13b4f2a8ffbfcc980ad2beebe6620 GIT binary patch literal 67293 zcmZs?WmFtZ*EWi~yAAH{?kZw2RME-s9o0_VdFv*5zXokrmFn&a) z3p(Fqq;3G5yJ`H$c>UcKq@4l~^CCc%e@pXFPI-Q|w)%D7-)dD#%6XRh=RQ=CK3SEK zAZDjzv%l(l8RT#AzZMonQ^o?r=l`pvq$*-?{I4S=wCH!KY(A=!D4hNfdx`09y79T; z;@VEpc_q?*A#3)J{6sV40p0)m?AS6E7jhJ-(RVHD2V2qiVJJNh4@t>F)_6C{n7@E; ze0@!H^$lZL_9y$sO{F|vL&Dh9$5{WPNAay6!7DWfa}|A0Fwy(3UI@~GzX9=7B7}x5 zr&&*Dr~yG|k|!K)3a-O~k}{6mq5iudkdfs06)1i3|7dpP>8!Xu3!XVLl5c))yTO0n zjZ$lWDeqB)0s;Z;kktBdGH&dBJTYO@_hB3>gOs+(FRxzRdiJ0v|JDc|XJs61|F(@}L5X|K ziDQ{dqh&ESw-SW~hYUej-b)d^_ORa_+W~hkUpm%bS*sn%)xUZq>h_NyrW4QZ>HqBc zkJC@ml1<+tFj)w6q;!>tOU0-=(K$MGUp`B`|B%Q{bAlt|;&QZk8E{!kdH!LdI%1{T zvHwUbAjDEoSg;_q)U0hKoaX%>VKUI#Tm&HzxAU0j=oR)uH(Aa)+Z~DLi?> z{#N7a?o78=Fse*6p|%v$PsvlvjZBfs4|@N^Cq*E0vDM6L<++SuFrB^1iSj=xss-Qh z_2{nt+=Z^H?a8T|3ZHPxh>HV$QBBh1rzLQ=Cd>*pKNciWMDN^%sI#pr0t2qf6sbO$ z#cQ;2=qg$;oZ(>SM*+XGlJXRwL}ZGlXQkSnrZ@!WP(>c^)};TNm+uIHvDK;ghKeF! z;$1iB8c}65JB?-V9lqc^&G1*5+yvCKZ$!B3-sG=de|DYR#N+L0BuP{k594J^%p?;x z?{yurl;`4;L5bo4$!g2P8v<(JE%LT?sz%6AW?w}O)}({{VP=oPHW{7${hyqe6(!e? z&1B{ozhWLn2z0+LlrCO%@o;gA+uUiGL`f7fNe+(!YslS)nm-E|eqGoHz2HSLJY}IR z*4efg{x?i>sXAW1{6(<`p-Jg97wwTCdRSVXJ|ua2S|!kruI$rqsZZXA09ADkS<6k} zU^y|$Y{zPvVKLELdR{so>WdK5(4Z>vtn@<8UB1mr4Zc*x34?VNB0^0$%U}hQ#wQDG zX)blUcjBIG4-2JS+@clntegfJor2!sL4jz3TE&=M#2x|iN1|dhSYbc?E?@d!JDR3ZnA*L) zLIS~;W)AaD|0#zf`6|S)oSUSTn}bxt0w^eE?k)CvwxCU$gi~RZH{X@{L2sMJkK@plQ2wop)ggYw=T!MZ4&K_Us!xg!@k;>A8SArPMwnG5Q(%cF@9m>v{86j zJ6N4f%4E1ss1~@fsbeBL4!e{Q;YcCQGMX$ z^}XvEO(CqFSAf_1UD)-o;zs(SD384EOO?IVwe0iyPK@j`l@BnH_QNv!!?FtGcuq z^}-lrqx(;$v{e4`a`UO`FK;Zmw{c^9Sr@?x1l~UVe~bzyFeXTow!SZKd+lQT+rGG? zzAurNH4q!TTCd^52fZw(-mhn_fMtIFcEyrzXc_gSm-{zRfBkdrux=m3!|halj43WN4O;@O>xy#dtN3jeah==y@9pT@@Nz&Hr3^@b#eu2w$3KCIBu< zf#YF7=1|Nql*Dar6|o$i4OzwH^_W8sr1szY4}0D|V5a}MVERJ=#+ptUT7&%92OTJNP5Fr%5QvPKnq=;4x<&OimO_2W=xP1zl z={>$pX}8(trHobs%y6dR8Bz!f&lPC)4-U+BfW*ssL7<7* z;+bXa@r0$5A9M#T2H(&idBPr|r|rU%{-bFPo^E)8cFFIud`3#@765%yvGJ`vzbk}6 zr%LZLMH#QYQ^yKukca)ty?lFn#zjM$kI0>MPM227``pkGgxzg17 zttKeY+$$W}{zojpiojTsOMnCsKxkaTVhAQafD%F=3;8ZkbntEYyc7^5mZtf?xC}58 zHi>Fs%3VaxAxtz!P@px9V%iy_&Vlll;^SAK!9#Y%mWG)*2vz_@?7#^Wj>h~)_5d*L z3(lNMDp3evysK0~nfWJ8zCFFyKs?Vd8#pJD&YFJZ> zPf5hX35gYs-MhZ4zp~u0db3zVj9x9Xh)ddk6uy)9c3AzN;ydCq3Oe-~Io7a7p%^tF zu|kNohfqBT3>oV`*eFecU?(K#8~{SYKmrrS@uglMVyn1xDq$5{KP@wC&vl)xVBwgP_ee;V{p*C)mZhX5a zwnYKWTnWVX+IzWiXc8)Yt=JT8GaQ?NsAdi$_#$q*d(9s{X-;4ys6x(OGgw2+6O-vL z`LRB*!m9+&=)LMMZpZ%&;M*Uvhz(@TLqJ1o@{ibc<{kSd66BHTw(sF`uJb@s*QxxE2SKsRoifxbT;nyZ2d zzJ0o{wTi3XdXdX3zDWqn8PEc`P~tYC#QLfKv)8jc727ydMh^#<7?Vr&JiLv8zI`&qv_pl3d~?>Uw-s@U}?Ts)x4*7-L%``d-n z@RAXYg4Zgj`Ox%4iHL4Mn?=Qwk;Fz8t39tuZ4Z0VJ&@3UV6qpV&T{P!qn|UIPIgC8 z=k9J^-lmD_}1wdL|1bbxB8rp#&Luu&a>(+)9D)8Y!*_# z9DHEY<=5eRvQug>&ntr^&NJyC!%2cy&(OCdCKe266dilXt4Ir;j+Xi8GU@%G}i z=I^LR(vflsb>a#|YsN}!N`ZVADI5@DQoC_ibee)?2lYY>&ScYWFJrj`Ocfp&Mr@7F z8iI`iu~BpQpG%}qYvY(@2YC!vRs9SfO#P=h>;;q~1z0F)}&HLwPpYJLQQ-M2i5`r?U&dQa~PONXFG6f!>nBw03u z_^Bz7=6FRrMe1X`T9DtIs( zhhnJ&LUyQ=N3mT{sS}SFYGMryv<<>68m1vOLVsm}pj5Ltvn%U7BbPw8ZVG4gl@IFP z`Oc%Y#MXQ_7fc>4C6!<;^mne#faE!3+h*BrDH!5ab;;z`y)r0~XTCFk>OlU3=4^D218^@C#Nd)4(D#>)R5@5D^ zx}u^a*+3m8MHhT~q#M(~GNh?*jmk}P@sEQOR|1+S)pJS8xikw?+*CEq;Kem%Dt77k z#7Bz315;k!g}5|DL?H8vmv7jAi(BdW%NX1`pImHo4(_U@UJVi6Io?5Ky3TTSi>M+` zS%e0!D9c~F%JRVW@IKK3Y9yi}O?Z((ZO@)9-6B!=_o|Ewc@%v^C{t%M8tB)7Dc)6R zwdPjn^H7(nd!i&$5AL!h4%Vts;+1#e;*EiyB+F|=vQ z@Trr?j&#rFB#kqkGhWUz2S3IE8w&_@J{;U-K@p11o7bWIuI2YwBCFkDpKw>t53uCQ z0f#U)e*%YfKOaA{UAh0Mpfx0KZXp`d!$n`T{GJD^5YemT(-{mfWWok(R>tHK5n z$FB6T0s$g&VnArhhm5cEyE3xCC`R&^_AQa6uH)X7U&V*mc*XQ+LbomQpqXNC0|Yh0 zBvIz@pxSnFkR%r>Klv`cMtG>+A|5W5lpd(E3nL&gc8DPSy;#{_d#$lO9*S=?kE>Nq z1I0xYO3;lS8y~u;jNo-}rH`_6PIkSd*PG6d7$=--rt+ni>d1f)`*ItuDcFo3@AXV5 z=1t8t2G9^%3V)$aus}KavS>XW?nmVDMRxV|CHl&cfoA|(f+TP(`3)M%h%itVucYfo zm4oX#bY#)u32V@47_>c_Zy@^!cVg8>EKzN`3>HVn;v2~(QUEi5T3i0kD{1wz{t-j6Z7mO)7q(bHj7crba3*!#5n~~8=?6sD<1LJZBvalUV8Yk zBWR=z{+fxpLqM-CH{X{f^uWMT88O_hT|3Y9?l7lNL5X5U-iP@$j!;x678;^;=&%7eKQIWU`&KW?{a z{UCKbL#ltx#tops8DrRO*Ogo^Z*&=k5XV`=f)OQ0V94KzOp{%V62ER%|@4+>y&4D!+f3Y}TrS0DcT$4K~H;$=o5xEUYPN>fPHhbo( zUK`cIowDY;7PSgEsgdY_xyQyGH}8a-tOdt`GyglXRSCYhH$qNsu#>YBcxxP|DMl;w zDB9M4xM3>#(|AhX$V;2&aZvLgz;S{|IsP7)O6gW?n=ME015DWnz-FSrWF{osGvO zU2}W(!8iaS*TLqwU|3YufZ18X3FIFC@MAq@^*9!G@Q491{J+VPB}8n+GqCG}*XJbX zgO%8W35;BS;WJ;wl4A;&d0r}oO0P8{9B79izZ5oXS~lymXO`=~#78qes}@g?W|SGVN1D?^L4j`Y7r^z5_r|FZWjmy}nn z+-3E}y7_!`cRAEEG-hc49My=NU{}Js=IZ{e{xW8Ni}$pT?4!_}&N=_SB)R_Q&NOkq zOLtEiI*0KRB!n+>0$QbB@J)#PusBY~QwsydZuz6VbA-~HefijFX+AKcmR4Z5TGUNFrMgC*zA!url)%N(p^>shXPFaBnv!)U)f8(`j?l>vbOTyGg7{LI(vQS=fHF6xa-gZBo_&2i z_Wp#(a?#F#Lgg4=z$tl*oGdLhO0Y#rm!jFn=kooybh(83pYn2M`kyB%j=2fwx7P1w zOVlKS5-^#4jiRwX9W~;{+4C5}@fIU}+9;SDA==xvhiR}0%>SF{!r?WD)!3J)jtNWn zO@b{JV>EmkLPL3?nRZqPmVkX(!v66d#`cP8RpcOG3ZaO>y6`7Bap@+|#M;8#Kyc9_%D)*A=)=Diiul#vfqZw6<|t5K4Rs z_6Wa0D3$K!Ox|}=?spNm8k91Ux#S9;`oT0VrUf#o`0~4W%M&3bDnapkyr`XBtF==% zDH}<|EZ!rsCj*u^A?L7@B3ZF)PpO@7mbKkhtTdA7FTeR_fO2_Ls+Pq#{ZAr{q+->E zydQGT7+;EN@sF#IVDs77LG~2m!Y7Jpwmc}fGxW^NDTZ>KLZ3w&+AsF1yv?{97lj5wyi=7_J9V8(%Lm6D)=uFnEMFr|1 z&#wg~QEX4WT(jBiU+A|;(S3F4cR=XvwHZms+Zkp! zduaE^GEgxqSk&Mx9EZ#kL6D1E5f`1JJ&w(3Cq;)Y0Ccm5P{Ud0_|Qq1n-c@irhD;I zLdVn;^F;^d-t>J)v5qpiVQbS>SxTqNpF!HZotn6oyL7eKYb=s5nb2crOKapiYF-m| zu87-E6|ouYz~D(mEz|nLz@gD>i_J@p?|twPHE6r@_n)f)OJLW%ytyDhF}8hIL%dyjbUy(9}i+|#!%tJ3lF5Lb(9iOI)wS48njCwqf|c9hSjn$s*^M; zGP>d%?*b}92eJ0=Su)NKTb&~U_yuTWfd*mh1{GlW=Z2dq${c}ikzRbmGyJ}i2+xIp zJzX2f#9F(y*E{jg%9q}Qe!B2?!^f4eM(W%IS9fUnHtbSws3~wXM>gd6Rz}YYi-T%z zZVGf}seJN@kJWMv^#^Hg*;aeC`eT`SDz)T_8w1atROuPG0_1{{vl=Llr99;|!hL3a z{T_9Emp)XSfJbvOK14$>>{MDkb(J))9$J8sN({4~qE+?j35^)Dm71JfO*AR0lrpyo@ zv_tZ(VC`{yd2(0YNurACo_A^n{DiupCVgt4m})H_Mu4`S5A{9b9Hcbyg$%-FWvMm- z)*{>XLt}k|D3bYEX(FHw{Y$3M7pNI{jJ3aIT^d!af!fvlo^9<@55=yL)Z3=iY&d(H zzoK(e=_Dr)BMN>hf&sT$Y%YVYdHpxVPwEb2hpkOxH9oXdAu#POuyVB6Y-C9e-sj!F zT|2(_bVL5ci1notO+Qu-2I|K4wt6A6a;*&G6G9xoK%rmQQW$$x2d%Ek&?z#N+WuOS z&#JivHF-%;h$l*_Q2oGRuF0L5`8DPU!E)(JP!=`Av3U*32QREKm*9@e-G$k;SK$k*ZVa@RPF&n|~{DAm;$ zLcu-^c2LTmqGcEb)8UU;645>H5Ql!2U#=SlOf8x51~*I6tqk%rXNwb-#3I@osV3Mu z5Blvj-c>jcwVrJjQxMX~J4Fr0@h*gC4rRU!3b&lMUp_`9a#ZE}v-uPAB<wiUXkLTyLk%wI;p4Lx;#JD;0?G<5S+Cga?;KDfaLigF9tKf342Xie zl{LZ^pe+{^O&{vH1B;Z+pEt^UNuTi9^~5D z)sTt)qV^HX^K3Ww?3A1|_Y@udRKH>(c^%Z9raf|Z96m7C%6DwDB1MheXgizi;8V2v zEha{iR@hOrYNZ%9|98(~#aD4PX&O|1i9-UQ4DFJ)?n3JX_<~+9Gg<4LWOrXJK;K?z zKe-D;#ZyDbBFH-!P#ZdPVQ)QIjB3`CGFpvJ*4l}Ogz}1jrQLN$i1(gn(16p`(k0WM z!&}`>?iDI-3>uEnvU;B)OKdtOV{r*G-F84x49Q#Q|Chs%5=bhbSQv}_J1 z+$s*?W>NQOh1ldP+g!pd9c@@J(iKI>W8W9pQm(f+{YIUruWcqFe$vo=+a76A50Xmd zI(Zy|6wjXB#Ug^5N{Nh^(~faY`;Ij2Jp<`^OL!>*nZF^vcw1AFaIeN6W#FWpEkpb* z^PtA-PXxOO%~Tb4J>(3Iz@d)frkTd~h=hh5I;M`8`YO(|C3$(ui~741nu|sb;o-@a zlcjI!-pUnfunS})*1h);kXYTWZhzkMqvqk{<@L6;zfG<5JtLVut~N+tNN)A+8$e1N z**2VHFgMcPJYPLnvtKyJ=A$0D7N9GI3<;Asxb2Z_kqXGh_Ugqi3ISgpgx!hCo0agT zc8o22bDip4=<{4Q{{kj(qV0qoW?v2P#}SHxnR@U*eSwuP+&}SLr(p@~gFRcasF8j? z!OD3{KaUjNsBjXX?iX?#@lqTaGoWZGW~YFK?dir-;#9p!C~0j?O0hkIgq{oY8OsbZ zKkM$=p_Vl?5o5b0)VKnQCe`Z62tlX^S-nMsk078Xzk9lUEWn4TBIUHs$2 zNrj!L>F?s@4&p{Dp_?EwBcrPvfFlN7!nr*g}W{1cEXMIh7pdL$tL)*viJkT#-5BHlUUab6fdcR8$!8hcNDS@o!2r<=o0~MnLx+|A={x zptEBNGRpfi7JT~W;NH?*LBG?jMURDpobfHCKxXD{Zg=X(x9KBeNXQ{e<)UqkdGV#C zHAEZ_PGE51;W?45xNR}$-GEn5-_ zm7i?gMF?+Cjow$3b*J6W+6=Lqa`{%&EhWXq3h@q^C5yG=xqT;V zZuYAe{9b>0kSk{01gjw>WJ@Ml^D10HtVh(=uba>Jp|614d6WzdLOv+t^ZCrRr$lRg z{OIG;AMJ$kl&mKRFS7a;@jFd+?9Y(g%kRIEF26sgvsSh>&S`0u?-`;EHjpu20H&Y~ zC)-JimhLp03xB@GWm;K5ETD(E&_4cAadGh(mzDuM%D7KEqDK2?E0w=abW^?Net%2I zt)og(B&;=qdWf_njlg7x-*n~F#N-KF?^oVFka_gn!dr&gb6e)Ok!T7BeR-LiLWp^; zSm~mK=5&4hD1fz}G#yS?VpXD+>UWoOKSN33V7!cni8DyYO^R_7o;XMtgT-7zM7R}e z1k9?A<~Fp0)nwqgul^?gF7N1{IP$^Rw4qxG48zfNs2JV;0PR;H8$xYM&N}#(XHpQq z7JpQHmw9w;}Ppq(^Vc+m3>ImkTH>&4q!Cy0 z;f>y~tf(N0*8)82eYl~d)J6q!hkcumD8UW(h|(5a7|`)*9kUJ^t~}J_&-obo@+3Jc z-Sq-;emg#HR#UN$Wqy7L5BRyC6GRE8){xrDOUmel=rE*nv9a@verWwr@u?3WZTc;1 z3TT|&lGBFz3kny(R%0HAahN4dI@rc|`TCR&517>nrD_tj$k|66`!~SIqtURUz>!R# zPDr@hil6ODVuVxUETZUwkDX5$ThN{twU1wGugi5G71(C03P+-?shji9*$eUC)cmpE zz!A|zsY~wYr`y}5&Nc+C_e8_M{OC!fkhW7(Tdb%gio{FXD0-7~e0zwShyecB@!s!c zgi~P^GTnC@VNSRLoquA#!B_fA}=7<&X z7%H+~fo;b19vsf`3iBwt;?~Cf%ejabGgTE-CnDPne|XB~Kv5Mg2!x30X%f>)6KI(m z@Zk>)^L)vTVQ*7tALk?yQL>JaY~~pX>>!DG;qTEKS!=Bx=5FTvY;k+gKh6^>Z|-$3 zl(AbJ0{e!zZK*1S@I&fb7cc(PS#HduPh9bffNi*Y+3@dQUoNUw=C2efJMzs<5lZ~n zHNqw9_Cpo!G*=WQmZa|+@J1Lsfe42m%33Wr-^4c4hy3>0jK9Kv-n+$5{3`l+gexH1 zw8~>fjx-xOxXD)GYjj~!I66wD$dnkq&i^rnMao0;MVkLl5psn6t};g31XxKyADg{e zLwC^}5jxPPWh6tWuC>(ZdeFEMU~Zh59#c!gTw$7Z(RevBGf)mT?TyR0!=b9F>F>;2 zY4BTdkhUGlf&Vgq*d&I7h?*GIH4*(dt`IHk*C5J3*m)!Rba5)4BX(+ON4moxB}8t* zCob3~D4<&;H{VNd?tKW{DW%Z0=ti^(?w|w!FUa-YdY)yOho*)?`le?^=$X9*xwEBE zE>TchznCYvG5OZNW5|-Vej%el&HD7qYwee>&B!wWM)>D~D#X^z@lRqV;CA3=G%C-uaTW^Oq%FMnD ziVf)LS_Hz`1H|JgB@hn1WDm>SKt07s(bK~l&#omyPWA84>3o8TaoN+EHGew03*Pf( zM&S#Sz$T%O34#>$gDE-2X!JSD8)aCZ=@{~6PwD+kSdNUAIL2m6a3WZ1gTe+2G#~o1!j{^p1{rtcY~vNW6edsvE=CCI z{jO1}UgQxfJImtJbz@r-Nw`y%9wxLL9Dt(lvU>^kB35=C_BNaJsY%Lqdw$?ZjK86% zcV2X_S#CrQ!p$fuO*kvIvHAYy!}^f;Xtk1q5goA1)gUcxV5e3kEizQ&V(=T?!GV*4 zMJgc*GZF?S6#NU)kmdEA2$-)EeZxu<+vYKxqQs&5V{3!u10NIVe&ST*a)nCp58C*A zL7eRoEak?raIOjCjk)x$nZBdL=GOkI1p6Wu$^m5(@a&EkD^(W4*YDFuM=IEaK#B3= znP0mq%6k0#*H^p_zsP|3eE5-KY}O40$=8~^L2pI#d}QW93TsxBMKC56M>nii=Ke!fN*-0KN(Ul1ZVV z=NJWdJZsdf>0orRk!%kq?DSW;UTdAyRw=j@V?QupBjRTak4g4Oy}o@u@0fSu{jF>;_`X?SMF~o6oyoSAJ5WMSfVm~|;R|E1ZYJ(!ZvfU#zN-IwU&=nl^Ggw@VlcxI%GtWrIP(u$^c zHjQUUM?d1omjikx%o#u1`r00wgK9&95{W0`zH4EtK>EtIQ$E7PI=5KX< zYnRj}3|qMcn_COYDv5pFjOG`Oi<=^_57HveJef23n{JYmy|TReekXqx#5|UMAj)WM z8J%vWWsdrmt?I0erC^Q`wO@9zTG4(AVCATVaP7#c=`u`@ScUpX11m$X$D!8ytM*jSEVY2MLnLvdL12X%43AUk0KzXu^IqXUU5DJ2LpC&&P$) zA-sD)#3zNHZ@8OpUg=s`JZ>(GAMzLPe~ z$W)^6zSqmLnlwU2HKo6)qEQ@d^gqLo5Kfbm;0?R(vn0P*mhP~62O#zpsP57W_7BJs ziEm3d8b6*^LYVp%{n*5%e)SO{4dHO8?V3@(1ZhC!tg+|7h-FQ?ndRy_!A1fgh_mwj zN%K%fnqf%q;!c+$@RcaN@P1QV3AS-!hB3OQ$%B#)?_cVCv^i+Xmu1=AT}T8B%|9Wbxbw04D*&z)&>3}6ZH9Iu1T<-9fU!qc zc~LuH2!}ph$$>jk1fw8i2~Q)9u3z05kuIlj&*s*ahg&{i%{q7N)GhzzgK6o5Lm=nSMSgYR zo_F|=q|YnG&B>0he^Jf7hU@wTj_F@`PHJwY3P4EjkU1miPC>ws`gIa3C!^GZ=3-!a zE_?ZPOAlk?#3i!!D}{pw)r5m=W(zfUkVJD$ShpM@@4GErou=uS*p_n!ky1cqWo7XD z@|*)0=_YK2XQ%%t^2sW>{~s{xn}ZV`aZ#)?euG{S7%?>pyXY^LOtct{gN`4vLEDd0 zXG5qEfFP&L`xVdFrZw`8?enu{C`I#fZb~A)sVo@+TabYg_U!#A`{XM`bPFNwj8yNZ zEV`1Z5R{;>IdyvW(hoCy$b-N*HI#{}Ljaak)k~*TcvqfdggvK!xo|26R{Fa+a0F0S z=~o{~f-fcRA3rAfy>OY$r38Z2q<7LRBqF0%|4!-QIBQ^UKHI?EDT#PnlR15?;@t#4 z+#Wo*qq42DDo!PSk8FD6Uz}~CqCsw+sI|sQmxWa$KOUkvc`%0{Wh70{4sZFRJ|lzO z$CPs8LUhw6p@^k=<&Y9g4Gs8)QtSQ3WWu*bVM!+JN3RwTz!5`Cj-QT}2ZQ@6moyJ= zi=X##EX@&>zIe;Jd9YsknpVP_S8y$0KJ!eWxez-!Ir#))REDm-Ibj_m->4LkQ-yJ| ztoy+TSEBcd$?D&Ad)uul`Y}w$2Zhu)96nXAK0FI4hMrqB?ZPXLfF|{$U~J}9<#6Uw z0OQxnL_92YgEsoWh!js-k8aSA0S~l4JZuSy$23`5i96sBey_PUat;EYQu~JJ>DprlDlKrx{0pKSbE}`CDG}*WBCWal<7OjDn%tC)u6}^3x zF^yjXLy!pcp>*u*0Ec39Hns<+HhHC0}8q> z74Yf*8U-@ohp3WjgxmaL1`~HXTL3;T$Qi~fZVodL3o$8NVyJXi(DBJ zLfB+jMOOTx@4_y>{EkOaMQLl`<{T63YdG~Dw(M*u3;=vFj%aKQV8qQvpQ{(IS^p!P zlUof^8sb`bc92oJR8e-cow=a=D0A~RYii83cqZCF#FS#*dD#((xq>PYhn*ay>`q*q zvfgV-prU%McdoL@LaH$Ja~T&G5Xe*>?@+`}%*W>p6vd9Ptd`Rspg!2_y?DN?V863o zc=DiKZO6^dHsPfh(%kwF@+z@m%O!BRJ;7+F3gQ!(vDO$!#WM<5;be_y6yM=cIQF8w zy7bEH8$#fSU`AX@j6jG(`oJHMFQ|?mo{|>Ap#}F%%FcgYD|Gvtu_Tt^SFilr3{}r@ z^i%u0trwU=0E#tRrM}5~@AF`2{rx z%?dSpjgvne;0Gp5R~Pj0T{WJOF;!^CbpNOg@vg!XhF^CZNpdr3!TrhS%de42J5m+lF{tw za1_%x8nN{Sa#vhnC-s@YiIXHrh!(8mW*kY3uHpORi1Ek=s7P}ea&g!63N8wJ|AyyN zJw0sj8tFRH1=mo=E3*_mmVv-%OPZ5!Kxxd0T<0$gR)D|59Ub53hJ(%Jq44P-;oyKZ z_|q+eSJJ{pE7x=1rz15V!D7nMm7nz1F%wa2bK#xezaG48y<{^?NId-%!@w{7b=g?SAa%8DiQ68kP#qa8+^=z3pcsK*{2uz8M- z7j4h$-WL@YLt2;Bqv~4W z)e{ks*CODTXX9jQlf;{wczu4`Qb+luP)SiLtsqjtVKgVF<NMZlOIJVzBj{dW*Y&V6ZGvUBB9i6lYNY z0kVM<0Wr}0WA8l_#Is#e|A zwF2^LZSPQe$ik4l_v1IB(IYEk$8bJBetrjKYmdbz)-P*Q?CSlod064zP@#o$xe_Kq zL{!U&_(@DKzkOo>VjL-3puF#o`qZw{cPw{j50pP8?k?ZH8{rSw=bJ2J+}Sse>F-;Y z5B8xjPxKQM@_-K6$p^~g*w6!29kAnD4`x6fBi(JrHs@Du$@pf_=4Kx)cQ(9z!4E5cl-%w*Sg%g{C(dgW)~Sac4Q=|~wf*{lKCIV$Gpi@a(eM(^ z%|s*9eM$lxpSA77d_OcI(Vyq&`bT6vnBqp8zOG~20n2GU`cL=m!u$YHb^^`Ik!f16 zDCxxA-%|nJpUBEJWYihUY2+n8!V1*;Be7e>xqQZtFjj4qB3d5Xk#la*?C2BuD((Qj za65?9LFJ^__cl?=7W71alR?YBU#R`D7qDs)o`+VrkWlgmH~Opgq0QTC8azl(a?OTl zY}^%p!QLUVU4%g;zw!PaF3=%<&)ArDHQzk%Z?mkO#*tw@^p@6_17MU>SiH<0dM*C< z$4TZJ{p!ISA7`OI8)(5TqUSgbL|Kd7_*&%=#1%%J{>8DP08>$mG1W=6s8#bAW;3Dc zW)$&2Muhx6TW2BnyYMjTQL)&V0uMTF=6plW3h|1>?$0|IP^k0a+^&n9{;_Gh!gTyw~4z4IoOamg=CSNr8vmcc^2wD|&Tk&Qs!Ox7CV+y@V4w~qI zE&OF2`^~M^Am~#)i2j|$K+CD!B-l;GP>oO6V+HYz9SMPH>sH=FzU}HTV9CFLWNcuV zZe%9<)@)+qFG~Da2oXg)3(^MzEVVaaMP{1Ecr^&8Ew*0KDB|Rodt^wz(wob$6U31Q zM{5SL!_ErcqxmTx$CJ@4C1JnYX3j%-Aq-CzV5VC&j_@@L`~qcjrmegGp~NecR@mC) zp>gmv`#T=Ak`yTWw062=wK6Ot7pbu*VmspXd^nTz*Z9>jqZoi~F7UVUR)(d2%+S`x zvcFZLa?`g8b~^7NB}E&TcFH&4<0}y;4napae7YRc*nKjzA(HVBiOG;%&GHSpRSA(F zH-Lm?)zX8NY+`{o@N{>TH-uj+w8EKW*yGG~d2TJD=?HXVVSPrrE9%PqvE)`bJ4GoF zMq=esq{5qSS0)e9VxHl2CZGYta1KTEF(8SU{Kdg4$c$+AEvj7pY*gSIwl^72bdDe7 zKm$H6w6A>-Gz|iN{W5w1Ukt2A)-_Ik^m{BOnm!TNcPZi3%7xY+wkiVQ-#~=#0i}ENsDTN8njl3I(N}6@{1d; zO>tN>8s_w3jKFrF2ttWu1+%5^P{Z9hN(2=1 zXUEtI5%sjDQCByc8S0s>Qu_IEvz@g*pLuYH^j70f7L}2YxKoEHMP%`H!TAwnF|GG! z9*(UYdlWW#bbN`EPjg$ZTo2pW)i5quJS?(0NZAq4nwB+W-a-xsuXJ1pFI` zW0i<509PIbR-QO^<`f04h9j5yn;er|tdI&C0b53lSPVWK0Z-pgNnPHdGQ z#DoB1i2R5nar=BsHaiD}qqdi7d??LAZT+Ru7A%518|5#mwM8 zJdQ0<`a2WHj9mJq#Dwaci|Nf_N-RG@GE{19-S+yS4rys7RkAWZ>!hT5jL#L8RWn8M zs*D^nC;105bQM{R8zJPtzLeAkT**YBG^2=1;E+}+)sAPMdc z!QGv~HArv|5}e=;gS!UzL4q^5bLM$|?|a^Js&3V-x^@5BU9+q9uHDnUdUdbw`Yiot zv12P38tjLR`ouJ6GU7^_Pc$4cQS_NB*gH`)`7P|Chz!+3^IrRzHy@keX|ZLWwlAA% z{#N8PdA)t1 zsYz*h0(akw`7mli$VV#rwuj0WI0`+*6hy*CPF6Ma!+0D=Y&k7~EVbJZXXc2#{$0Kw zxr?p^$E?c{@Z<3hva}SzgFEO$zb9pXFtFmJK%VNe7wy3LIv78=D{sb5HxpLXK5F6# zA0}z8OV;JOYTvSV`Hg@#fQ#lcNvM)5e5M~^%l-=T_f(vO$`fmnXH&-V9Ij3~5KytY zANMF=g>lAwg#Y2S^~o|F{k-or(<8kI$@$=A^P|FTAD$?T=bAg`U;;^)t5xjKZd4)Z zs)rW2_X*SUeFX1zQU;hk9&tFkfv!R8WMJj=Cf$3k>i)HvrDuM`j4fc?I(CwMTQwDz z)3N0}w(D|4c!PEdDU;;FJY&3$XdDa7*XmYGPrm~!%?<5Xiy>;>mEhk=mMDUbc!Q|K zA>R&^Ed6=Wz*iJ%9k#3_Cw|@A@XcF;j8g+Y5sTOylrVoYYo73{#-unOz#R#jfV5-D ze#Ae*7Do;Pf>GwpRKgIoUM_5K(og7EnPm-pH!Xh_%L{&u>x2*@o$UdXmsCs8T8NOQ zRX=lT^k&4o;^UH+_=!W-O04U7l0!7 zTviyZWOwux3l0g920S~)J&k{(lsRn&lEU5kv4lr*`O zCddk8{+%>b>m+b3K#8rYl#t{_VOFJXAnYoi;GAaJmcIFOvCodHUgafXx;M68*YpHq zw>UR+t$|)HZX#^J+BC;FbZ8YRbTD*q(v-wu6}5RYemIg&iO`S5rLffWs?CLD<8s|ea_O;4q%eik|65P(5NN)!tN|3#1qgJhR6s=s*f<6mE&As*$4xw zQB@wXpT{L^kCTO0H=b{I+Y+&XcL*=is{7V>_f5ASk))`l3w@xDQ!DPwJJ@gz6G&BE zPfUVvaN4F`JS?di-&-Ms?qOHB(l$XH4Q+e#?HS;~yS%mcvMcl18}a%mKx924RxMe% zE6_4d`f755uG%4VGCe*6A6@chkh$!N)@-of&d%?g`WYOCUe~S}bBO<0Y_7>Aw*8Xf zCwC2K6X5&)yoyEKrg6i3~-sSM-Ekd_}}?4MY}8*nmX?Q&&LCvkbwmvbF|5z#@_I3h*{7j_x++7tLgTj zPpoL5P~`x8{!~_!?Nrnd{#BakOVfJU*}N$Zw#8>bboYw8_L$}#dwD6QC$R#>$)S9p zHcGAl-k_xI#mefK+R7Srd@6J+XRU-wSuF6WzAlOec}cS==c7Hl(_H?Tkl!cTG)ad* z!Wy8!-}?87G4J-1TDD+9dy~U<53P_-(~PwdVtedx@wMy(&*6)|C_I8Wj=VH;5x(+& zuoa$QaweyW?Q62t7HBj~QHf;GfS&7N?Uh_h2t++c8+ogZP>_a>svT7~B?ridPifb2 z3?#5IT3lVycLps=Iwx2*;CRt_Bh{p;+7FqyVd*mQaFMV?G|mD$fOT?_iohS=ew^%5 z#FFq~>qPNK*7sAa*o6$_n|w5R%va>~NzTwoCw^%Ch5^Wk4W>_K|KyHz$!Te#KH1FX z*CRcw%p_(93@di--Di^Z)k4HJWx@H0Ixzem`#VWq{Cj#>b}E0IOyUMQ#tqocCpIM+ z=C>$P8^0Ewn+k~8qQ7WB4f3Ad^k!{633FqFn#Sg!R61H47mYF{nB8R`?*43I5iGbk zIT$2IX_{2Dw2bkE2KUHjK$*sdh*)o1Ne&^8buwrt6=15<`d&-lleFtIr%Wcxd^2y~ zX9nSGud8Hn;7Bp=ud!a+$WPRQFMf~6V8)#MfJssNc(y|4KO5$Z2I81QpLg{yh znP@Pgc})~`gjX_&YwgEm)EjgYGtPo1&dd+W;1_O{`Thuex9uyM z`yBP$X=XQ>u-3M=ptBdHpAAx3S;Ru8a`6roLUR2hh~>m4J ze%*@(+_=AHzDM%>H90>4#`w26yLt2^r!18|e$x@$SwS}gPj*_{eH+^DJib_)b2N4J z=JY#hsebYkRyfX@QTIl0*SswlC_8w`%uEbhUJOLuG_x>rJ|mDircBhIF4|};PJeqm z_IevL<;$1dPlVYuALz3^mdfhGEenMX)BbnN&!FPX0$d1F{6{AdJ?UzMyfSCCLhbw0 z6QqIIvr;U{Zky3}%8S3*9+ZoJQ7FWsGO} zcuScgVh367^4odJNp6JJUty6^@zTnpY`Zjj;>QK`xx`pPm>mW;N~sL9`3qB&%Y zRgbuoNT0us)7>LR|DKe!QKE_ArI;-X7C#P}`-)t&5w$yP9Xml5YCE(BI#aNn&X~jaGk((7dtB`wp%BpN|3!=8>I?L*%CUB=>Uo+H3CUXv;B|O{ z_}>q?)|hS|VFjS8=Ib*gC}ZCM|59%ja>ExS#L4VMx3=7EbZ@1?=@}CVz-cLyjsqm$ zn^94GZm`9k{he&`^UE*0a`XqCG7EGJ#A(;63!6UHay*})& zje3~hzmLVk`h({ZfV*5&GQQKxEU)qd{CG+=nQZ`fh3w88{WojWNE2Foe`WcRF|pY1 zT}P6uW$Vt7377{y`2naNOZsH}r6s+?qiizLpU780fjz4!oQPUVibGa!-XzU$_YP|} z)B5Tw`W+q9B1f(-+5(Q|Bu`tILpDRBY_ulVE!)G9+%bWH42t&fVHtUkjU{f_WUY72 zmHL_yzOUhF8?P8ycMT99S_?}`iLp!TiD7^UQs33rf~!{5j&1Dcml1EdEH`!*k~|m# z-uDcjSC;L1>y-8H(jhv?mM3q9k%X2ffr;%xoooR)0%*q>TK7653hC9(C!#sxvq9me zkEnV+gM}^4HPl_y zD%giqu#7Cd>JK&spgk4~I(#$aB|K%s>esL}JzFin#^~j#yax!-xgt>uK0aj5$=KhhnP zRU(ySI;f+f=#djR=?lm6Arhsol-vSvgfqXG;^1_gM+koW2(3)_J6SpH{ViQ#QlXQe z9Yd<7HZy&!BUA33etVrY^JQ!48$mRdUl(@^4xjlBm3iUE3f`0+LM+3F0iOHt*glIn z8Om-aK4|$-}0R2q{ZU8Gg{PsAIOsWJ)hue5pg!7%u)Qznt#xJT_cjYRUYkFJ zy5BHLsKo4dMfTGN@q<5=L>H-M@AoR+%?G9&Id>M6xvCgOis0Xne9u$mjVem42l2vS9$Lr9j5gvZWtOCIZ80 z`MLkE3GB3H6X|i2rzwcPh}}tyM<$*y6aq$4OEKBmOVy4`4>;o|$R&;_+3_z^A&OQ^ zP!lyu!*wny1 zu|o~tzOso71vQRo7WAgX$FK+hz%r;qDXx}VJ35rx44cSSHt%O&G_*UMxOEF|?*VGOxG+L32SCK&Yr((V(TOne0u{i-yF|c4-vkb&1(d;?H5%u>E^~~u<3Bw<6p&_2H z=!K99DhB_hq8duy`ps>!P0VU?cq;&j<15zB>5T>clv6)lk0`ffd|S@#+`hCIj*a%G zuFW$2j>k%d*Lpq{=H)q}%*CT#Fj6h6;6id@uW^4_#BA*}Z}zm0Wo=fpZ7Up`B zk__uah4;YevzhGqiHW(?Ru8L&$DD~?J!I<`0G!1WELTJ?G)Mzpf52X0WYiYCEh?}4 zu*!2TAs-6=Z8?gq*0nQWN}0skK?2g$Nmq3Uc9VP8Y-m5nq ze^14Puc|>N7Ril(t57tF#eHe=eKSc>U!>rmC#IJnJ`#*2$i)tW9f1E?o8+OHiGf-U zkvFmU`}2Ly^L62yPNp}8qC^2KKQ-PrwDCyWgL z#tZValhStSRZP~=M9z{IXIkyGB9K9s_5=7}^I>XA|A(RUF8T!>eGNTnvJKsyrK?V2LnBLk-mDlvwYT<`sS%#v~9yHc&byrzl3-{F7a8bi55 zN}lONUH|+}SM$Vv#xV=-;r*CVv9UBMO?c({US>xTGUrmbjG)fVe=+#{lK!?I;iSnb zDbYY$=j_au_3h(l5}}c0Al?IZO^x>5^|L%bGK z_JI*3-lA6+`=}8|kbj7H()(UNR=!v5$O{vewP12OaudW!R~>ItbOOwfBjRWX#EtBP z@XVdVUBVa7MzB3{qcz3x0AvBcTb*f*Cxh`>2z-c3+9MF_hAGQK;faP_YA7r>R@wg$ zd^k*C`qWEU(^p;`}$@>^5hNba5a(qp`#7NdGRxb7Y&XrB&zKvAg&W?*G z_9+xY6PxEH46y>uVh+-K6!znX++PZst?UX*(+eeZtR(;8D25O@5BA zGn!E|+{Wh5FVtreD@Uqw39C*RP;_f~%g&u$Mo^mvuZXs8nCFIJbXyL9Qr9S|rG-G7 zNe#NhQH@LdGhci*3OETT7_DPY0t#sMj^FrMsj?=v3EkH@W5-? zq00?|f{!%DTBc8B+Qb@a)Q>?A zhkO_JpWcgJMLteDV}KM|sBYwFANvxOH3Fbr25wRx3WNx%3LyDI}r`zwjQ3w=}t z0u3^E{^pH4Jt&$L?svc^FsGKe0{;h%T;3dg%cIy-Xt?@E^mD@pIVhYUMq};>G^C{7 zd9|T?vUyJ*JGmYibxkQCkQv2LKb!GytbKLc3=ImRYW-rxlis2h$cfRGU%O+}eE{2> z7p|GxeIEIp+0BpgFCw@>R6`r_ySSP9`Q9CLQN_xx!zxrDK+Krdy)I@2mZ=#y=&S!4 zd<<$=*R1UbV%Cmec-Kujv+u8%4)bnf^VGtjnvc zH!6&=0&)g_tlDOQh^^6%VGsGl!9Yaw^#i_!{~^Xd5Sr`<1QY2oaXSnXSe7^e0q8*d zfc7TO)0QVYzT~wmrnsXJ7Jk%4DZ}k@x_OyI?6%}8lY{y;3_zL0zpd7QC9?0 zizl@aO^PRVXXrlTDOel1ITnk>c1lR8k+hDtR75k>RW-Bg&PN>;vB3Q{+tC2xB8pjb z_pX6Tf5`5^OW__nKEe@{!*dToM~blDpu!pk6c?sYhFM3lRA0Ge=o1S36aNhz*@WBl z&-u*4LbaWMbN_fMp8e@aqykCY$bkyzWEn1{p8(iOjLWf`mH!VPNhnkDo?j!wE|@uxGa(%2(-VE1VQBYbs=Z9#|QEc`q&&NGGP{iqmvzKa?4_ zw^a9ymS~h$(rgpGzJT-x0<6+L0s#tD`QM=bpuDiztpFHq~|d<37aZ13c`MMbU`Ts&t?bM=Ms{5cTGWAB$OX2>DcemTk#Fr8V&D%OZi91(R zWHj(0xaY`Er~V06R^fEwG?Bj3e$e*LZ>qbbH&fM)LMn4Gf<~Yn7dFFc8MI%s0M#CY4gsDW10^xm=_-!eJs%{)$7)^=eY(f=IbUxVZi zHApm;P#alky$~I6@O4}l%8m+_4hgZeO&MPwOc$d91Oly%_kwa&ildQO*y+MdQ#5nl zAq>JP9>G!fvd`swl8}s?ZEgATA+@Dc9)YQjYDuu;r92S{Q(e5M%f#O5sZd01mBJ?o zgI!!$awyWWQf{}kWeXP+J^Kq(F4z!7qutN(33`S;YDc(;Z>an6ngJ9ol^T(XiKF?f z4UstXLTYABtX&Cw1xsk7>fG8kG&a#^J)&>ed0>>iS1wJ6VnVi6WoRg2k{T!_r(s89 zr=N*bh!3LAbZ?5{j{38CdI{P%45?ZUp0s2X&=p8uMX0&KXxOk>kUwQ3{CkIl%0}?{ zxzwf%_G!WG-!567Hm*V`qN=p!2|eqbsq0PeB9%)pPzB(OhQVE35of20HxrLePrlKy zGAgzPDvVF6qKy{qBToR1@TqUYx=N5SSS0TZTqTO+en(~qNb9q+Qvy>lJ{3q``soKJ zVwm{%K&5uDtv2bgJ`&f6Qy?W~+Lm*Sy8aEi2cxikk)aE(u1at% zQdl7I^l{kgY3NvS*s7%HF7b$YahT2rLBh|Km_8eLM{IeEy(>0WgjGz1RH$V2N4}gk6j;e6^{cNjdMWUn#Ow-!SzT*}lGTurFmSzdioc10vzfH}JEr|Z z8ldAvLhM^BG&&O?tsfnL@$z#Q0hTe<6NRw2n9qmOg!-)Ri&bSCaz*Ym)+cO@=T`>Z zk2t(lb9T7G1Sw}VJ1`SfYevwQrs6;LyT7u)_|xPfR)pdU(*reLtvqv}l()!V(z-`q z1MU;MoO_?2n|;%x&`>4p3s;NpdkY%BShQ(I(mN;qOJ?QAoZk~8hgn(zr9q8E)qK{H zxTyrD7T3D-2MMO>o(Zci9JS)fCFn_O>$)u8O83rTn3irtV-kRdO z`p#H3*X|M&wZ)v(jvlOUI!vC0koL*@klFeg3il7N>-^ zT1^?4*VaG3syu%u88Dh;q^bm`a8M@MD)5T@UCKucQ!yp2^PZA09Wj{Jvg-aP%9X40 zfT3NH6Cu^vur*>LFtrUuZfKSHx)BMQ&9Ve^#R8{#B&F|!XkcmvH@Klle9$o7k0vapaHh>|U;*Na z;+@>jc4|1#RNi-LaG60T1*xJB5SU(9=zn=f`RpGC)cBJ+g=~__|K>qcshj%W5Y@7= zV5;gCzAaF6*QbGx?!u_^cGCw_jbFlWnWJXJlsQSb?kk|PI;S7?n2Kv&T<4FZeh~?D zRxug`LkV5|fYk~|?)d6^z zE&QPXO@F=}dP~V**uT0WWCDn?NN7Lcnn(|YN)fKp;Xm7pJzkQm>q$?6zBuaQi<%WJ z$c7!&cqN41-+QSWy%b_-zL6RYFciDtoHM@Ctbq~X;~!_5kh>$%!V`vxiS{=F)&jYNflh?4k*Kc9GZp3$V z%5v$xPtLxdDj%bY!u|{=I!$@~L5(|KE-|x5*R$IAx(*`86xW*Yt@IB^c0Hh5mF!y| zEp^qnNyh%o%=HQcMMIEtUH%~JzeublFHiQFS|fDF`KFZBIQb^nE1<%f?8WhuLpmKO z)dL;BJz`l7hLW=!SeyJ&xu&jcS*rjhXqJ+#hJ?27gri0fpmRElDeBsZ9fSl+JD(0r zii?<0_~Gc)*p;B56!m_*p8!e(kVp-Hr!b;(jQh{b$3dhvH!a zIQEjFdUF-D!|*C5)G7=ra1Qpm{IdAV#KrsP&N*{@heC^J^IhbzA*)N&G#@odTc<3c zxF|YZHPH|y&VOCwBL(e`aNC3{^Yp3Ljy9$pWUG|%bIdGM<6y7Ap#}>68?aGrs08cRxEjhS&OmN*_LA8IU)X1Nj^_@uDw&PF zq3m=HaiG=KZ~i;oGt-1w>ecQd^1)29$<;C8y0q`sL9KN8*6byajPVU~l`uF)n~r?j z%${~W#wZ8?84_NkihW{rZEuuoMAH=6Y_heb&t^=3uihxQx5O6?+Z-ut&+Y5`?f^^+Nu{kL(+SeklGr-K%0*){!g zRHbPM=BzA8zQ6vjl#O6TsVfWPOhcNvgVRGPaoF+_W#LRg1Rz4^Ai6}VETV+ZMoV5Jr>b*OmD*53*G2`-dZCel<1n zb;!aVR3F$u>R2rZY+KLUN$Y;$MB{M&qgDBt_+n@^FvdN?PGNjG49aUmMNTtw{JiRn zG^^TwW4>Okup}8T>j)b0uqHk0d`VcEHrFr>0g_E^T;|OrqAfL}T72gD(1>xoxn5EG z>!%^&U5?|*!+H&9)V`({UPUy#G*1u6LtX8$s7qpvZ8Rj5?BsFMYpc=;oYkb3xcsxz z2p(&F0~r|_ME_v%pucHz3d*r|Ot69~lBXIr+i#BHOxhW^dFxhxaG6p%S@(~Yu%+R2__1H9JVTjG~VyW8>S>djK6tkB{!{k4Dl zaj)!|uPugjx{B^k>Lna5K4Ua*_z73HZ__+)=6ISaG`)|ws~lX}$t+SK<|JPzb;BAN z`7~AkHK7zvao@4$TF*gZ>~>0Z&2Jaw%VuQ%iP1B5!X`H{9<|IRDrh0(hB0kh?0E4l zp(IA&d=fs8on9A_j5uK^bfxVh3SmlVKY~7KvDaR)C;O|Qr?IA5xfd3rWCgF-)Ls^` zhM?wl@xg2O;-*2Q3ciEnb0mfNfX-IsdRS?m7plf-#KqZH*NevkViSc?iPcFJNKN2m zuOQAOQLs2Y-h5>s{#!sGyuk6o)-{(^!dxsLK@2-WKLxu0DpkC)W-!(LLk<;Dq-Cbs{0 zok0S(CeTGeAp08v&T@pftc{Z&EIiz3V;laY@%;tE%8^_3HE+J#qC(kZhgNy!MuXk^ z9kJ;60nsi-JT$2C8a5RC$xZ?}Y#B=V@Go#qjm87Ad7o@R?gUw9=Qjcp2j){(RKEh8 z^CpMns*o%2yAy^n(~5fZBf@OQoVWMzDRs_!N~9fkj8r;;?(k})wLqV6ECm>6bEtV@tx^PY)w1FvBHT1+{WGWs6w zUAAK0wu*#BPypG$n^6b>?{ws!D?`wnt6}f6im0@+7FG$4W$(HV0>J?L-oSC5T$WK}$9PS2&>&iq$Z>JP>MWU##>rnc-YYP4pc?I6}doTwK7m z@%#sUegRy?*E^CQKblOZtZKHx77w3vx}0&82J)R zb-Yk3plg|_6ybxzQKhU#M!`p(H$roVZgh+_Vv{{g7K)qs$Ak660#A;Eqm%t=@||Q4 zgxm1h<#9DTuMzmh7kl0Pc>o`T#i{9?)^3sD98_g5yU*G@Z|;>034IA<9ROY&zKg$A zqCJ8Gko#7wfbGqig2^Kp-#xtNr;)${bzaPF?=AA@zn9Kl=MS>AzsEoN>amkO^%<#R z`HPSlKi!|Il$hNe2ZHpD8MfS4>pVx0y}W10^#g_+ofdDBYqtWYYLS1!HXVKTx*zdO z^mwgmd0T8Q^ncOwGP5AGv**^nUvbrT9P6uj^8!ppF%E4SWx^ZHBCOr76SJF~a6RuX z-ho$sNqP}e8;f7I zJk5v)o44=CeEv2Q%(daLGOtBdk{yPZ-q%`8AkEW#O(fH5$2yZ3Nvqjvm7ZvM&$x00ir45HVi z_SL6bz2wP#nJOJ_zqazac=csdXvafJ_)F^*p>Lh~-cOO< zs3=~6AZn~SE9(6(opiU!2f65}emJJ=BH#_~liGH^_*4*xK5geRW{^Ud8nI}y{ry*^ z8|~(&cegcq(Xg4lEjN$Ii6gh{);oLmXD1R&hP9e&SGd9$TKewfNFRSvTCEKbRI?7{ zO5&aXuCUdQk)1Zm+|ntN*`43jep`3o(;hIrEZHfKp(W3GnN!YkC(Dj#D*Usz{nqfY zMA;0SoJc?j#T?fld64OQ5x+t}b1lxEqw!6qKZ-%u!q} zuVxxuMP45d0(XkyR_jc(_}5C#4##D3zBs5nPZOeEXrA_N(+E;vM{I)#TSs|DbmUu( zBj#5@iw@w?&~PHqiic?Jmn>kM}M(@6aX;7sH}Gw>|8-G|Ga zo{~S-QGf(wS!!|)e)NYGXcp8`9%MG6qPDf=L)FHGksn05#B8@m&JVI83K`yfi}?KH zS=dnx9WXeAqG*c&cP=OjDiRBk8TYrXlyx45K24%<-N^0n99`Kn_kNX&2_>dqoFJZE zaU)^NaucI{8oYjhuAD5@4GquvtM+EFNu=q}A9FD&JFKL_I3wHcyR6z->Rod2)uGa_V~k^Q3?4z?)dZ!N!q`dY z-B@Xu4*vVnF~o=}R39^xkTiVZ*)MZjHa7U)ahQ>6Xz?;;rlG&!m78N;B%2ED`mltq zw_v@trUD0kON!v^)AsfZ>KeF_?0Dm$RzwgAB!s5A;|0$1O+*s2A@RQKiaZ}|28Nu* zJZM8{J7eIR6j@id@;Fc1}V8b z%d@7o!Z)d*Btkjs^LEicC|V3ISrM?yz7rzz3NpxgePuXN!hkY#;#+cUl=kZ{yYd&3 zSZf_5u}8JK!r*lP!nY?8*0z=XLwQx9f2#Vn=<&(hT=<)Cc}-u!I|=x0X_8RU{4VbD zwtGGAE;IUk16)Wiu~T6ZdJ=x8*6b{HKM`MJJD5DRpx4WMz&>t}my7%ggOWT0<5()} zwf17SCNO&MA~R0`oPPU}ZyYDR$@_?Pee@5{5Ll=7bE&7225Gd0&MkZi+1Xb{kyGq}tYdCT z%IcA>oEDPE`tqZ-b5&;Jn49nSEE>j^-?DT~960oqoKnjXqy&4BVSkK6`vvRzoijjy z>~Ux=ozn^}*ZWp_&3zpwJ>KJ8gI!Sv@r`XiYWwGh{UDjppFsUxi`MBGQ;Q)Pcg0n(PN%8$8Hv0gC?=)mGEZ5wp`v8Y#w^j;qp)jYQq;n|QM2HeIMub6U%JbS zzt`*L6!?wi5poiUUvM`5R9LY~<$ULo3(U2W6$B*oWCvlIA+v9{30{!2vrKru@(V$h zz%4Cog!IcZbd16X0fg7S(;cM*@JkW>^+?^Qw)iZ;4@aBZjasjLHS4bX&%_C$7o;SH z?IiA+w5GoYP4_?HZ}@|$?SAoWWk*RCxGtCkIwR8B z=qYY-@xjFIHE>!9*>t^nAXYU3kT~9^@=!R-X*zZA&p`Hw<27sgda?;fHaYz~Puu!XVwB}7~bN$$Ni^t64q?(@dT`S~k9 zuR>}B0fUUA-nXNiQ^tXhZu&yrbeESgTTDg~4|&Y8p)AN5YAk;DgN$C_RQx*gIhK~g zJdILWO}RG92*P?AT;qWbEjG`ytouz{KtW4#H3G}YMlAxX$OF0v+sl#dOcU5&Nao4+ zoO#@!gDj`I$e?agDEnqWyQ>m^)E*cKnp0kR%JF3hY1M=&UWO~&)umD}6_^h3eJUm*6=-+L}4hdBAvHTD~s7xfy~&w!L!V#JP?SZvij%9dBpEUXO=wJ)B1_ z`kV|p@)ms?xX6&(r}OPoEh7*otAEs(LlyxRC%i)GJ0Etxfm)AI zI>(`g7nfZCN1(~}4pYgUjM;9zooLlQtmQTuro~>_9B%>?*Q^hu(nLdXP60+%*7@4 zjepW+ER~YNUPi?Bw$34K)vuZ;1ER-j+CG}e#7j9SkR(aWTA+{1&ZN^1$6oht&*nQF z6}LDn@Oez4$|$6u<&cs-8}^*2;cx$_pzQ-q!jELgE;+*4e3ly_j4tRyO0+gvj4-UG z%wP{^JBX@QIWRM{L77c;`GWNoW-;Ubx;LGR?ma2#HNtz&aFyK1kXSyc`umu{y`DLX zh{Y6OhL(ODvP^u>G)P}N_Qmt~f<=DLC*qFiRZ=rZeA`D!R#cV;jv=k znm7WaEW5Ft2)qUY!GO}A_a9IQxlz-y(_$vucnEf`oCZEGnz-pIhi@a zL4b~TABZgBgCffB2$bLji!gc-+%U;-)A>m7@!jjAWjO=-%d& ziN=N7XQ(e4pkX~x7a1jVl{@zjb_B|P2%)C=NOPLOfAtoJtr=>y8C?46Lb(g(qy9(S z^RQnK6FK1dcI~;w?|c7^Q}0in-<4%03Z|S=?DM{c{=d&al%49=Q18!pK#}{ULRBhE zR282kMCzNrW{cZ8!m2V2FX3V~wc6^s4PgP2ki77kGJ5E)K zNW|PA^DsADN@+EJ)0#KQ`QIfN8Ot-% z(q%~+i%}yJ{LtOmh%xiC{8@zSht}39TydG}W1<=xLbE{*Jf}~TV|DMFa0edec^iq= ze#W-rufFrw-zadrM)3vA#oA3(h#qkt`HNyMz%d-#uB~;hrw&XjYwxmDLdlb5w&6Ly zs`}<50a#aKB<(A!4q+jy=Qy8OB!rg6_kJkGlrlEBDOr^sdRYljCxQF-FGI;bR;5n; z7O1+YgZzr|kB{dV1-rCCK6i>7HxT{xnO`0vnjNTqubT({83261L9U?oGV#YwLPEMI z6{Iy4YrtSPaM$p<4$GkvaDBD^X4gayvD0%XZ7@sA zb#(;0!Tjs@C5Cxmv)EzfxGxeRj*5wO za=xX`;T6fRfW9YHzR}CwGr{YW?b+Ld>g?$XtAVzZe5{|SYR2TT@vE~*7a=oqm3EyI zZxhKGXwtyF1(M6iF8wvE)Ucvo!*jfUDVu;w+pX4f9-Mc_9J-fu*aFGs`Zf+-(pey(m<=?8$b>mWNIrEX{w*a$n#l7pDF-14F!2 z^%kM3k;{~H!wYX`Cp|c>urPw-ivEt9Q#zvW!CuMedxE!6nWK-oCXeyULSNa@1!W-J zs%6yxZG~??I&qNmAyK8aQG~0b0Q_dVHAac@=s>L!G6S#UP*Kg9D+g>v-T8qcM}A5-C;fdEwnSY1V(kUVas%d zlm%1Mz#uwfMka8JA9xlum6K&&`{@hu5Ptv2n>|WNAY>>yXdnca@OozY?A3z)rssrl zqYT)|Ab9S6%ZiKWN)FA*JMW*Q@xE&RC(urn^a^I2NiX?JwdQr~#pSpbUAq5+(qie8 zQjBBo*i}rO^@Cvtzaw!|Dj%Emd?F(?3iTm`#%W?AbE#=VRLc9BH@8oER+7?Lm`9m8OT2yViF4K&q9$K zQ;-sOfGLF0m5XVam)b2&H+FwYhni~+ChF_^8safkN*HQ7 z;Ky(d4Vm4-NhXq-ZBffBJMMnT->r~ffy>PuF7BDbZ^a>yGC&e?=dDqsdI5HL8(eCT zI~s}#f9I{q>l)5l3@ziW8RLKVuReh)DL~?X3f=#IZ0^`%YbrNmD<^zK{7+5Y?|xSg zqhYC2=aL#$)VadfA2uq|EBgNxeNp^#Pa!OI4h;HTZsFB=$gXb8IIHw+6fbIbyyx6; zpy?0swE0&uS!fv!s-*hpfTt?4ghg0@?>BB)8}7W#1Rp(0kzYRO18wNWJU(oro~SGn zUD={AxnOtG(+G1~(DNIWM>F18}S7(KBxl)c2i0lrDAX8WmtS z!F-X$MEl~a)wCbybw649-RI0=_%jRg#R*P#f{>0NogyI+ zaCq7bBb;+{e_dq->5p+V?cHho8$B^F{T|XeN#K^^A20gm%0lrGk6e%(#^K4Nn+f6ifeyKXt=O;=1p8*>XGT0Qc#Mgk|3m?_1Qv9%75#f_i_tyF#JJ zj@{7YDR;WhnB&EC=pFdTPw@5fNw&78z;~T$Q~#L^f7HWX%scsW6uD5@TK)TD1-(=! z0AzmW4}3tdCodO0W@&njPhe6q$is{GhogO8qvv|WQ=mWN$+6+U6|x8D7Yf}vq{yz1 zLg;CSq!J}N;&iFqhx4PsrJ~UFwB-0%pT<{suotUs5+%JsI}Ut@^!=$M`c8GlRo&lT zvb6<;lFKWwJk?A-d*7a)I>XAo;osc}*jp?$kA)Kl$Pew23tc?rnW|f&Y|?zsrhB2O zv@;~ubn8sGQ#b$};e;Awb&_7)vGx@HNK@tOiB@JzG!_JGj<%v%N;=ld8lLDu@Lpf! zksThES=kuI3Z(?6SLT5Qd3R(%4 zj{TG%deOX4*i1lYVb|B6U&?lJ<8=X%K}ZrZs#GMk+IvRF20Zi3S%dsdbV}K+N2Gg? z(l@t-Ba&V&v@zPx9r3ACH?1JOf>hSpXBwFiv z6ma`GD$#IvX?I~cBZTDhR@LE&+4;x|sHd7W!T31=OP8$}#WWXQ@mPY&J1aNL`F{zD zSKqzg!i<3Kt|HV%BX=Q?*Ex~9=cWSrN+k+9Krb?i&=4QkyUBtk} zx`+PO#-`_t*Jt)7I)r?E@9@Hm2SI>V6=fJuH#`EFjNM!uXKQp7+`VcC48H|=lfHPt ze7v7`1&&wh$sWHgvpuEQedMhsr~tgEHo$CDMHtjaeR3Y30}G6%9~CJ*C~p@McV_Tx z>A#oG_xugtb~0X`x-W{L@DD2_?0o+)8K+lBIPQT#=8ebBpNqrIj^}V4Kwgk{RQWSq z3{#tV37bm1Mi4F8qU!0k_=YK~A^&UJ;JfRN-f8s^kFyHNwfxt!ljJRX|8z6eIPe*1 zinSFjB{cnSrYmA#zEl^e9rY!>12aXMssu}|CoL(EFAQgs$b)+GkF1}_gU{>T$BiOi z<6yf5)(RkVCZM2?} z_CCuPxcD1o+M`s3rP$hxl52ZUwl|XO4~4=hNnFCtho*$Tu@F%4bi8n_ts3{+QGzq_ zpOD*yJwA|2Uat>%_ukjHj)X8apPU)ho<1GZL92G0{Y)zvd6+s^Z1j?R$N0pZAH#RW z?hB&WD&&IBRz106#1OxV3zXk4MzMWd#n8||+*^SWwLaXx`Rg(G+_S0_whM#iFnQpP zF^8%cAp+dU655~i$-kus92H^{P|Xp@CF9v2jaP^?FNT%aWN!HBy!?W=qz|cw?DX#Q z8k$Uyu(6m3l~|DzM@L7JATCOW2lpl%ik;69ZS3WoaT+?7C0B{3d5yY7tG@8B>8W7x z(i>L9q88PeA6;d89x0E!{6IZiK2&nZde=wR)0?Q?-GlT+M~7t1_W?)fd}Fq( zk!uaqNZ7oeWSeP3UHHb9mz>3IVOLm$$5huFfYfi9HJQrhKI2SWYN>PrSmM3WEn29< znM-0%5_bLY!et#g+?NlH>>C?z$X5EIY~DG?ik)TOpZ_-^H=hFU@r%$KkD=qhY06XY zqpG}><$FllK+H74Lp?MGO4UOJ(hkr9!YRs$XP<^~#!5!rZ<-X@PMWEVbzP&d4GQ?= z(z(gz_1q|IAJ!-uVFjv8a0Apbz01_xClMWa_KfyhB6rwN#Ey>Jfxia@?oV`}2g0>w z%TDamJ1irw6+hf)fp_c8H`=b&ww{veh_MHFTT$!C@p z1mMffmtNwYK1C#XCW(H`F2xr(>qs&T!}m7q%)q{tvW2iC{Ds-7*X33?tdQyjorNj% z2Z@U`l>^DC*Ul|5;c7_!iwC}9dll|;lF-VW0_?tZf;dWev|{>x!=a}3Thh>lr}u=r(0;iK z9pZ9}I+@(jHA*(r>DIBGLgo&p^IG}}s>~M3GvON)kUq349b3qc3dDv{U@NPvV6AgW znQ&6l8QPH9pYFC20fkl!95#(_ti$HJ=4>p7f_uxHotu_7t`Wy{2T_e|G^4<)FT|us zpdcwKI0en_0He-3TOIBMUpDMVtg`_t>^1)u-)ma$c31Q@&j&-M)#mM+$N|RY=Ffowy_ax4cD`FcK zq3fvtg=!=Y0@}c*5@Wpf1rHSG-gKMYJNrf7@K$^B=FGt=Vgb*8cpzGlmplpc#yxw8 znTG!H=^AYrcHt9G2jRr{r*KnfRb4Upu)4KKs!E2NK5aZ1q2U@5t?$Ev9UD6@y|}&C z_ZlmLxs#HCqSWVr-Qm4$eQ>^A;?o;m5FgTXdFv~b!A44>L59WK;MYFCaXVu?8#DTM zlngD5p6-E~_7`3z@P(WK&umMhqZvyJ=Ofi`xa+ZI3$EIY=E}{Tt~b1&TnK(HcDMcH zW_TG;)p+;_9GLkSQaPWH4N_{i+105uYQQ!Q!q_kj*%3czNS#;v6hU|_s2LQAgx(Ik zL?%v~9f+Md61~3}HCLePjWcW_*5x9m9@g(~(a~$%za0L)0Sqn#J-!BCX@U)Yl(wLh5rRGcyg`UhJ+pDp@)CHP2o6PL3{!HSY_MM)=>}!$edc!wXyaEd zmAdQ{?X9=zOKU=}bnimG^VT6TU2*3v&-_DgYpZ|B&af&FXRG_mZ9O^YWY-hE)1GN4 z?H$FcxX&EyI=|gRpuXsgDgKLR1|%^X%ss4xTSAx z;>Ar&1EM()qBE^vywWF>YE^g_kiq*(jkE3=ML?h%P%|J3c>m6Z9lA9SY(b)*yiE1; zp@xqhK{R1&1DYzn#4U47+XE)AvV6L7_78S!=Tn)KqB=KRa>OaW>2?>0U0kiTYTkHE zS9BMR(5XVakgJO9?PTM`eL=lknD7x^WzNBHB}kO5l9 zt)QA{l_2>-wGA&z%Z@koo^;CclGd(}w7m3&;31=LApuV&suGUT`-_F;iM@$W005Fe z1)e-)t3Z^2lLnyV{h8Lfm8w2cVgHk{r?<--c1s-sPY{^^%|FcAf~|p?;>2y{cBeZv zcwGLSx5%tz^44rS_gt0Y14D{Q`gn%{@(ZVDyREMlMHgEyPxzQMr~TumyD%-JSMv8F zBzm*ZV%8DE^h=*)6$;g{4fA{K@4$zPTd!kto0=-}I2JTODM8@EJJ7m4l#I0y`rKVB zR&kM)n~Sbg%p!@YCk1AznG^m|Q#sO__FIPdxS4#!p}NtEl@BBdIl3 zy1P^1d}R`kjp?)c*v)?+)mKMnG{!-akTG(9S=$%xc42P)e}M>Z6KO;0|Kcj*Q;Ppz zUwSil4=q~sHACw5?ddz#=>Gi>Mj;$R zgSa{)CcJx+3TRn6F}L{a)Ol*3-6OJmMeKBH?|s{fk)-+8)Tw*hB{!n5rsmRrXw*gn z7L>sFKLvX+pQ2oPW&Jgf;I)$T$j4a7_14P~!z}#zAqR*J=wYB|j8Z(wt*H6k&SMwD zXLKq<`EFvkQ2;V_yLRaMlLZY{d(B&&7^yA4(i$zA1Sn7zVe@s%=t>hxJF z&7R^~n@4t1$8s3X(WjD77LwWAY_zFcE*u?qOF1=kbD8o{`WWz>w)nh7vP?IxZT1kT zSdLIH4Lb3oSeWB+CdPGu3KMOwEe~Y7ZnIdI)Mgva1FWqg`|Qq=BY-cKgyp0J<1k#% zoWHW_zgX9SqQXV^?7-cCBo)oxzy|>iG$@E2H`XzCQoEJvw(XN?*-cwBzCKN4KhSQ( zFj@C*e^EjRp17zD-^JFkU#u|OP7~r>-s>BqF1gGznypO!J+uQfWj=7K)iC3>6^do!!XedjH@mG{oU zXl**_29MQCy1M^F%UxD-2$K7nC-LP7UZ+odWD(tQaOUqb#^v%o)~~_}OR2tSIm7lF zgh~d<`Zv-EujskDU(<*a|K4|`H>~N3igYEqgIs7cZyEJIe_3bR5q@osXdY3s2O+Hk zhgTA7#soWzO#|PIxhUyNQ0ifH5~?_!HOasu1^~}n92`lO5;!F`PsM7O&Ft3V;f)x9 zW@S$#`}UN9A@X-Kt`8X@3=h1V+M0mZWtN(`lOGe}Wld*} z5@%(7+vAX4aEE!9$$EOou#`9>{eS7LXlVsjg>@Nn2&Duk?M5~-OIL0O(K@t z{;2AI7_iq4Q;6f}BKPn8$@{;W_5cz696_yDhVZ{knd6+;I#NBc0!ZsW(|%D7e9rd3 z`f@$gmeunAjR5}x$c$P(=;Sr(A3D0uE;iy_8lE$T4Y5v4&CEc}O#gkZ_?;Y@^ynar zUF{`4_KjoVROy2GuZbJi-KHnvW?p2Mp-3ME8BulGHG{>Fv85gU`(+2U&@6ts>Im{^ zSoeY%Gka3wE3zl&vaFv>orVI`tYjJM%O1#&h}sYkn*ZRNi73<~ZVzDhW~b{L94)EY z3+yO<`Y%W5Sntqy!S;Ia#13l)N$SY)bI273Pe{<|bSz%ARDL4RR&x9&m8k6(-7?Y$ zxn0*4>Ot_#($9K?U|wx@7b7I+`qhO>xUr_7V0_xo)uqUSf`Xqe3%x4ykH6+Edc0Vl zF<*nY34n&M_)Up}rQ7q~u*~cphr`P)Jm3qqV7t` z&^1lSDzLP?$$!E?TBc!jpbb9>A#y0ny~X~@eYD<($I2vGii?%cdcRqpy=pnYYx2Bw zwEuH;b-C?>FP}h4{88fd-xtOXWQx(ln=GvpTWY_ZANC6^k(c1{v7g1doggD{Z zvT%L-HRTxdKjp!Ld*34#==w6wslFS>wVFnPU)-!4t!7WR=-u4--wjhVY>v7FDU_nS zo3}MDSyj4DyDmgI8Z~H~c7?j+qqu1cKK|*j=vi)jYH+eop<;=I6qDNtIZ$Q1r0ETJ zPpH=*L_Hl~-#wjyqaIJ;)N61fjay#_9-{*tr}IMO{Rc@`Y}@7?Bls?a+3-+Nr}K9hD-zek>i1mJ)`EtkgfroI9e4Lp7lnn;obso?Bs7`JfqgGe z*rZ6her6zd9B{K6A;9a9`nUu$8Nyk(y`&F+^O7Mp-@xyFr?KAmM+uMp5w65WFY{#} zXnxV}HUmy=+i}EuH$Jf3{k$${>9&~+O)%b}0QWeJ3;h~~m7H&-N$g{28SYPC#F8Td zNg?u@_IC&)%wRmPSKq;H%uvR{>5!*c%>B)5I+}+b?1v=*3rZ{%$Vm4X|8(H_~`V z_yd!;C~iXVO2*+p>TLVzc6|W3^ft8E{f55Lec3XOawS9&@JRkT{9?l2HL&e(7!6(w zWj0p<2c~Y`E>{^(YriV4rLzsAAgHAYHsV^dex1G=XAlv4#7_Sdz0%4J|66vuHD%R$ zWZ?X{qq=uDto7x9s8z^J2NR$VM+~)Ms63AK(Dcg6P|hj#Mh4_KQ!$^YuYZrEQ(R13 z2l*3ZGIc(}W-i}lUzED4R;MsrNX1P*{Sq1G$@FPQldt~_v`A~$WP=4RZ!Df;t?6jJ zn$Tkj%!;m6jIWvv{GOMNOr}C3?QX5xRRy z4#seLx~&oE-Fy3(m4xsx3&~p%6@Oq*8dxGB>_A^mWR9XNk{en0A z0lpUk-WJT=ieI4QBd?SwG(O%CH^;>JOU8~bA2E9#7+kpx@QtA~e{T~kDfxqADMz-l z^3sPTPg=Lm&DG#OgZ12Y@MS}8H3-$;XmaU5;<^hzEzuiO(i9tL{OW!3`h#()t;_Pc z_4*rP<Ol zGNtE}tn(zYELF=-pBs)f-9}VO`ST5a0j$m6w9kQcL-@+(Nq|kE=T60oiM0DHY^Je( z1o!(2x6N&c%he>34pCdcx-jhHq2TJdhh?RA7ekR)RRm_%@WMZ`oU}na-ao-Yk2p&U zw4ZY)|M6GC-VYzSGGFb$SA;uZ-OMabYQpbd8r-PPmEsN%2EaNo)}9~V$9%^_L2cv3 z`IGa(RSA2tCL{Ek>9(VW=ok|n&4~5Gx7an*w%avj85Gn58{Wm$cEOV@$^6<66JNwB z7(=v1;pKhbjevf?f-#uwU8Os$mXb{wOG{{Nzgp zS$69kmzo`5F-rw+sfs-N^&-~ime&E^L@+T)XY}PjF67oP$Vz3+a7gqNYMTA>ikqSK zq9{*?dWFAAc--CLE}kWk4mt+$o(8;_*E$a3JZ2Ukw@8kFVPs+PalrgUo`lX#B9E!O zD3e3_S(emUyL+>)C-@Ud$(51%n3sfY}^a<}y6URA;~{I5HHWrR%U7AK+hgy46=nB74rj}PdS4(-7ul`UX)+vs^cjvw2nbM$-nvK?>o$> z43m~B7<;Ods|+~3c;{*}n#XMLY0GzFqdM}|xLGgPTgpGq+=`nx(NB=H9=L8lU12T^ z&fI$`gooHKEUJikj%c?>sp|>+skXt}tH#B$RV=g`P|rJ4=u1oJ-uo4Jbx3%s9m0T2 z11vA961t|fl9xYd`>jl1;C|oFw!gRBSYXHaO~oxnhkR&ue!csoLAX;`qrn-XxBbCo zmAv4XVfWMwWNa1Z(+Cd-=7SmqJ4H9IZ$_BmRH&$|5Y4R(x!YJ%>-Ub#{gfWDZL4cEP zU6tPZZJC}%=_%;bU&hZsQ#YA+CoNoJ8rSaxhT(XHmsjU`TGAMxKErp#M}^r6lwsB2 z?LPyOOFZZwIX?V}I~K*F;Bt^iKiVgsC9#{%!W{R_@NS_3*3o8^ktZtyOH9n|{H{0e_MJ1vEYx(K z6%vGEZt|;5p5Hw`E%XS%SAvd*rDhv9;G8?nMx!0NhzF zT*Yg}HZv3)UlV+MLVGUe=pC1f*6U-uaQ9<+8pvWqK3nXJ4>v?=S44)iBitvdE+f6^ zcFFcmzr-cj4WYaP%H#TU$xJq-t9V;c8KbA-iJyo&TTk?cUxr+6ZS3+`QrAaJwtA|; z$>4=DJmPZ*YS9v7_K?aE$a&(-#ANnzh9xbHbUw3U4EY-3nazbVL5fW&e%qSdEx*bgeJjm?HI5|y`%XQtdm3{5f(=!#VikH4j%alDnyWZ#3`dTjL<$a#R7S{xNt_5@4ecy%TEwBeE<_AeAe zA4@4+e#O4EQG~V@lZkuWG3_!fT1_$b zs@JvfT3g}#QHaH23M10`*HzE>wl8M6d?x%bbpnUS;1`E+3f{>kEn!GBSQ}}b?m=(z z=c0-!o5>gwDHf&pjEpe5fLv0zE0em;?jgA;6SbO#ZfO4Tf*F}d)4ltrz7g(PHSlLbvaMtA~ydv3AJzGp_3{65po6UZepycXMc*!Br0=Z}fDi`be^ zu4$^#DYAOgx7k^w{ZG@Os12}3>M0eDp!S{r=S%B3!{>GPF!pWedDmxu)JuqoaC@|_ z%e1{HT0N)X0p*Y-X`XXPaBxd#sW#E&tVZl$t?Es@`+OW_6jp&kk7VtIjKNgxE-@+3 z-cY&lL?JDk-7Y2RfD27;spp0rM#%1ih|-8)vCwS2Z-=Evc@HmFXp27is1&QPNa0p| z>(vF9W0V`T$Qy>)S@H|J=1KE;L0VBbK!lrojBBmvL}=3EZqj(-gJZ*($>~-;{y=RG z7`9O(Sn(}ZL8sh?r{=-Qr&G?bNj{!`I;86iNd>YiTzO9*^wceH{#2RBA?quED)pgW zrje8HrkF@R=p4>oG;P<=t5_yyWxyvzv5m0Nw zR!V<=MxMtR*<{628hfcwV>$Rp1#4!SF(6XDRTH-(RCU%9B>2cXN0UZu{DWm}p!ST& z{`-m4R)Tv$`IyOhW&6yn#kWLPNlEZM-lGZ!U#%H)EX~-!eXC|H>qkG|FH}PxfSkYk zoP13xjzp>-em37NF_V9j%@x;(@)LWgwwZmkxfCF%c2fD&x5r={fB~vK;1B-UN*$iw zESfJxv+QP5%)?Vc>a%-kNL{K0CI4;=wZD9$jFoJmwe4AJ;>@-0iEy?G=4b5iNw6b2 zZbZo}bvDH)Ft8Hz=%|dxRa94|| z*!y1%joC7}Agwk!L$zxBW0!{ z=3%bpFpVU&1jL0~$MB9A88&B7+N8!bcmY^De2+aqu2{!QKe^dr2%ov@ngawiM}zJk zR(X>e1XK5K5+}2MkT~&v`IDZk0Dlek;Wig5^$g_v+hIO)@M-MNT=Z0>FM?64c5GU- zl(q$_OcP1o3GdWw1+dM?YYXaRy)mMn*j2HfTOl+zx_*6eyQn(NwJlA^KANMelJ$W% zH9T$eM8F zN>nL4koe|F09T1Nv^;%jnn^%hPq*NGhXw8ROnWbPL{_RcV5Wm*%>-30qakf-gBVG7 zE%xVe1pMj=2hC35{LGL==l)Ku80NI<@jOzJ4(TP~+cmWhqvGxXkh8msO^=IiP$T zR8-j2P8*?J2q@TSz4JA3WueU&hwF*&&s3t;%+bDTBuS^Uh&7hW)(#a8!HX@P{F+5C zhlNyMtFhiAvi3X+zuS!((P@vvH`bw~a$t;JBPfZfV5(rw$vK#*;(y$G8NpYps#w$M zj=v4x=r5O_%v3E`WPuLc%nUbBMi;1z$J#C z%ZyREI(AE3*pMpSqcC)~Ih$~)8=3-z^gh2d`_qSUF$O(&Rs3GdR5qT{B*c>GZ13}< zW;<`9f?jj6vm3=oW|6K$A7x2-(Y-_&K}q>=SE-1Xwxp#?fjnZq4xjjEPiM=~T|J#@ zw^3cw(d6-de}0VSGyd{3azARp=o6W~66>PNtcK|LYQ=ml9f1Z5-8Q)}Z3|4C(jl^O zZQJyvVcEZfEIBf%!@ecc7jf+QS89ad<0G!#D$X4rdOJN(KM^-fbB zpd3`IgGb}-GBqvhI~gE(U6paUi!S$5FY~w9isTZR-=X{T7qkL5aTu&5QVe4?TO7!M z41pbOPlw{~iG{CecfOz)cB0gjLugKnQM>*f`Z8MmG;=K@?{#a+Mpl;Wr=qF2lu;(# z*0lCSH#d2H&ZUdGyPZleTSQWfj0KEq3-Z|!?p?*ax4n5bvLugdQGD9#BeScdO{ORx z1Kw|WPa_pz+pb5oEMq`ZSP)o?vxX>Ea5ZP6!guysUL@KcuJu%&g|NJuU@pv~4=cUk zjK+{kyxY04B>GlN#kNZ}n@xSFW{xlTL9N6gGwOuGOet6zN6$XIr6e(%{|)1f6f8pz;}%{gma&d{p3 zmXGB4ud4$ZQJT0bON#6(X`6l)A2}vhjgD-7!X6rS(H!2Cu0rN)NKLN)n7JzRdm##F zqW#}ORCL++#S_v&R^x}62!u?CG*Owy^P7s3-pexhQOnd`G3LLy|6!V(+?E?BK^A2c z?}qr_Wvsn6ezX1Qi%bhDk&~AB$!0W@*WWA_g#zkrNGIEEjJ3JYX#_?@(bvhnT?on) z{N!6;V|QJ7|GCKbM1l?P)EApfw{DjzHOZZ=zKdjLFb79ObnTo-JUzIC1eZk(?#R@b zj_xl)Nc2A2EPNYIuIUq1cP+MJri~-qqX6q?-DtQ{3f3Q+P|K0t^1xhwq+LZeOgk9R z3tcGmto$;9W;MXNwUwEfFGu5zXU1$gN^9cdV^j?Gl-ua7SXhb@cubFe3&see1B|co z;#ECbwyB2{3`M%AA0z*w=l+UG!-IOsKnRp)JwIlyGe#0R9h}XPxyo)LGS4ScG9s3H z500@4$$OSKW@t3&ia5-=xnv9(GUj%wjiWiRtX!6NUJE)VcMy?Ai&9hw$pO}8it&Oc z&Fuj_qL0%@bwuoBvtZ0PLX+rt-vA0kmm;W^q$&b%zJ_IJq2mWnCK%2hyRA|A36P2IX0uz#BcNvgEJ+8h^9sJ|gf7|QWVB}^LId@~K^<(?Z)EHd7egWegRp}~7(l*%o0(q(p&hMh5* z%GgJB#G}*F`VVJy_&m81(Pjhe`z^dAauY+wPSh{a{>Jm_nF}&kBG*Am$=*KGmz1t zM^l15r<&yxncmoNZtWHEaAne405NBBIB-QRhql!PoZ;zA9Pw7J+#)dnO>IwL{hTe+ z8xVM_?}OFTY)8y#hMce@fZt0mBzH}6)9HT|Ssc{b+rcA(L3x2;+#j)-JFox6dH&Ty zT<)uy{(zb$dNS;q&yiGbxKKZQdlqVIw%R+cmGB3uofFem_D6iiIPq>7_-r%7RT+B z28&12b_l~nRTqTTXg7b24ICe-PN9?rC|+>Q`M~;J|zHh5zmsagyViCwiCgd{ zxtkzsb=08pW?dWG0jBFe5$F6;`*jo^z-=iK+>vfwV^t8FF4n^PN2vjEz8*~@EZN*` z@gE^wEL-Ymk{qbF zPhv9Phw0wJqD*=`XJk2bZ}jz#$|nt0Z(wOzZP`YkWK?_{#yq&tKjti`x7<)>&96bC zqk4?-=lEEQCpz)f1*1zB{l*cU69`ULn&uJoq6@8=gH6g(RoX*wpua!3JiS|^c={YP zE2FNIHZ*V7HngCnGnKtlhhAYT(q*T7tlPfcD7ski=AP z+z0*s+@Jkez-VuOjk=ZRP>>_6q}G{{$vOqbP4!aw$2%-p7&dS*3y1I>6W*L@j*flS z-qrh?a<*==^sUaPW-0M@-64Kj)YWFaVhn-NqoXE0v|4md-ZLs1$kMYoq5jI8!rD#Y z$C#R-mH+@VSTWB(<5(EoV|SG*4XW7095%Wf`5hF~!F$vW zs=J%xQ2}2tE|47=6HD{SUnn$ZFRWaYE)z_w86$QM*B~XUTQz$HfAq~i<=9d{&HU#! zN{*y#K{y0zZ`oA7ezx`6knyYy?<}1AIVe6)MrpJ_071EGoL%H6Enz$joZL@emCqL8wy-UWc(P!QAV!XAd}?Y^~JNGxzg zcRBI|=hv><8`e~Q@_M5Q4t5IUdPp3p0? z-RQD_Ag5Uw@)K)*dg?Vh)Ju65vF884;u03LP1xy=7)Ez`Jx#l($SA_qX_%-%GD?qi z|56CGOBKs^w+Ocr5SO+gObTcg+tEKxb)Y~y!1gkx#A~$N6PHk~V3Y~d(>-k{8K_T1 zajmr80oiTE2NUNbcdM>8;@@a_ZBFOAlNHZ1l=3itek<46r5Yy(I$8@Dhi|Gtas`02 zkMM2$quYuDXW~He-N{h} zy&Z3OA!W0F&}kFFt0kgVa^5c%BBwd^_SEJKD@mcgHn){QA71Al2Nj%rnnpQKCiC`U ziGd|CSe?@e{j~&wgN%b48}<0wx0FNjyz9d+t8U!B1x5w%G1seCj)K@3Q|l-pR;z@R z&?HE!i9L+5{77*wWoh^%#MxZJ;!wdcOswhQL8tMl9=Q>Em{4A4MV?ol+7qXjzw$JK zj-dgaXnXNZ`RG6Z=Wy~bHES$zOjBB%z9wn_U*oU2UrY3ltxKqu-pnXL^=G%|4p~bl zgM%LMh$0EkSso5-K;BPc>Lwmj>;-QGyyC0=i9{(b_1CIZS{9*)h;Y%!|u zM6t7?(M{D<4GN`xt-wPS%66JST$hjZHF-{7WTayIqgB=QkVyNSY4VDa#OAE0ZlK?J z1tJY9hML;_BKB841n*q+{GgDLfX@CY@Qa54)7?H?`@b!r^8OuvTq_PkB7TTG2kdrHU|rV>wj+|G?#U7G$U>)Fl?X zAJku|flXh+OEf1L;Yz#;Pv#J;O9#ljN`BvL0saa(JG_oz!kpRrJz(D@9~XEIFpd2HIRvaGU{GLOoO9N@PvzQ=}?zNcb0 zCV8=X?m1g5cb*;x1U`c-EJ*_xJq#@P|cME2l4eQ$B&a*MZt^{m4SF zQ@K*te9k!Kw!UIVZ@1o}YFd|T?Iq=8GZDp=msS%nGwnonA$j#r#!2@ezkHK$2383P z&MM6Gfk)mf53Te0da2=uMw41Oi_%UBtao$qCmn&i;A6DQnzQ+IN}1kZ$rpO=`0bn+ z<9rw^WVRET`1*ht7n2tsY83(;`Ke3&@5t+O&k%(lcKbq z>LVv7*-`Z8g-aNFtxf6M6g+0c6H#@L?Y6l(kCp3>EM8)ZWmQDHLnBi(ONr&ZT_){1 zOj%50FX!eDtv(R^l-JEAJ~}K)dEeqo=f0S|Fl%TSTI6k|s%o75myVww^zlF$pro)% zHY&lUq1QcGM@b@c#31lbumZx}IC=%gWkdrpr!N+jkN|Oqw(m`TL|fxliQxWXW$;t+ z@7jaa)E*ruhuej6sIm5Bhlh-}!@iey6tLo~ zanHsHv|5eKe+-ZiXFnHU)(dhx`D6P|AmNQJJn~Y$R9g8xpyvm)~CmW zhuUA+5%IDwAI1hi_AIc|!gbF3pj!(g&{(UQ#0p>wyy7$v9(;>2MqNdQixx z-B)dmNd#m_+QzfU#M=F|T-D%LR4tZyr6E3cA~$_h8)Vc(tkEM?PEgr7wgC2*f*46> z=|2h!&T9b|Px{Dt1osz8P(hcaKVgbyUur#cQjp`Kqjh#44A1inQ8&eUB$K@}%p}9Zbt21rMi7i`$E5!KMaLguS(=B1JaB z#-?R7f{gy7=%(yuqZyVRhazVZsTuw#j9Q}t&`un|pjhlbF=cNvhp5wrzF}Q1FD#Nf zpX&3_rxMo8ntm#G;4>WcoM64AJBvz{DvfMI;YlxeohfGhV25g4SpNNJ=*MF@^B2AW z(R56N%?RzunfloK)R;lO+SL1LvuNGCQS^expOj@8k9ak6R9^(QKh*Rq8mfRoV5wmA zK+fTL(&TOuzC6}t_0en&9kj(J8MTQ$yeIc|!;?m#xv{dly11gZYNmkRNap1C#Nr;l zIK@HOv8_&sHAEHpjdG)`vPOg5kT^j(u237rSd==cg1_sl3e*(L4=Zw=V`ujsW_0t{ zb`VlpGf!_<+#5SnSUm>Rp|4-Uphn#%BZ_u1{Q<{#rDp*ZCZl2^=&-C@02wm;5Ay;@ z&>-99%}ms%l5*VaTkG&(IsS5{t=L)$l2KgCB2^%%J(wiauW+1Gfd7o5E$=-gQpmK$ zOupKUI#wJsfQEXIGg*j_-$eh&5PA3?=HPk4>EPKHO^eeC&@yxVwG`OEtoJu^OY+K` z2t+MhgJLzG$kXiaU3mCX7Ov{@49PcKw&g-C;>!So`(hZMg={?{<6R$1d@D2Ryqp&z zJkh?v=onZ()6oTgmg4w3I;u9Dv{3W-0U5Virf!CMyNIag(G!Q{)Dr#Z>TbqPWE@L= zfgegsGYXRPhI4RO%agdC+0+&hiCfPPUjUo^^b1F6d}j&Y3a)kbyzB>c1o>qlF(14) zG@aZD8PRDC?+rB#cZUOvj_ym$4WnEOGQXSM)yg}NCk>zZBEjV=ps4!IvP`yU5=%XLM64yZ6Omvv zz9@F0y%;UZuTi#;^9l~{+(S>D-r5fWS#k6#1vR!upcL1AS?6t}tJ9g3;G}x4=|T?J z{JLf}x0qhivT`}Y8O!{dbfX6Qy$PlB>C_u3C7#_k%=>dCelT?_LtE3jac}`?W~{Oy z^@}+T<)(vkFjnat#Ey9s=&P%}c&>WCe&cp|opd+=DYVVydt1$WIbFf2+3rm65O}h` zR)Cs+A3uC;zW$5FM*G#`+xit@ub6uI5YeJ5vuqj>!nMohb!cZjdXXnKpgt32DfNhi zWeR?#R@qLhJj{wGJ8h3zW4}f%H4&s;C*etXJ3&CBTsZu`{0JAacVsEt{#DN~-r4?7 z1DG3Fg8tIFD=WiZzk7kxfP0`Pa#Q7qPat0yIl9REVpcGs*L~PVt?Mz4Vtc%V?*rLw zBs2U`^|@HnriP=9)ua$G@U3Dj;$4BlT?`2UX2#gSGGT8Pc z$9%FF;f8`SiOUMhi#ek4WfMHr8W|E(_O3oN4sdgc>sTFTK2^YIc-UK?;H( zo_?UybdQGS=yYy5k&zHhH2&G_8ABUkV+N|}5#8p7r5}+wl+!1>sDt}gI0~o`W$L$3 zl4lmyFK;nhO=&goGBTo;dT!&zeY?Ig?4dwD+))mRnsve&3Uy*X5;I@_maebHNT`%c zdIXi7sdBuL$~4X|1v*9dReCi0)2LDFHX zU(a?XgTxaO1W%_jOek3xeDiPN>ikn`>gx4w{NAi5$0<&x)$Jucw82Y+>SVF8W+rEn zjKmTsUMmO%kFD|G#)j|VA{{sT)}wwWM6z55LP>(41BstkOF0H zM?1}KK6c#+eVEh}-JWU-I~m;I%oZ$l6bIP$WAc>1xfBr$4{o*ws~Wx_?*GTsik%b$m!ybYEl* z$-oa0>5B^(&dC-qQFl9JC&Q^=$d}wR1>mbC?sIIQYBw7Se*w{Sb$Y%b>K$=r6*K*Y zT&Z($>}f~_585D-S3Ac5y&5g6{h+}XWgS-CStKp*nu*x!fF{H^aR0c zKJ8?@zkZVB@CDSO@9R_n6cZXE%ud=up6=ahx4x$_2UDeL=(YBRJ>B7qiNLv@$l%my z?lo$L14F&`mm}Ai;=&Bw$xd4O+=2!yxj0^*73E8;LRELk7-k2J_B-gASjeT6jal5K z9`?4pX^%cHsCeEs)_e?MmGTbHJ{KkCyu#@9dZa&jSZV2o+?_Ait0@%Zo@3#h59}Bb zahhU+MH~pRSo_7N$=(tYWekQW|QYTBHnE&M;R+RGkgM`zA=Nn6dO|E1xLEkn1El%q8vWS z@lq=kKoALdDu*xQgy6_=1pJp1LI%#~9OyQhr*l7>FA}Ktyp)J7Tqb9N3 zkum(>)$oH0-paU__aP=7&BLQ8YafOpT!O5U!Xbkej0<~pdJR1E8~1$uj##`1eBc0L z_`1+!%M(irQ1x}1^X6M2cH<*8t+i1fF;G*JnI1EN2WvDs;x*Nk84mi(Z6?k!?69V* zG-NcK#jjMwmmBqbcA1nDXHTPy>M~Hh#dLE)mF}$B<^`oA3wj-PAa1a)@TM1S_d?S)l{3%`9bN(yJqg=N&l-Vv@?1 zP--e{=D%Edx~}Wt=t!3{;d^pSG>+z@z*J4bQMwHO zYeN731wu=iaZMaoK6fLZ9R=Mh*BU}lZ38w-<3Sa<>4b}{_TR`-DmGRS)8yIF`8 zo0N7%9YOMTYJ4mc>rQ6RurV-$p=j~|uvGd#NwFw zuTr(War*)fa`eP39z)pmdQ8iZEzQO%Lz;zPQV8R_JW(qN4j&3n zsU@~~HFd?G>A3Q=Y#`@Y@lA&+Fa*Q>=u)9ndRT3R*?4X?TIjwTILgkaiLsxGvurpC z`|@9^`cpa!RZmPsz%?SNHrmKXoMceR)mc=p?UIj^mtq1pY{aQ`eGX66+9t zrIr==Ed>|X&Tg;?a6MLK9_DiY&v+2S_Y&(( zch5T`Sh;<5xkpi1`k1J%AaZ7H-K4bVUISknQ$rs4AZ?=ts^wDa=|>QOLfPoV2Qgq3>4lmF-)YVlxyKs+kP-k}Sg z8uv-m#P{=u5C0a*qLmrZ{vYjT(i8fUh(tTg0Nd6GtJ_*C&jnmnGT2s!S%&HE_&-dx zR`=bCoX!|GRmS?V;PGZFi9qEAl$g{xGN0kU9ro!uqBb`|i5_X$8w&=q<9ptyB~R44 zrAHj{h8+%7xs>5GLl+)F%r6oyTakjc+b|v%b@(~pEpKyZVMeo>%{lgQ{oT6{pS`9X zHGlrMEj~MLpiP`G5{|4@w1?d_aFOxo+_ukS+h#)7Md6XqCy5bg`4UZmCzi4(q!ZL^5<(gB#2$ zjhwloVSOTodAB3H$Z?3BaSs*!nj{*Zx2_1)E?ab;s=Rw|Nb+kU`$-OSk3eSrmXq1; zFT0k4b>5!dP|0ovvn7vGW%8$99U^OWtWq zf>(%RR?904Cljr&jt0e_cKb7Vf3Deen--RKMn=^QaAzZCQ_^1i9v>dnmU`L=#6ZQL z(?k*Tl4{)|P;~mh5Z7yCj)@Z8U+AHsvq?$PqyY^arq42Zr>-LooOP>7VDDGFuerg( zv&nk8-idR9ihLd)@q^8fav;b1I9~B+62$bf7V7%4Ci2Y?Z9tp25ZF#v-ahi9(N*g9Khj2YzY-L)kF=O!ltWCkvs^s*x#^cLEb zsT8of7&)P<(k+s2ZY-Wu9;AP;N4k$90t8n|W`29T&JwyJdhjjHYq^7|a4`;l)L2vMvUh26dy=xPQ zcEeAI{&DDX$jv}|9X_;R0aHVaSNs&su#at}d|5B}^qTLRAvLRcHVZ>mtf++xat<9t z;gW|cu#s$k=I{)nNPJF}Q)!6s&i@gQ+tOfk;jY8Rz+<>p}`U$%Vo4>9n-4 zUfVjs^8>!7WD~qr!+vUh`0aB0$TQguYN)OzG_eW= zEP2vWzkx*EayCJ$TWgJt>CbcR=n#8upbC=^RIt+H;jBEHwjA#AYIdxO&hU68{u77h z$X8O303X5!WD6#ik;aNo?($PO5(hQv&jEESWIMieSFa;*qyA=pbo1Tbwd~`Xw)r8)Kf5%;u-uv3U zu+cD9K@&QZ!lR=@qZYcDWe!qg>SMI|m)|WoC2mItuJxt1yc;!`%pVv|ulys~Lb1N) z8O&J(ka}S?Nbp~3_b3-Je1^^^oj+BO)k-{yQLx-;>%}DC4pXfy(PN!!@lB;KewnxHLt$8l98WR5J@MOpc?Jk z)n~?oB{oJ$g&oTIba3r{)&os$))zkTy$jV#u#U&Lfv=OuFU(wi6^vUKc(P`oP&8l6 zrdk8Z8_5hPL>ilHm@N10fLpssPP{vMZ3L6~*Q{oqG}`zGecf%bN~@pmwWPSvQfc%> zLP%3IL8~b<0cY%Fz@L_Cs*ZnFdPldjtb~*X3wo?;l7Cw*{+^Y8_|1N7aQF+JSL`0L zkicQ1f*lZiNj>~uJ~brVd1mx6q6Q5aRHJHenj<$R_HvWi;1GguNs?^6QWH2FBdJYp zWu|(sSxs>kmyA77WvrJU!F2yq+mR%lS6| zGeaO-=MGP`GQ|Z=Q}lOw*8u8QY1QY7ZX`h$Sccnmv9r+ylT_X~u|ArgB>EUF2o)Nz zoX$iFyxZE7bwjk)lN$w~$>f*bDU(Gz-)-H&mY*hd;ec_HTmldZ-u>W|}5o8rWq zW(DPLqu@iA(eKEVSuCv#M0{}xk|7{+q~Hsag%Wh&*9nb+@?1YYqDa2K4EUSLPyP0@$*a!lRU3sPr( zWSKUTiG(keRUGPIn2#_!=HC2xjWYHSt(?)r<6AQkxlFFu-REi*zTErDcB|y<+E-dzGEf`d^GN~{b05dHgzspr|@ieuhM|C%g!(R8|d_4hT zwQ)v;+xA*kawuw4+B0JjRrqM0*aTdyM_b{doF>P(swd2AgPxN1M$iH`qJM8x zLwMt(^|r-!SjbMV*;a`cla6h=G(-(Pa6)(#(Mg@_t)D$K^;Z4^2ge%AP%Rd>z8Q82 z(eb4e`={{!^j z=qYo_)tr*e930m3H5!<~)V#2efk$FCYI{I z)Np=fRS2N;nUde{xqJ_@c)0|DWk0%{vB>Ddnz!Om`q)-s8840PHVgI4%Dwg&F0d9R zTIBHX@gUirD??|(m66i>H-xMqX4AdSA2fgDXcT4mGwj(gkNn8@rOnCFnl5ie$vau@ zq$LU0tjXIc(peWK1>@^%nDtW${%E_yEHe4_6^EdZRj!&89v5AP|>Mehul=rm2W zScSbC(uz;T{DuWzsKa6Q3Q#F`Cbn7N>GRUZnoMV)j;o1$@h)Hx49;{^l=Hy2NkaOW5e1tXe+g9PER8(${BoL zmo+qenrdf8uZ)qa5<`-LODqolHgo%Usumt%GI-l;Bee}+V=g~Ib0sTEZboW0bso6|bsi=X zY%a)YK#eB~wg<%2Eh-2+$U=lxI?4&olGJuTAHgIOP=3%sEQe=? zMDOHXqO7X<)vsZH$cK?`U?4j$p)N&}!}W9xm{}#fbHNI&P6-83SIt{YlUPfq*gmtVmU+${dkU~wULE}HV>`VNS|hb11lu(VOIDyvFK zshakVm&0YFY#Jbb=b_?u#<~m^<6Ss-&|3lbHGO#hNRB{4_?n^p^bRe?S08zrB2+A_ zZjQ%2XAep{rbxT7{BT~A;2vncxEgs(LVY|@QjD6Ga^=Jj^^MV@c#=gnj<<{NOX#S7 z67Ig^yjJ!R2`T%S>cUw2=g0i}f;1PUm8}_{ALVovL5bYZB7}@5Bi+x{Bm%X4+NWCC1|$J`|ZS2De0JSn^* zdjzqYOheE6#9SvmM11aCblo1^b-fRe2u?~wy1Nm^;Wb5DAI4a*2OREuzPljmz^C^@ z&*8D2xjZGEEpY->gp!_inp*yq29FN6(JRFNq3A%#Y6JHA~Z7KfHT zx7B~?A^z{o;;MeVy87`2JYQJ}_Vd<6|AFY+#>I&EF}BY-e?Ni3E{jnlD| z$CoL}wfqc@bGF&A9d_QOY5x-}`t-sm(U-&YkkIS4LrZ%~WSILp={-u6TM+w3@9D$= zD{i9|4W25EeL~Hz*Ji^uek!uxx!iBPWu>3|AkEIxk%(FWCsDm)GP%~1Zvxzy`eyza zECjTNSoyA5?=~wd{oN98;&j?%2ROQ~tyO*(E6jbH+xVO9kfs zE~a$u^Z})UaziZ!+FMl8w`Q~z_Pxe5fQ*iUZfk25fpSMzu)dxc(^IoAp9TqGbdnZa zF1TyB77G|vXDsiG*fv5fFeSDy2^vozuCI60zTu$#aw z_0()WJk2gJOfQo!SNL-aD$)xy$4--6#pH$S3XJk%(I0ISm+^s4A`+A z?&r$e;#dl_c8mQPS{@-I9&Yf-Y?GHwb%*(~5~`kRy|MT%+~T*>W>dX3NsNPEmz!e$ z^x71e2@ms@m~dD$pmz>B-uN8SGR^7D@l?lIo5FCMCW7kY$d<;`>_kSxN2Joui~0@L z>=;jv#>05XJf@Zy{gAB~wOA55jazR{ZB%I+XEtt|9ar8kloF86aFA}9xD~6G1aHtO ziFm}a<0WQC}DU(ka)wzVaNrJ%fnhpPq3+Jhg#qTWti_l?wUa0VrxNsW`T2~AGzPfW zM9F&{?p+RgDziC2I1#(Q)FW?eZlOIku=xp zLb638=p^D9{|0BVkCQ^~W7RIibfBUFJfM|OQN|Sm^sMWgvQZPIEOFABfSoIsakY)U zC7dr-YK!AK*{Zf8{RIw2WyCR_oI9WaSuRuLW^a=i3gFmjx*SMu*Qyxf=T~`~k?Y)E zWJz5w&$`;sz|F}?c+AEtok$0)XsXx>>7T9-sW3?d!vD!Rz{ubCFTTDgyi=)jxMLP4 zejJ}#oEeBJo>D83$(VsHcKN^Doub9IJ9*#e9Adl#{TANwx+M8`hO&}y71_fk{|#3v{%#gpD1}*3wyzJl^>z{H-2bJN zlp;}#u772_^2xH3yuj;5Pg3airIDGP$wu0Mwfs~kh*L%WI9i!B1M9aU;dir>s?k(z z8_n1n#)brT{AK5sTMy?{f(p^5I4nlqHxrG56CD|r8H6sMHF4K0=ikXaa-E*h(h3IW z){qrC8>lh-2T~$3*=h&*ziD}#74~Dx$w^%WQdh03(c-eYun$*dvOFK7@jd^mBf2@0 zih<5}L<|fdQ!0;lyUSZ%r-QNgmFqvzSG~?)=bf&w+M_LF84 zzmj_Il>>f2eeuZaW+830x~Wskw^D690^1|%Kg--PZ4TTvwwC_5Mm(tBPko&HEcj-M z?wQ@wrw;;HtD>yUgZ;eAhQl}fUZ=bI_i3qgJ&LZS%!X8~ycALTzTw-sOxoqi2N@54 ze(3q8M^mlnL;5J})tVf)K>}GUqcpMzUl=RrA z#C$HoAX}ng-(}nVl3c&{P^0u)e>NcV%B>Of#FMJ=pz^47u*||#_hxe=;>05A+)h3} zy{#@It<)dy`Bx3>yV#?W@Gp%t>J{px^W`*!98T;e&s$#-0j@dys|NI_mVHn{(J>Ig zC4*zsO`la}T``&x#@^4(CQ4fel6OdvBFUpVX|Q7f?s?C2BU(i~~_M}%s~h^wf)P3IU@ zd-cP?NdZ@FDtJKF`nD%QVEJ?%@ z3E?DJ6+X55cw-`Y_Dr-Q1}|5F678Ewr}3?~Ob-bXTDSwFgZeFlRhQjtc~;_3MSiAC zu87M!rG8m}>1|%}7o7T-1V7sNKBv)@_l-Ea9s3QU>{btAm7LfdR`+jtw&Klck^Cs1 z8-FbL9+%jYK;2g9)?^i~I(?K}oG-K!U2BA>Sr>`i{M;b$lOZ&2tKXwzMDoHHNR&F%#?DT*z>0{Y!6I-V})>ZL2ps;?7YAr^_M% zAw#ZzlItV%5{~n#1p36u{#E!+74b{wAOyM%Y(_Y6?TbDCIB=|Wx{ts3MpvOH6KdoK z1t~^m{iapX4j;pkOcg-%)5${3bOUGaXK_btbU;+&V`JPq!*0n!5Q)hEL`u1w^_QQG zBE)B^(2g8OP9)n~TIR0iGfZ3A1va9m^N;I^OqBVMPdns^Z>*W}vml8yYdyoa7Pvz^ zrcQHYIQBB&ZPNM5P@%R_hI)&Lv9q91^32zwigmQFCu%XgRSwL?29t+%%HL|ap=wG5 zPBbd(LCt0_d0lNhn)8))W28*| z#E?UE&?Z0|`+WC8gGnMrSS{pUp^xm8qYJWgO{(Smv`MeVKAOt@S3UOr%?ss&lI;!5 z%Lh-DSA7EL;VL*cl-mhL=6v+9Ubsx%NG~W?_}eRz#sw zcpsXs*jjaoo#`4FFS*W8bOdF2L|E-dd#+G$*?%yac)Am&0=a+OGEMGI0c`JZLDbq# zpl0BQQI&|xbLxGB^u%xd@o%;F*_`ma^nv!f7SJo5hiFgIJMyScp4*UQHZ3OW`N~+z zfZL{mw30b+{d9LWdAL!|wBm$O5$AR-aYnZ(-jze>7s@ z*-;eLD~*ij^hOvvVTn`MuwxLvnIuN3rkCSvOWlj8vy0O|StaO4A*V8C@~a1#b)1`# z3l|q)f2oFoZ)1>X@miP<3*1;W?H3oGHMD`M_f72Y4$|?ymNk#73zvUvU z{YO>4uY|y*Xzaky<=*gp_CNUSbDBL^aA8c?W}hkE&d z2?DeMGK>%xU5_!W(VVL=LZzgHZAX<}~gT_q_v8#={EGiuCH?r21SteLH zoIXT!Xs>i`roit0qhmQpPrLxOcwSEyDNsS*W>?Hv8=IJc=22A?II7nv-H zDdu#Q);d@V?)+hD1I{=r^=Ybmt*ejCHu!);bME)=lnq@+{*EuDLMLot1&^JKtS#LL z=dZm^bmT*BQKjV2B1af&A8T$qeD9jynjql;Cd|p3Zyz-MNDOaz;L}@ZIkh(aXt$mS z5Z%n*$=C|G7B$i`WSJeB!$j<|V6sOM=niSA~-KM=`E$Q{Oy2gDn5 zZBLAp$aLpC)LU+TY#e}JZ!<2-YMN&a*ZdNEOa0DmPXkYjgYg>7HqpQF;||t#5)R6e z>Kn#sargAENI2S0h86JYF$)B2Dn1{Kbi>)U8CUvaxVc3uYppC6^>I@ zQH180(eZY)cPFDbjRn$Cdct1Yiv zZT{a?hk04yyhb-Q2A9n8 z(#=De1;}1(!ZUK!jcb$djr4VPwWDCkgNcFd&?AuS$x*n9#^d#T-?ylO$amLHU0gVo zREO2rYJCczt|^&7t$7srWl)MPZKc0y1Zf-@JDXLcUy+Y%3UaYxUJhTGTA?~w)NP6r z#hBdD-i#1Bfz71D)-+EzgSSxn9oSXrp-CNCZvISpR{JiyK&8ltUg-{B87g*ejw&Yd zy>wD_XIvqVED`-}i){QGw}`!CL&hm~-{@#cfV$f{3**D>{D9`kK#Vvxi##zk|%DA8H&6QY-zLO=m}%VqkuM9le2Y+yi{R} z2`2wvTd{DL9@W}1?Vb#zCiSdsYEp%TP-}_v(`P%bgEBadC=d-%ngl)~< z#y7o_j3Accg9O<54^a-QGaA^X50?$8q=W(bnUl|EU#73oT9CJ!WcN7V>=#{_?Y7So znJ7T7`#26gCxy4Y@8DjWs9I27^st(}s6jfO(4|8_T(gwTLuY~?MYR}Z`()BV!infI znN|lS-f2h0HGH4Q>52%xO@_xwK%!C6*-i-zNKn8=zk&)qtXksWdL3y`RaEMAna@<& zNBhY?FsPrWhp!@tXL#MVpbkNa zlG}PeeRoF2^4IQ&PYmcpA}?jIXZz0FWLVIs_@f#(#w<&oQSf;KijStbe!pnhP2Nm( zX1O;A^+3t_aB)-YUI^z3xM!2fH!E=2%^77o)--PZK8dRMA&aYOD!&DYtEl)Lqga_H8*m(f?7<)#0uien0m~ z4S(}U;puT(28W=On`6TYU}`t@hR}F5a4e#`8p3Y*i&q9`Z?3#OVDDVGoVx~3O{uXC z+`fWOYUwwPTVuU(%wu?9g_AxN?K|FID}<`^;lk_2kC1cvnum$E(lpp_mj~Z1agSJZ zzFRq7^6UVSxCNr+XP~puQ0sH%e&`F4oUv0r_zHQm)QK=ZMCHG{IwMrp($80$Hn-SU z-5%8$m{|9!guzZvtv&&_BTla{I+g!?GL#@8uWu8r&0{W==5**PPgN0bWT|RDQ^DQ54(ze6zyozE61_Igpmxx;z0y+x>2i5Y9t=^oL)>42?D?D6 zi<9^A=xfKm#<28d;mX!g|9nH0W0UZ^H=@VX+j)TwV-Iz&HJd{eHq<6So@SrDO6mq# zOWI55BIuP8#;yC0oPVFX%18{-?%*kzyS;Bc_<{B97v zAD+mf*(@U+OQVt_c3AoTp>*z0F1Xh~BHaB!&Y2m!ktyC3-DoJpi5q@#I9{rWw4(E9 zuJ1D1qzv+p8PjF2_>Rn|c3HPpY@?;K=u3Ve@ePj=>}$Tgx4@`=nodZ9^Ug9OHQEBgFMFeK49=Hpa)kdiku~>UZ9IDT^LKfNb z@JYAM8~DSq?9tP?A$|y%@`y{b0z(SQ((fNUA`=e24yk5p&0A~&jk;`w>7`LH*IZMI zV+(5^ARg}bB(v`8?if@QwUt&Ww5ih}PJ^yBj<4W8LrSurnwH6w7o-?jdONu;o z1i1dtAi9hWWK7+IZ<63drkQF(Pm1Z6I)M=09+ln}{=Vemu^xI!8drjOH09pUqnEwD6xF&joenfOBCaDYec@zewp=tXQM z169}H%`O$EU9)KovvJ~Lnke0dQdZvx z@V$I67tmdf$UR7`vKo?{eq|@SqsweDUXASS(T511?xUp(5~Qe)wZ-zDDE79)CFzZB zp?_QaY;)H2VYs+-PDj@HME51?4c^oiM~cResx#|8cWv`6lecl6xUatpzn^fwUElF8 zrM5MAn$fwbJpd$buYKvQ$<{-~skNS!3$%ES%?$ z!Xpe8vRDVANq$oifxDHMXsNQDd*iVJT}X$61!#3H#8Vc|1T9xrU6CxLC`&2=2u2u` z4OIQ6pOeWg6vG+Xi)=(MOTxJ#tMEYnFINg&HHjdV8r;^wYaAR4_RsT4D0_7O6o7E&&o{i4HZU?h|0>?6g=M6horf_t zSQ)F^-qn?L>Mfa|W2ladGJ{ZcFoh^ZA8M}XY8RmGz0chnDCspj3d*Y4z>c{jwk!C% zmzOrDHtChNs%%<2t&!-~1I~)s{h>?J5U`GPNJgfASfD$UUJv$ocfz?3Tq%dxgoD?# zj~%r?Ju@$=;+NlwGL4VuhXDhSmyAdbW*+ckR)WR9w@2@X!C2&YaZ~#Ry0K(?^ z?nOve8GaMsl%xt>Kyu@(rLf^VVp2c?j$%I_ZsGBA3U7YWvrEY1tKUMy06*2Gfg%iG zcgtQ})1Rc{F)HdB>+8ZH6>gQN)DAp3`+Vj^R2t4$3}4eK*zZW}df4RTq>(mI zM!Gnjkrc;EGQin(svT@!>3Y0G8Z$b(ZOY@Z%6&T5bFB7Ivns*bjQY4;(LQNU)O&RQ zL1UCp%Liy$VwMy(0quFq=V48Ze2^?7e%6f zMbX$J!C*`*{zO%t)4L~8_;wyIG#1PHySx37+}5I7O~hAUmp7^=lL}d8KT0AqkV-Kr z6y&Qsu+fJFYOT4)vm(+F``wv+*K3*~aTh`a(zTF}90(@W$pX%=T&r_5+ANR_g0V`K z2=BMCNQnZhmY=6X4 zgcLVL9DvGWn-=;BnQ(e9UK0^HkIQ^<9SZ+< z+`YN_f=+4_-K<{Y6Z9>$3F{4TGo3X6{AJ{Y%ramER4eIk&D=_mImIhAY5bMu;e2 zJ($AB@JDoHV+UuUaf|vSVN${%rO7@g!IBeHH zgbE|E%=cdLW9hOg6Lz?S*qhi1w(hT!;VX3N-!4_n32td5!&6)95 zEOmHGUznX>7v$KJbtKZ~#jAs^)8I(~R#bjZA$7LC{y`PX0H-OHmgmsAJ_HrMYA)}p1&J@459O9wENF+9QkC^5kH9v`ot@RAU5>N5#TE@Rn zIuFB*7@p563_&OG;Qn=!Iqk#BQ7MW1Ccv&{vSOm4Sw~x{ay}|$awN^*y$>q`8^m8h zc&gB|+#@!_3tu+=9Rrb9Yy@3;#){9GJ{$!pS!!Bn`bAStY{2EdXA6r{xo><%5~DR2 zdXN`$yPVT_l@r#UPYszUbkr&U%3I2VJJBJDf!|JExP1rToz0)L*i&>_v`iKccK+g8 z#a`4#b|6C4HhiVug)JOX?9tgYTko2MrPLU`LgUHil#L4SVDN?bKn05hbzYraD=w_M z1QfD5qL9dQ}A~Kl9vcBi+r?A~l7iwK+aAET(YTHtAnT6y?(E2R3}EGh*6XPt$j|Ig3{n>&0wN8Ga+t0WLuyX4s(Uu{DsB`b@0r1{IB zD$d{nE#K+Hr}|_(lm=`6wU1X5mc?8Nmctv7w}~2P*0U)GV6v~qSQFh6+-^E&r`QEH zg|0VqBMj+eT)&Tdv7lI#LhYYEnG=nqNK92*VA?1*CK7IE<5;x+BncjGloocmpLppx zN3YDhcRSK(e>B}vbdWpQB8R%41aS_It_P_(ct6#;Wp1S>a$ZWIf)D;Pgf_C|+Q=uk zw&-dK{_F{FWdcPpv84S&H{qcvSzx{;zstCYC2_1(v!>isx@cXUn$L;xm1B*U!WK-| zQbVQo6}rQ!eOVv8{{;o=W67`}q`9+mQ0uEeO=+zih{BN+k+11Rw%mcO-K5;`;P?ug z&w-?@05O^OuI^Udf+A$sDXV!B%odOt4C^b^B%Lq&Tt>_I{#4t) zYl9`PO0!&69YIqu>Oec~Gx6`Ey-OHGNA5$_rbv`N1?LSgf{qK;juCzH9- zScFyQ!-%EA_;?9z?KG>wy{#n1U4dgd@b%T|KHbqb%96nvzTKy)K!t#S`qmz4!p5ob z7r=jUV^7_wU zm7T=Db-tJM$Cv!n_RMLi1<>DJ{;H{%`iks8dw%J13Q;oo1z`gqx`X{0ifZc3>6{+X z%^{<+o#R^540X997=v8hqB?U5xu@ILcpMHXhwP7m(@0`A2I%t4p7; z?y^b{^;pl|#ADsejpIi;b^rhwx~wEWR!~zYkuHF%jCS_JwE{(TzRW+S`Loaqe`Oty zHEO5DZYNZ$I7=EAC;SBI1w9FyD< z=GElD#l^*{;|fdMR|X;+)jP%ng58Dl@Z%u;27J1|++7Bv6q}T9wfSerzL&T6*bRXN z2)#5zPw}fo1A>6>M1xwLBZST=LZ$zcs&n-IAgtrB>|+172@ktx4Jq~0g{xy1}P67Z({NIhCsr7c~=aTjsJ_f3BA-%OK zScAQd$Le5rQ}#1=z7!UGb3-eyEhpVhyjdy1R7zX(8lN z0NpJ7Hqc0QudX!pq%vez6aQ79-BHe;V1TBsgj$YYzGE(~RB0T;FW+skx_;+fAD?57 z7$smzgQkRmwxHhI$EI|#wl}fHZ%2u>Cspg<79RA8i?X>;KFIWjRUP$4G>U4##E<1p z%Tcyz#b@b9S5IKK{gz2GzA9~eZgrmk{N&`;78O!@$rapVY(C8l3qLK+BXNC|i_?|)J2mNkTxi8ZU?`Rd_ z{Zmq9JN+L?S+xYK{XldNtuk+_LtB>vfoM#v3vBIOb)^I{8oUaQR?*=u>LH}OGr!Q7eYwp^80C+A}CKXtD-P46kME7LU7Er`L{$ZALFyj%2pk^ zRD+kx06+uzM;NVrnfZIAM^bqR_ zf6Hm?`na4y~DUo2tA-vE@7GG{K~e%nfJCMOLotA6C-XH(}-mEOM@ zR5;o6Gxm3e2|H=u$!q+rM>%OZcVJzmqvuCMS)TB@2y7YZ`msfDrZ>x5t$o;W=mXpH zF^|jq$bKuaoVq}H#!{oxY+PgI(q-IpaEKmmw~PJpaqTC=Wt_Y5K_S(2FN!rG%z8T> z*pjDLmHDt(+D`uN&0^mczu-Y?L-e4bZ%a>wt)=;|@KV$5YM=G%hik{tQ@Bb((WkQM zkc!iF=EaenV$mkY%o38xJhu^yQt}1kp0JTS889yU4()lL>Fufu)|N>sDk%?8Zj;|C zbAl_foO!<(N-9w4@o}M;>XR@MjtZq}|I^D9mPyseyUX|aWJBWWpiI(*wC*GQ0Va`UAjRa`Z+7jr5!#u8B86N@!Zvr z@HmxY&(ur{nQ(`;U@aWNt@K$IGb|u|kXmBQ&48U>)9yWM*14+i`Il5GDPCKYN4rJG zXV!4G!kLq$(gaRdJ^Ri5b$6w!RP59KgU`R{!&A7Gxt&Q=QCWj=(qEabchpjn;Vpi}iDcN1*3r10orrSE_y;cQ!fsG^@~e?Kpt$>{1M+B$ z6eJylVO%nOzV8C{D$dm1*bv!Oi~EQO=$A~K(79D(e+~8?K~MwN$yc?0wkZ3kf?wNW zNEwjX7)I}o0SOZVw?uPUgO1)_bPY`}e84C3(P?;u z-ZBj5%402&Bm77rx*#7u#_SQe?|@vUEzaBjz;D$_9wMt-2#q^au#N|YU!ir%%!gAG zrw-+Sq0yzuFICt2IQO2m* zO=466i2d)zp>=BPazmfoH2^??VRN}Int_}6y2-V_quT$R@t-&ce_&?I+F0c$C&8yD zgHM$Cv!HdjFeEpN$ITxO?vU=)<=#R{YZ+(zHCimSSX6bKKWf27MXwD_q|VqAAs?5% z%(bj!EeigPSssjy+??9GF0H(_s+Y}irUEU4+t0D(CQ-2_$J$1$6~!&pC@D{$Sd_V? z{Ybl9V~{4||D`sS%1}xHf+vm3FoT}IQ}O&2b8D>!ohKIZx%~vHPI;5U{P#sU78{6` zcr!FGNq^ zH#<0tN%oR@?RRg8fLhvR*e(QLno*M57#!CkBD}!PEc;!^mbIybo_-%4AA9iz|G?GN z?nQvqB+j@gcjd@@|7{4NF#&tJAR>)#al@}$Nac;WiVioLBliM*htrNNSovv-I`K)? zT1ZsH+N`YmU=3z^aAnFme$~Fp5P8keFzPlq-DZiVU%thV$}iX|HYX64i6z0X;5xR4 zgGzV1II*f*`hCUL{I~9_@EYv!)oHxudU6(I#d$+&@3*QAqhkoV^HTGzd&kVLgS<^L9vkSTKxw?npct-^o6t|J4eP9w+mBtw3m4ZRyf%mnBQY} zDv^y;#zePccP_dIV&l&J+5L9Dh~$pw`!>_2O)eJ8TL5s)=b?OE`gDDKStN;1by#21 zASZpIML6Wufx7PJ293sP*=s}NL1OP`kP|YQmr@Rq4~wr3Q?mwY#^yC>#-3*(Gh^2{ zY)T)~!AN{(-cc_<6<-`{U-OZZ=7RseC+WGunq|gA$UUY40zw}P3&}|E%NBvVSTsQ)>-Q@b@4lETr#>^XSAl7fUB(t4RUUcNCs z{G|u}bC3t>+74wl=WbtWOFDSLrIuzXd}6~hdZ4`g3ZJXor!gV(VA<`!sF-xQ@M*4+ zWWYx+Y~(|8OV$U1FQ_K^IqEbxrwC(m2WR@v%Ck|;XE8f!G%SKGF)YII`C3F

U$4_tnc{GxMLX+Wr`W&FZ1QDIrr~MoIU#yi=FaY&0$E+eJSawR1llK!W_0l z7BQHR#y#P zIPZ`L8kfmyK2IDpy^x%+V0J3WjaT(e&|FZhR}FF7ehPu^33Y3;i*$+!%&Sd#{&Dsk zAA#mV_ZW92*vHNH#GIeM@SaCxUiJF%NT=r9?kL7yywvlQCk1M9^ecUi+3W$^@r#X- z@m(d$rXNvwUKPEzq0anYn?K5Su+y(rTJ!Y#|2dS?qE!y&H-vS+cELJ4U)dh1|? z+*lX;Yft_d0!i0bKJZi6`XU~vq?H!?~}33 zDV}UXn%6FMnmj=1Q!YUV5lCa*Hh!k(y7wopvZf-yRg9IMp#W=HTwOP@L)8wW7qm08 zIy+wh59a3@v38`d*l>WKAyf`m(j-Tmz3F%Q7iWWvb;_T@J{R!3da70Z z?Znz9kPlwuX`H#44t`O67G+c-^Z8=oLsMYh_oG6DmV8w}+mW1g7nnXb!W-k58seQh z$Y*W+HYdfOm7}$NoL}A@mw#5K&oZpt7O1XMNf7~NSrp@yjkWFL&agLM>i+G$!&6y? zFtt1TXl;_WSILZ~n5q{w#2H>|r9T*mat4ZSo?X4D*c8H`nof@2Z$xb(JL-{Ce}WF{ zIfQD@I9mj~TKR%7e$OU=-eq!*`Anuuwinw%!@d@zNQtpJ>as#q=|;8NZ3xhZ&ljo z#iZKd;Ln+}H9DLqxAH+u2TJRtn+1^$vdb1I57Myh0oSH zd~@P2Y|~&CJB>nlagIFF2(+|&nxYl|(3*D*8DwGpW_xC~(}u8=-c-eb=Rx5IEKR2- z0y#}yX~~@a=iWM+Lazv9ncBjRf;h~%3cblQb6id^W^QT{n@m>Jv~~fK=B;j4Rkhl- z=vh}_63sjLEv*TprYGX^2}lYV2bRl;9*i#qa$rO7#}9Y71MBtD+v^j|qj7mD&%ong zXU^a@-<8xqxbka_Cvz2+dq(q|+o>WAD&JZ2? zBJZ2yB!laBNn3AdT7$fP_ag`PfmLF33+E2KtO&L8>5P8yMGRcY#;Moe{s(P&s;X38 zT6-juH2yAasjetdw%O-_-lx-}yxd#vZrG|Py`*5f7dMVc^-@sBQc40Cr%qTVHT>e| zJXOU8W7S3K8U)Y3OJSHcmdjAF6v$UDZE7-CVz1=FWr7ARa)s+ByvdvaD`2SN6Q)nfOm1rY64n%I1*9iHQhGTj|${=B)f zbL+!m=b$5GClfw-Zc8VZ>_cW^P~i>bkLcUSlcbv&zwZ$$JL2ewP$J=~odgdF3d`WJ z>*H^FE-rG-&>XuDnM=H9GYgCdK}JvfzG~ld)vYtC;~-yFh#C?Xhm$WDx22`BKiSr@ zRzAu~Xu_10ruvJr1~(KkO|u5UqbyB;dV`IX=2J3iNUE}`m=1PZCmh-jRI_SgM(2BR zOXs!$cV4yK8ON~6w!d!M=iw4FdGVB@oZzW>FjIAlO0^#$V|S_9s+Y1n7L(E3Nz*7h z5oGKG%s@@1f%cmZ)2X&oCczofrOnipU`wMJYmSP%?covZbX2B*I-2$2G^D_y`bF^1 zmhF+;vwKF<^?a}OhQRd?gEObw^}!~aZF-g3X- z2oM`N{Yo&--9PJDPXmoOZJNT|7%~13+2@$sP?xuQg{iLGpX(>8U$tqEw#`awmAi`s zC{8kL)Ri4uy3OyT#o&GxwcQ7$o8HJz2DQkv!m2!J%pj@$$2@yV%qXKWh*Qh)>H%Xi zkDMOm?9!Y9@H&hb7gszVyoD9VTp=rYyj)81EMxO@mM#lHo6Hr%h7LE^QZ@7HL9GyN5>OHylRhY7L=Hj`QYx1X7_IiZkr@t$C z!1Pd;*`Z2z&5y)P`us_3p0DNBSrb%;4l2qYF4y9iTmAK~HSEbibE|J#MrUl0qrr^{ z^@e=WnMK*bxILk;N-}*xuF5l*ja<3eG7h5IC`({y;>>wPV`1RwKQ4}#0%w@;_R3AV zS{5%r`>OK3b>?Rxf$tlej8XY|i}N8U2E2zGVIm2MNV~wY5o5asBLbkt=3}pn!GpC$ zQ)0M&*y3d^j!HQspvB=&;BWC0p09owN-LA;l%2lpBE`S{bD?oIw!Fj>f>m1)zBd1P ze_-Z`?YTFlT|_6#*vquFQ`0DaU6l6r&m5so=)DrX*FzRpZ>3ujQ?>FIr=r}q`y7}i z12)Y|)3;BbG*z_q1y;1vmV&8I0t+#dJth5i!_VJYB^3a`%V6iShYi2l>xx%r*zjE6UT2Ie0GVDNTvL@q543su zL;Z%I=%7?(@q=v*Cz0dtb(uuL#OeUX9C)3ZIY<{baPjsl@^yw#Sl?H_SE?;fZ~L}K zy9EmgS^ZQzI$nRC>^VN>q3--C!vi)Puxrd4G}7fR{UEGhZBK=K>Zwm? zE-C!-!PuuWw^0$TX;TV<*L`M!)9%-dmE68-Pcgw=%bkz5NEBp6P2yW0-7eDh;AV9o zC-N9c`J63mv#^l!0~f@;D?&_twpOfX$SosrAg(FX2BXiu(PlHDjd|bp3^el$o-Chw z`u6kpK1vIoy%Y;Y#nNf!xqN_x_RnS|raH3VPGv3H&n3 zJ1A%4+}h2MgvKr5J>d;$LsPfeHLafSHkFaZ*$yr(0m?$pX@ob z{nYj#_104GFIjpBB#MZEjD+i831Z77s9f8fOuWuJ4oi!xNY4Y0eV>HqXS3KpS5@WQ zefmt44(AhowOTH|?ER^kv`ijrQbnfKk1!9Fc~E`OHlTC996 zT#^=_tn5y99!4Zn%>BNz{DfyXpwezpt<<9w|JsMz6`Sf+49=*JwLq}~>LW`i3|sp) z52I5NKS-_XQ7N@yoSc})r1|8AAGw&n=mz`sCBsVQO0W3brVuGUg4s4`?-?tV-}AaH zEMz%eNj2T}o@RGHF{Z;j!}hG;AfY5EryN{~TfMJom|RzO7RzN4T=XhaZ;C-#_ZKHRV-cu-Mca5%yf-15!C>U=;`n-Y z&!8!kgj-1i@RrSo{Ot(d~k-2CQS!1hIjhz8k0*OMK!`wq3mCfsiC)W6PEef06 zsJt4btCJ(0$~j8OjlU~5hptQbn0jY82?_IAX&FHDyiV{qWp|?{hhft*De%i~MzPeX zm4fcBX2tcG&HL)S6BwD2N3rA&Tb0_G8ItWfrrY;{f`}p?&^qpFsMvVDq9#6C@Itx; zyg0Q%(Wz2Rn5HtCq-s-kh(GxTKMD&GzH7}G>^2q#9nJ`7rD)|lzEio9erMtUrLq|? zJ5y=?a@&70bN=u+cFQAyvwgBAdwu3G&P}jV_@Df%O*{$#E{yVajm@-PWRrVPLPWf^ z3csBS9+%RDUjV+yiulBjtBQqi-z$;QWokfP>-kVhEo_}kEzRB(?IwZ@@A<&B7(+*4 z&`RNBgG(xP-!+dW-S~46_q zQ4?Hm2(!T^V5bFQpOsjN8h>Zw^ydn)w;(8R5BQ_N*wQy_YW>5bfZthgN2yik2kc;`N~$N9;PG|1Oa_>hlagB zP+?ahvkuIN$+T(T*t*F92M5^OL5d&h5vDCFAH1brXSGwiKfzDbR&qNLtB!w)>j!Y> z&ybmgzhy>*b?~KqqC7E)mgi;fAL;CoE1Y5}IO3o>n)Pp0)jWwTv-V;E035{s#!8}2 zML|+C+ClC~7Bx;VzMvhy+SkbD?DHk7V{KP9O_UtJ|N7>}yR3jYoa{{lVlg%`wJd=g z*M$t>UB2kD{agRlp`41GNJT^fJIocIe=_rM$U7r>MVR;hoA}jOSi988p(2T`@;zOY zdV@>+AzGoq_Lsj8??us2e>C#m*oxDS7T-_yT`S@$MDLp>{QGaJ0nbqjCC-_0h<>;p zxcUD3VNadl4;p00V`4Ct)KLw0bt-@7T{#hj8A(M*ry&~BtRJJS-XvuE&)voI5lg=T zuCztOh{O(v@DU>=%F6lQmh54sV!{i+bIaQ9O0{=zycz52cy)>8@Bzwr`jexWD%x}3 zq?i=&rSqnt*CSrrv-Y*UVZ6?QR0J$zQ3!l6t;1e2dt12HHlT3r3gRuFG!Nv0`pQ*+ z{*!Ak&QZy)Dk|j~vyJb+2SL0CzYT=q;HAV0*lSNSPwX=Q;8-EviJTt2J>7pcU=vI% zDZd*Aa=1EK0nO{r21T5~VlW3zp}9?2lOS{q#mP16Lbn8T>`A#zE7q=kId($ud*lQk zc<>AKPDVuTj8oHA&I4 zOTYAhi$`yrS~*DU|Lvwe4=9X_AjT$6qXxcT1bzljebJT(&G6_2RXqSux`Q0Gw3fovy4Bcy9Yp|M-6O z!p17RsG8{JX%nMticM5O-?*+tWiS`iDf=ot8}_E6D6QeyVkRT~GD0%@%B-W{vlY)< zkhW%ua<|rj9lfE3i+A8d3aZ%c*PJxr{w5%LFQ=X{xp_sIiQ+2@$-7vkq+CDIJ(rWB zdr_{bYQ)+$Ypf=xvJRz&Zg`j3<_$n7*SpE=2PvHj!qZqv{~x4R)wI=x-h~x-HB=ad zklPgUtZa11rGQ^MH8C*g$Ju>Nbo3r{vUIR+IRisu55 z_7nMhi>4tZtOoybD8*=@p&YkJ$IsDQ$;Uh*XAO2OXbqZ9?U`Cp?-J_Cxv6WMfNvF# z)Q4-9?l69QC8dFfBos8giZ+K*Xutj5SDTa~nE%qrp&k7(b9@8z#a}=XS~Vz??`Y8& zXV(jQm0>1n>AZd%#{-+)W{QtI{~$74aRo3(rRX#QdwTR0wbB+}tPM;jj6Y4-y6eoAkZ=jAn}#62Zia$CEZB9}R{?5(#U zs$x2Gq$xc*b(~8S6|jsV=lYfx&UHeNL#lF7}&H*qDex#(Q_4o40rY_#PM z!pTI3toFZ!EWR|Uijp&YGf|O{t9LNIA1>sNF%0m(PLm1Rx|N%;>7$vZ-+Tq|veEl* zQ}dsFmw5UoRAdBhPbd1fr&#sh^%Vc-JeNwP)ZO%34DN*d1I@I|*S!CC{nLMXlx=SE z%fx1F_L(1kPqx0y@1hL1I=31p?{<)HwCM4j61%kf0`o2S-93Qvog%Y5=lE9KcKIHA zeI_(FAnM_D!0$F!L+h5LzI$2tb2JK*FmC5tLttQxuBe8!|x&d)B)52F* zXRVtrw`zi6(#3A3}<~z%~<^-@BFlf zMM(8RU`I!FWxI|W+>}|~OK_f~(sAj?5xBF{8Kn~xxYp&qz^}J_uK&`~TJWSy|8bm* zalYekJAbYj_ibFTfjiVnH8D!*uZHH@KC&;g`|YqhjqazJ<3vu+CZVqDu1)35NuxbY zn`yPHjD_=`2Ff27oLBB;dhq6%5YK3Jo3aS1+GJz z8c-Ss7?|o{^Mw^nXj10sQ2_S4=kNPYb1FLjOVRCoEl?HXYVwaI<&SBc+Gg1W4;uZ< zXU@wK4lP0slo}%so=NwZotc`3q_|bCyR@nPOMCj?Yc{(`*AmJ*IS9d&J%dKIX1S?t zYEeE9qz~G4_l<4Jr-s{z+`9h?RPKd+N%5TDdt*PpmnaM0&~trubvImJOiy7^x|ABj5PW+9%6WUzb8AaTycWTBd>mvSI(r5+hKP|~NIQRN= z>;Iu$J*E2#@eNU?%JBc4>8_wWem6B-T&au9`$Q6Y^YY27(bm(*^fUXa;71>cAHH)9 zHoeJEG&)D50s!#8W926vcP%9$@(TEN=l|nq&|lkyZtox-vJIV7zK};U*57lsxEn*{ P380~(t6cT`<-7j?nsQ(R literal 0 HcmV?d00001 diff --git a/images/EarlyUpdateCheck checking.png b/images/EarlyUpdateCheck checking.png new file mode 100644 index 0000000000000000000000000000000000000000..5cd3422100ee091b8f108724eec6492cf04095ae GIT binary patch literal 8269 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 literal 0 HcmV?d00001 diff --git a/images/EarlyUpdateCheck options.png b/images/EarlyUpdateCheck options.png new file mode 100644 index 0000000000000000000000000000000000000000..c0403751c942aca0fe02326fa432ad19cb87a1bd GIT binary patch literal 102216 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 z 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 e0*ZGT{_|IK@5(%7e&aa<5O})!xvX..language.xml` +Example: `EarlyUpdateCheck.de.language.xml` + +The language identifier in the filename must match the language identifier inside the KeePass language that you can select using *View -> Change language..." +This identifier is shown there as well. \ No newline at end of file diff --git a/src/CheckedGroupBox.cs b/src/CheckedGroupBox.cs new file mode 100644 index 0000000..60b532c --- /dev/null +++ b/src/CheckedGroupBox.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Windows.Forms; + +namespace RookieUI +{ + public class CheckedGroupCheckEventArgs : EventArgs + { + public bool GroupChecked { get; private set; } + public bool BeforeDefaultHandling { get; private set; } + public bool SkipDefaultHandling; + + public CheckedGroupCheckEventArgs(bool bGroupChecked, bool bBeforeDefaultHandling) + { + GroupChecked = bGroupChecked; + BeforeDefaultHandling = bBeforeDefaultHandling; + } + } + + public class CheckedGroupBox : GroupBox + { + #region Members + public override string Text + { + get + { + return DesignMode ? base.Text : " "; + } + set + { + if (!DesignMode) m_cbCheck.Text = value; + base.Text = DesignMode ? value : " "; + } + } + + private CheckBox m_cbCheck = new CheckBox(); + private Dictionary m_dControls = new Dictionary(); + private bool m_bProcessCheck = false; + + private Point m_pCheckboxOffset = new Point(6, 0); + [Category("Layout")] + public Point CheckboxOffset + { + get { return m_pCheckboxOffset; } + set { m_pCheckboxOffset = value; OnAdjustChechBoxPosition(null, null); } + } + + public event EventHandler CheckedChanged; + public bool Checked + { + get { return m_cbCheck.Checked; } + set + { + m_cbCheck.Checked = value; + OnCheckChanged(); + } + } + + private bool m_bDisableIfUnchecked = true; + [Category("Behavior")] + [DefaultValue(true)] + public bool DisableControlsIfUnchecked + { + get { return m_bDisableIfUnchecked; } + set { m_bDisableIfUnchecked = value; if (!Checked) OnCheckChanged(); } + } + + private System.ComponentModel.IContainer components = null; + #endregion + + #region Init + public CheckedGroupBox() : base() + { + InitializeComponent(); + OnAdjustChechBoxPosition(null, null); + } + + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + m_cbCheck.AutoSize = true; + m_cbCheck.Checked = true; + m_cbCheck.Parent = this; + m_cbCheck.CheckedChanged += (o, e) => OnCheckChanged(); + RightToLeftChanged += OnAdjustChechBoxPosition; + ClientSizeChanged += OnAdjustChechBoxPosition; + TabStop = true; + components.Add(m_cbCheck); + } + #endregion + + #region Eventhandlers + private void OnAdjustChechBoxPosition(object sender, EventArgs e) + { + if (RightToLeft == RightToLeft.Yes) + { + m_cbCheck.Left = ClientSize.Width - m_cbCheck.Width - CheckboxOffset.X; + m_cbCheck.Top = CheckboxOffset.Y; + } + else if (RightToLeft == RightToLeft.No) + { + m_cbCheck.Left = CheckboxOffset.X; + m_cbCheck.Top = CheckboxOffset.Y; + } + } + + private void OnCheckChanged() + { + if (CheckedChanged != null) + { + CheckedGroupCheckEventArgs c = new CheckedGroupCheckEventArgs(Checked, true); + CheckedChanged(this, c); + if (c.SkipDefaultHandling) return; + } + HandleCheckChange(); + if (CheckedChanged != null) + { + CheckedGroupCheckEventArgs c = new CheckedGroupCheckEventArgs(Checked, false); + CheckedChanged(this, c); + } + } + #endregion + + #region Handle check/uncheck + private void HandleCheckChange() + { + m_bProcessCheck = true; + foreach (Control c in Controls) + { + if (c == m_cbCheck) continue; + + if (!m_dControls.ContainsKey(c)) + { + m_dControls[c] = c.Enabled; + c.EnabledChanged += MySubControlEnabledChanged; + c.Disposed += MySubControlEnabledChanged; + } + + if (DisableControlsIfUnchecked) + { + if (!m_cbCheck.Checked) c.Enabled = false; + if (m_cbCheck.Checked && m_dControls[c] && !c.Enabled) c.Enabled = true; + } + else + { + if (!c.Enabled) c.Enabled = m_dControls[c]; + } + } + m_bProcessCheck = false; + } + + private void MySubControlEnabledChanged(object sender, EventArgs e) + { + Control c = sender as Control; + if ((c == null) || c.Disposing || c.IsDisposed) + { + m_dControls.Remove(c); + RemoveControlsEventHandlers(c); + return; + } + if (m_bProcessCheck) return; + m_dControls[c] = c.Enabled; + } + + private void RemoveControlsEventHandlers() + { + foreach (KeyValuePair c in m_dControls) + RemoveControlsEventHandlers(c.Key); + m_dControls.Clear(); + } + + private void RemoveControlsEventHandlers(Control c) + { + if (c == null) return; + c.EnabledChanged -= MySubControlEnabledChanged; + c.Disposed -= MySubControlEnabledChanged; + } + #endregion + + #region Cleanup + protected override void Dispose(bool disposing) + { + RightToLeftChanged -= OnAdjustChechBoxPosition; + ClientSizeChanged -= OnAdjustChechBoxPosition; + + RemoveControlsEventHandlers(); + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + #endregion + } +} diff --git a/src/EarlyUpdateCheck.cs b/src/EarlyUpdateCheck.cs new file mode 100644 index 0000000..faf21c9 --- /dev/null +++ b/src/EarlyUpdateCheck.cs @@ -0,0 +1,1060 @@ +using KeePass.Plugins; +using KeePass.Util; +using KeePass.Forms; +using KeePass.UI; +using System.Reflection; +using System.Windows.Forms; +using System; +using System.Threading; + +using PluginTools; +using PluginTranslation; +using KeePassLib.Interfaces; +using System.Collections.Generic; +using KeePassLib.Utility; +using System.Drawing; +using System.Text.RegularExpressions; +using KeePassLib.Translation; +using KeePass.Util.XmlSerialization; + +namespace EarlyUpdateCheck +{ + public sealed class EarlyUpdateCheckExt : Plugin + { + private IPluginHost m_host = null; + private ToolStripMenuItem m_tsMenu = null; + + private enum UpdateCheckStatus + { + NotChecked, + Checking, + Checked, + Error + }; + private UpdateCheckStatus m_UpdateCheckStatus = UpdateCheckStatus.NotChecked; + private object m_lock = new object(); + + private IStatusLogger m_slUpdateCheck = null; + private Form m_CheckProgress = null; + private bool m_bRestartInvoke = false; + private IStatusLogger m_slUpdatePlugins = null; + private string m_LanguageIso = null; + private bool m_bUpdateCheckDone = false; + + private KeyPromptForm m_kpf = null; + + private List m_lPluginUpdateInfo = new List(); + public List Plugins { get { return m_lPluginUpdateInfo.Count > 0 ? m_lPluginUpdateInfo : GetInstalledPlugins(); } } + private string m_PluginsFolder = string.Empty; + private string m_PluginsTranslationsFolder = string.Empty; + + public static bool ShouldShieldify = false; + + public override bool Initialize(IPluginHost host) + { + m_host = host; + PluginTranslate.TranslationChanged += delegate (object sender, TranslationChangedEventArgs e) + { + if (!string.IsNullOrEmpty(KeePass.Program.Translation.Properties.Iso6391Code)) + m_LanguageIso = KeePass.Program.Translation.Properties.Iso6391Code; + else + m_LanguageIso = e.NewLanguageIso6391; + }; + PluginTranslate.Init(this, KeePass.Program.Translation.Properties.Iso6391Code); + Tools.DefaultCaption = PluginTranslate.PluginName; + Tools.PluginURL = "https://github.com/rookiestyle/earlyupdatecheck/"; + PluginConfig.Read(); + + GlobalWindowManager.WindowAdded += WindowAdded; + GlobalWindowManager.WindowRemoved += WindowRemoved; + m_tsMenu = new ToolStripMenuItem(PluginTranslate.PluginName + "..."); + m_tsMenu.Click += (o, e) => Tools.ShowOptions(); + ToolStripMenuItem tsmiUpdate = Tools.FindToolStripMenuItem(m_host.MainWindow.MainMenu.Items, "m_menuHelpCheckForUpdates", true); + if (tsmiUpdate != null) m_tsMenu.Image = tsmiUpdate.Image; + else m_tsMenu.Image = m_host.MainWindow.ClientIcons.Images[(int)KeePassLib.PwIcon.World]; + m_host.MainWindow.ToolsMenu.DropDownItems.Add(m_tsMenu); + + Tools.OptionsFormShown += OptionsFormShown; + Tools.OptionsFormClosed += OptionsFormClosed; + + m_PluginsFolder = UrlUtil.GetFileDirectory(WinUtil.GetExecutable(), true, true); + m_PluginsFolder = UrlUtil.EnsureTerminatingSeparator(m_PluginsFolder + KeePass.App.AppDefs.PluginsDir, false); + m_PluginsTranslationsFolder = UrlUtil.EnsureTerminatingSeparator(m_PluginsFolder + "Translations", false); + PluginDebug.AddInfo("Plugins folder detected", 0, m_PluginsFolder); + PluginDebug.AddInfo("Translations folder detected", 0, m_PluginsTranslationsFolder); + m_host.MainWindow.FormLoadPost += MainWindow_FormLoadPost; + + CheckShieldify(); + + return true; + } + + private void CheckShieldify() + { + List lShieldify = new List(); + try + { + ShouldShieldify = false; + if (KeePassLib.Native.NativeLib.IsUnix()) + { + lShieldify.Add("Detected Unix"); + return; + } + if (!WinUtil.IsAtLeastWindows7) + { + lShieldify.Add("Detected Windows < 7"); + return; + } + string sPF86 = Environment.GetEnvironmentVariable("ProgramFiles(x86)"); + string sPF86_2 = string.Empty; + try { sPF86_2 = Environment.GetFolderPath((Environment.SpecialFolder)42); } //Environment.SpecialFolder.ProgramFilesX86 + catch { sPF86_2 = sPF86; } + string sPF = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + string sKP = UrlUtil.GetFileDirectory(WinUtil.GetExecutable(), true, false); + ShouldShieldify = sKP.StartsWith(sPF86) || sKP.StartsWith(sPF) || sKP.StartsWith(sPF86_2); + lShieldify.Add("KeePass folder inside ProgramFiles(x86): " + sKP.StartsWith(sPF86)); + lShieldify.Add("KeePass folder inside Environment.SpecialFolder.ProgramFilesX86: " + sKP.StartsWith(sPF86_2)); + lShieldify.Add("KeePass folder inside Environment.SpecialFolder.ProgramFiles: " + sKP.StartsWith(sPF)); + } + finally + { + lShieldify.Insert(0, "Shieldify: " + ShouldShieldify.ToString()); + PluginDebug.AddInfo("Check Shieldify", 0, lShieldify.ToArray()); + } + } + + ///

+ /// Reset indicator for invoking the restart after installing plugin updates + /// + private void MainWindow_FormLoadPost(object sender, EventArgs e) + { + m_bRestartInvoke = false; + m_host.MainWindow.FormLoadPost -= MainWindow_FormLoadPost; + PluginDebug.AddInfo("All plugins loaded", 0, DebugPrint); + } + + private void WindowAdded(object sender, GwmWindowEventArgs e) + { + if (!PluginConfig.Active) return; + PluginDebug.AddInfo("Form added", e.Form.Name, e.Form.GetType().FullName, DebugPrint); + if (e.Form is UpdateCheckForm) + { + if (m_CheckProgress != null) + { + m_CheckProgress.Hide(); + lock (m_lock) { m_UpdateCheckStatus = UpdateCheckStatus.Checked; } + } + if (PluginConfig.OneClickUpdate) + e.Form.Shown += OnUpdateCheckFormShown; + return; + } + if (e.Form is KeyPromptForm) KeyPromptFormAdded(); + if (e.Form is LanguageForm) e.Form.Shown += LanguageFormAdded; + } + + private void LanguageFormAdded(object sender, EventArgs e) + { + LanguageForm fLang = sender as LanguageForm; + if (fLang == null) return; + ListView m_lvLanguages = Tools.GetControl("m_lvLanguages", fLang) as ListView; + if (m_lvLanguages == null) return; + m_lvLanguages.BeginUpdate(); + int iCol = m_lvLanguages.Columns.Add("L-ID").Index; + foreach (ListViewItem i in m_lvLanguages.Items) + { + try + { + XmlSerializerEx xs = new XmlSerializerEx(typeof(KPTranslation)); + KPTranslation t = KPTranslation.Load(i.Tag as string, xs); + i.SubItems.Add(t.Properties.Iso6391Code); + } + catch { if (string.IsNullOrEmpty(i.Tag as string)) i.SubItems.Add("en"); } + } + m_lvLanguages.EndUpdate(); + } + + private void WindowRemoved(object sender, GwmWindowEventArgs e) + { + if ((m_kpf != null) && (e.Form is KeyPromptForm)) + m_kpf = null; + } + + #region Check for updates + /// + /// Only perform update check if last used database has to be opened automatically + /// If this is not the case, use KeePass standard check for updates + /// + private void KeyPromptFormAdded() + { + if (!PluginConfig.Active) return; + UpdateCheckType uct = UpdateCheckRequired(); + if (uct == UpdateCheckType.NotRequired) return; + if (uct == UpdateCheckType.OnlyTranslations) + { + CheckPluginLanguages(); + return; + } + m_kpf = GlobalWindowManager.TopWindow as KeyPromptForm; + UpdateCheckEx.EnsureConfigured(m_host.MainWindow); + //Try calling the internal method UpdateCheckEx.RunPriv + //==> Running this in a seperate threads does not force the user to wait + // in case of e. g. connection issues + //==> Creating this seperate thread manually allows + // - to check for completion of the update check + // - show the update window BEFORE "Open Database" window is shown + // - Skip waiting in case of e. g. connection issues + // + //As fallback the public method UpdateCheckRunEx.Run is called + //This method runs in a separate thread + //==> Update window might be shown AFTER "Open Database" window is shown + if (PluginConfig.CheckSync) + { + m_bRestartInvoke = true; + m_slUpdateCheck = CreateUpdateCheckLogger(); + PluginDebug.AddInfo("UpdateCheck start", DebugPrint); + ThreadPool.QueueUserWorkItem(new WaitCallback(CheckForUpdates)); + while (true) + { + if ((m_slUpdateCheck != null) && !m_slUpdateCheck.ContinueWork()) break; + lock (m_lock) + { + if (m_UpdateCheckStatus == UpdateCheckStatus.Checked) break; + if (m_UpdateCheckStatus == UpdateCheckStatus.Error) break; + } + } + if (m_slUpdateCheck != null) m_slUpdateCheck.EndLogging(); + PluginDebug.AddInfo("UpdateCheck finished ", DebugPrint); + } + if ((m_UpdateCheckStatus == UpdateCheckStatus.NotChecked) || (m_UpdateCheckStatus == UpdateCheckStatus.Error)) UpdateCheckEx.Run(false, null); + CheckPluginLanguages(); + } + + /// + /// Check for available updates + /// + private void CheckForUpdates(object o) + { + string sBackup = KeePass.Program.Config.Application.LastUpdateCheck; + try + { + lock (m_lock) { m_UpdateCheckStatus = UpdateCheckStatus.Checking; } + KeePass.Program.Config.Application.LastUpdateCheck = TimeUtil.SerializeUtc(DateTime.UtcNow); + MethodInfo mi = typeof(UpdateCheckEx).GetMethod("RunPriv", BindingFlags.Static | BindingFlags.NonPublic); + Type t = typeof(UpdateCheckEx).GetNestedType("UpdateCheckParams", BindingFlags.NonPublic); + ConstructorInfo c = t.GetConstructor(new Type[] { typeof(bool), typeof(Form) }); + object p = c.Invoke(new object[] { false, null }); + PluginDebug.AddInfo("UpdateCheck start RunPriv ", DebugPrint); + mi.Invoke(null, new object[] { p }); + PluginDebug.AddInfo("UpdateCheck finish RunPriv ", DebugPrint); + lock (m_lock) { m_UpdateCheckStatus = UpdateCheckStatus.Checked; } + } + catch (Exception) + { + KeePass.Program.Config.Application.LastUpdateCheck = sBackup; + lock (m_lock) { m_UpdateCheckStatus = UpdateCheckStatus.Error; } + } + } + + /// + /// Check whether searching for updates of plugins or translations shall be done + /// + /// Type of required update check + private UpdateCheckType UpdateCheckRequired() + { + UpdateCheckType result = UpdateCheckType.NotRequired; + if (m_bUpdateCheckDone) return result; + + m_bUpdateCheckDone = true; + if (!KeePass.Program.Config.Application.Start.CheckForUpdate) return result; + if (!KeePass.Program.Config.Application.Start.OpenLastFile) return result; + if (KeePass.Program.Config.Application.Start.MinimizedAndLocked) return result; + + DateTime dtNow = DateTime.UtcNow, dtLast; + string strLast = KeePass.Program.Config.Application.LastUpdateCheck; + if ((strLast.Length > 0) && TimeUtil.TryDeserializeUtc(strLast, out dtLast)) + { + if (dtNow.Date != dtLast.Date) return UpdateCheckType.Required; + return UpdateCheckType.NotRequired; + } + return UpdateCheckType.Required; + } + + private IStatusLogger CreateUpdateCheckLogger() + { + IStatusLogger sl = StatusUtil.CreateStatusDialog(m_host.MainWindow, out m_CheckProgress, + KeePass.Resources.KPRes.UpdateCheck, KeePass.Resources.KPRes.CheckingForUpd + "...", true, true); + Button btnCancel = (Button)Tools.GetControl("m_btnCancel", m_CheckProgress); + if (btnCancel != null) + { + int x = btnCancel.Right; + btnCancel.AutoSize = true; + btnCancel.Text = PluginTranslate.EnterBackgroundMode; + btnCancel.Left = x - btnCancel.Width; + } + return sl; + } + #endregion + + #region Check for new translations + private void CheckPluginLanguages() + { + PluginDebug.AddInfo("Check for updated translations - Start"); + Dictionary dTranslationsInstalled = GetInstalledTranslations(); + + Dictionary dTranslationsAvailable = new Dictionary(); + try + { + dTranslationsAvailable = GetAvailableTranslations(); + } + catch (Exception ex) + { + PluginDebug.AddError("Could not load available translations", 0, ex.Message); + return; + } + + bool bNew = false; + string CurrentLanguage = "." + m_LanguageIso.ToLowerInvariant() + ".language.xml"; + string translations = string.Empty; + List lPlugins = new List(); + foreach (KeyValuePair kvp in dTranslationsAvailable) + { + //Check plugin version + UpdateInfo ui = Plugins.Find(x => x.NameLowerInvariant == kvp.Key.Substring(0, kvp.Key.IndexOf("."))); + if (ui == null) continue; + + if (!VersionsEqual(ui.VersionAvailable, ui.VersionInstalled)) continue; + + //Current translation is installed AND a newer version is available + bNew = dTranslationsInstalled.ContainsKey(kvp.Key) && (dTranslationsInstalled[kvp.Key] < kvp.Value); + + //Current translation is not installed but available and DownloadActiveLanguage is true + bNew |= !dTranslationsInstalled.ContainsKey(kvp.Key) && PluginConfig.DownloadActiveLanguage && kvp.Key.EndsWith(CurrentLanguage); + + if (bNew && !lPlugins.Contains(ui.Name)) lPlugins.Add(ui.Name); + } + if (lPlugins.Count == 0) return; + using (TranslationUpdateForm t = new TranslationUpdateForm()) + { + t.InitEx(lPlugins); + if (t.ShowDialog() == DialogResult.OK) + { + lPlugins = t.SelectedPlugins; + UpdatePluginTranslations(PluginConfig.DownloadActiveLanguage, lPlugins); + } + } + } + + /// + /// Compare two version + /// Ignore MinorRevision if it's 0 + /// + /// 1.2.3.0 and 1.2.3 are considered equal + /// + /// + /// + /// + private bool VersionsEqual(Version vA, Version vB) + { + if (vA == null) return false; + if (vB == null) return false; + if (vA.Major != vB.Major) return false; + if (vA.Minor != vB.Minor) return false; + if ((vA.Build <= 0) && (vB.Build <= 0)) return true; + if (vA.Build != vB.Build) return false; + if ((vA.Revision <= 0) && (vB.Revision <= 0)) return true; + if (vA.Revision != vB.Revision) return false; + return true; + } + + private Dictionary GetInstalledTranslations() + { + Dictionary dTranslationsInstalled = new Dictionary(); + if (System.IO.Directory.Exists(m_PluginsTranslationsFolder)) + { + try + { + Regex r = new Regex(@"\(\d)\<\/TranslationVersion\>", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + List lTranslationsInstalled = UrlUtil.GetFilePaths(m_PluginsTranslationsFolder, "*.language.xml", System.IO.SearchOption.TopDirectoryOnly); + foreach (string lang in lTranslationsInstalled) + { + dTranslationsInstalled[UrlUtil.GetFileName(lang).ToLowerInvariant()] = 0; + string translation = System.IO.File.Exists(lang) ? System.IO.File.ReadAllText(lang) : string.Empty; + Match m = r.Match(translation); + if (m.Groups.Count != 2) continue; + long lVerInstalled = 0; + if (!long.TryParse(m.Groups[1].Value, out lVerInstalled)) continue; + dTranslationsInstalled[UrlUtil.GetFileName(lang).ToLowerInvariant()] = lVerInstalled; + } + } + catch (Exception) { } + } + if (PluginDebug.DebugMode) + { + List lT = new List(); + foreach (KeyValuePair kvp in dTranslationsInstalled) + lT.Add(kvp.Key + " - " + kvp.Value.ToString()); + PluginDebug.AddInfo("Installed languages", 0, lT.ToArray()); + } + return dTranslationsInstalled; + } + + private Dictionary GetAvailableTranslations() + { + Dictionary> dUpdateInfo = new Dictionary>(); + Dictionary dResult = new Dictionary(); + Type t = typeof(KeePass.Program).Assembly.GetType("KeePass.Util.UpdateCheckEx"); + if (t == null) + { + PluginDebug.AddError("Could not locate class 'UpdateCheckEx'", 0); + return dResult; + } + MethodInfo mi = t.GetMethod("DownloadInfoFiles", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Static); + if (mi == null) + { + PluginDebug.AddError("Could not locate method 'DownloadInfoFiles'", 0); + return dResult; + } + + List lUpdateUrls = new List(); + foreach (UpdateInfo uiPlugin in Plugins) + { + string sUrl = uiPlugin.VersionInfoURL.ToLowerInvariant(); + if (!lUpdateUrls.Contains(sUrl)) lUpdateUrls.Add(sUrl); + } + if (lUpdateUrls.Count == 0) + { + PluginDebug.AddError("Could not read plugin update url", 0); + return dResult; + } + + dUpdateInfo = mi.Invoke(null, new object[] { lUpdateUrls, null }) as Dictionary>; + + List lTranslationsNew = new List(); + string[] cSplit = new string[] { "!", "!!!" }; + foreach (KeyValuePair> kvp in dUpdateInfo) + { + if (kvp.Value == null) continue; + foreach (UpdateComponentInfo uci in kvp.Value) + { + //Plugins will be migrated from Sourceforge to Gitrhub one by one + //Format for translation version: + //Sourceforge: Lang!!!! + //Github: ! + string[] sParts = null; + if (uci.Name.StartsWith("Lang!")) + sParts = uci.Name.Substring(5).Split(cSplit, StringSplitOptions.RemoveEmptyEntries); + else + sParts = uci.Name.Split(cSplit, StringSplitOptions.RemoveEmptyEntries); + if (sParts.Length == 1) + { + UpdateInfo p = Plugins.Find(x => x.Title == sParts[0]); + if (p == null) continue; + p.VersionAvailable = new Version(StrUtil.VersionToString(uci.VerAvailable, 2)); + } + if (sParts.Length != 2) continue; + UpdateInfo ui = Plugins.Find(x => x.Title == sParts[0]); + if (ui == null) continue; + long lVer = 0; + if (!long.TryParse(StrUtil.VersionToString(uci.VerAvailable), out lVer)) continue; + dResult[(ui.NameLowerInvariant + "." + sParts[1] + ".language.xml").ToLowerInvariant()] = lVer; + } + } + if (PluginDebug.DebugMode) + { + List lT = new List(); + foreach (KeyValuePair kvp in dResult) + lT.Add(kvp.Key + " - " + kvp.Value.ToString()); + PluginDebug.AddInfo("Available languages", 0, lT.ToArray()); + } + return dResult; + } + #endregion + + #region Adjust UpdateCheckForm if required + /// + /// Show update indicator if plugins can be updated + /// + private void OnUpdateCheckFormShown(object sender, EventArgs e) + { + if (!PluginConfig.Active || !PluginConfig.OneClickUpdate) return; + CustomListViewEx lvPlugins = (CustomListViewEx)Tools.GetControl("m_lvInfo", sender as UpdateCheckForm); + if (lvPlugins == null) + { + PluginDebug.AddError("m_lvInfo not found", 0); + return; + } + else PluginDebug.AddSuccess("m_lvInfo found", 0); + if (Plugins.Count == 0) return; + SetPluginSelectionStatus(false); + bool bColumnAdded = false; + Image NoUpdate = UIUtil.CreateGrayImage(lvPlugins.SmallImageList.Images[1]); + lvPlugins.SmallImageList.Images.Add("EUCCheckMarkImage", NoUpdate); + + foreach (ListViewItem item in lvPlugins.Items) + { + PluginDebug.AddInfo("Check plugin update status", item.SubItems[0].Text, item.SubItems[1].Text); + if (!item.SubItems[1].Text.Contains(KeePass.Resources.KPRes.NewVersionAvailable)) continue; + foreach (UpdateInfo upd in Plugins) + { + if (item.SubItems[0].Text != upd.Title) continue; + if (!bColumnAdded) + { + lvPlugins.Columns.Add(PluginTranslate.PluginUpdate); + bColumnAdded = true; + } + ListViewItem.ListViewSubItem lvsiUpdate = new ListViewItem.ListViewSubItem(item, PluginTranslate.PluginUpdate); + lvsiUpdate.Tag = upd; + item.SubItems.Add(lvsiUpdate); + upd.Selected = true; + try + { + upd.VersionAvailable = new Version(item.SubItems[3].Text); + } + catch (Exception ex) + { + PluginDebug.AddError("Could not parse new version", 0, upd.Name, item.SubItems[3].Text, ex.Message); + } + break; + } + } + if (bColumnAdded) + { + UIUtil.ResizeColumns(lvPlugins, new int[] { 3, 3, 2, 2, 1 }, true); + lvPlugins.MouseClick += OnUpdateCheckFormPluginMouseClick; + lvPlugins.OwnerDraw = true; + lvPlugins.DrawSubItem += LvPlugins_DrawSubItem; + lvPlugins.DrawColumnHeader += LvPlugins_DrawColumnHeader; + ShowUpdateButton(sender as Form, true); + } + } + + private void OnUpdateCheckFormPluginMouseClick(object sender, MouseEventArgs e) + { + ListViewHitTestInfo info = (sender as ListView).HitTest(e.X, e.Y); + UpdateInfo upd = info.Item.SubItems[info.Item.SubItems.Count - 1].Tag as UpdateInfo; + if (upd == null) return; + upd.Selected = !upd.Selected; + if (!ShowUpdateButton((sender as Control).Parent as Form, Plugins.Find(x => x.Selected == true) != null)) + { + upd.Selected = !upd.Selected; + bUpdatePlugins_Click(sender, e); + } + else + (sender as ListView).Parent.Refresh(); + } + + /// + /// Show and enable Update button if possible + /// Definiton of 'possible': + /// - Update button can be added to UpdateCheckForm + /// - At least one plugin can be updated + /// - At least one updateable plugin is selected + /// + /// Reference to UpdateCheckForm + /// True, if Update button shall be enabled + /// True, if successful + private bool ShowUpdateButton(Form form, bool enable) + { + Button bUpdate = Tools.GetControl("EUCUpdateButton", form) as Button; + if (bUpdate == null) + try + { + Button bClose = Tools.GetControl("m_btnClose", form) as Button; + bUpdate = new Button(); + bUpdate.Text = PluginTranslate.PluginUpdateSelected; + bUpdate.Left = 0; + bUpdate.Top = bClose.Top; + bUpdate.Height = bClose.Height; + bUpdate.AutoSize = true; + bUpdate.Name = "EUCUpdateButton"; + bUpdate.Click += bUpdatePlugins_Click; + bClose.Parent.Controls.Add(bUpdate); + if (ShouldShieldify) + { + bUpdate.Width += DpiUtil.ScaleIntX(16); + UIUtil.SetShield(bUpdate, true); + } + bUpdate.Left = bClose.Left - bUpdate.Width - 15; + } + catch (Exception) { } + bUpdate = Tools.GetControl("EUCUpdateButton", form) as Button; + if (bUpdate == null) + { + foreach (UpdateInfo upd in Plugins) + upd.Selected = false; + CustomListViewEx lvPlugins = (CustomListViewEx)Tools.GetControl("m_lvInfo", form); + lvPlugins.OwnerDraw = false; + return false; + } + bUpdate.Enabled = enable; + return true; + } + + private void LvPlugins_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e) + { + e.DrawDefault = true; + } + + private void LvPlugins_DrawSubItem(object sender, DrawListViewSubItemEventArgs e) + { + ListView lvPlugins = sender as ListView; + e.DrawDefault = true; + if (e.ColumnIndex != lvPlugins.Items[0].SubItems.Count) return; + UpdateInfo upd = m_lPluginUpdateInfo.Find(x => x.Title == e.Item.SubItems[0].Text); + if (upd == null) return; + e.DrawDefault = false; + e.DrawBackground(); + int i = upd.Selected ? 1 : lvPlugins.SmallImageList.Images.IndexOfKey("EUCCheckMarkImage"); + UIUtil.CreateGrayImage((sender as ListView).SmallImageList.Images[1]); + var imageRect = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Height, e.Bounds.Height); + e.Graphics.DrawImage((sender as ListView).SmallImageList.Images[i], imageRect); + } + #endregion + + #region Update plugins + /// + /// Get list of installed plugins + /// + /// + public List GetInstalledPlugins() + { + m_lPluginUpdateInfo = new List(); + BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; + try + { + var PluginManager = Tools.GetField("m_pluginManager", KeePass.Program.MainForm); + var PluginList = Tools.GetField("m_vPlugins", PluginManager); + MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); + IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); + while (PluginIterator.MoveNext()) + { + Plugin result = (Plugin)Tools.GetField("m_pluginInterface", PluginIterator.Current); + if (result == null) continue; + AssemblyCompanyAttribute[] comp = (AssemblyCompanyAttribute[])result.GetType().Assembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); + AssemblyTitleAttribute[] title = (AssemblyTitleAttribute[])result.GetType().Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + if ((comp.Length != 1) || (title.Length != 1)) continue; + if (string.Compare("rookiestyle", comp[0].Company, StringComparison.InvariantCultureIgnoreCase) != 0) continue; + Type tools = result.GetType().Assembly.GetType("PluginTools.Tools"); + if (tools == null) continue; + FieldInfo fURL = tools.GetField("PluginURL"); + if (fURL == null) continue; + string URL = (string)fURL.GetValue(result); + if (string.IsNullOrEmpty(URL)) continue; + m_lPluginUpdateInfo.Add(new UpdateInfo(result.GetType().Namespace, title[0].Title, URL, result.UpdateUrl, result.GetType().Assembly.GetName().Version)); + } + } + catch (Exception ex) { PluginDebug.AddError(ex.Message); } + PluginDebug.AddInfo("Installed updateable plugins", m_lPluginUpdateInfo.ConvertAll(new Converter(UpdateInfo.GetName)).ToArray()); + return m_lPluginUpdateInfo; + } + + /// + /// Update installed plugin translations + /// + /// Download translation for currently used language even if not installed yet + public void UpdatePluginTranslations(bool bDownloadActiveLanguage, List lUpdateTranslations) + { + foreach (var upd in Plugins) + upd.Selected = (lUpdateTranslations == null) || lUpdateTranslations.Contains(upd.Name); + bool bBackup = PluginConfig.DownloadActiveLanguage; + PluginConfig.DownloadActiveLanguage = bDownloadActiveLanguage; + UpdatePlugins(true); + PluginConfig.DownloadActiveLanguage = bBackup; + foreach (var upd in Plugins) + { + if (!upd.Selected) continue; + Plugin p = (Plugin)Tools.GetPluginInstance(upd.Name); + if (p == null) continue; + Type t = p.GetType().Assembly.GetType("PluginTranslation.PluginTranslate"); + if (t == null) continue; + MethodInfo miInit = t.GetMethod("Init", BindingFlags.Static | BindingFlags.Public); + if (miInit == null) continue; + try + { + miInit.Invoke(p, new object[] { p, m_LanguageIso }); + } + catch (Exception ex) + { + PluginDebug.AddError("Refresh translation failed", 0, "Plugin: " + upd.Name, "Error: " + ex.Message); + } + } + SetPluginSelectionStatus(false); + } + + private void bUpdatePlugins_Click(object sender, EventArgs e) + { + UpdatePlugins(false); + } + + private void UpdatePlugins(bool bUpdateTranslationsOnly) + { + PluginDebug.AddInfo("UpdatePlugins start ", DebugPrint); + Form fUpdateLog = null; + m_slUpdatePlugins = StatusUtil.CreateStatusDialog(GlobalWindowManager.TopWindow, out fUpdateLog, PluginTranslate.PluginUpdateCaption, string.Empty, true, true); + + bool bUseTemp = false; + bool success = false; + string sTempPluginsFolder = m_PluginsFolder; + string sTempPluginsTranslationsFolder = m_PluginsTranslationsFolder; + + ThreadStart ts = new ThreadStart(() => + { + m_slUpdatePlugins.StartLogging(PluginTranslate.PluginUpdateCaption, false); + //try writing to plugin folder + string sTempFile = m_PluginsFolder + "EarlyUpdateCheckTest.txt"; + try + { + System.IO.File.WriteAllText(sTempFile, "Test file to check for write access"); + } + catch (Exception) { bUseTemp = true; } + if (!bUseTemp) System.IO.File.Delete(sTempFile); + + //define working folders + if (bUseTemp) + { + sTempPluginsFolder = UrlUtil.GetTempPath(); + sTempPluginsFolder = UrlUtil.EnsureTerminatingSeparator(sTempPluginsFolder, false); + sTempPluginsFolder += System.IO.Path.GetRandomFileName(); + sTempPluginsFolder = UrlUtil.EnsureTerminatingSeparator(sTempPluginsFolder, false); + System.IO.Directory.CreateDirectory(sTempPluginsFolder); + sTempPluginsTranslationsFolder = sTempPluginsFolder + "Translations"; + sTempPluginsTranslationsFolder = UrlUtil.EnsureTerminatingSeparator(sTempPluginsTranslationsFolder, false); + System.IO.Directory.CreateDirectory(sTempPluginsTranslationsFolder); + } + PluginDebug.AddInfo("Use temp folder", bUseTemp.ToString(), sTempPluginsFolder, DebugPrint); + + //Download files + foreach (UpdateInfo upd in Plugins) + { + if (!upd.Selected) continue; + success |= UpdatePlugin(upd, sTempPluginsFolder, sTempPluginsTranslationsFolder, bUpdateTranslationsOnly); + } + }); + Thread t = new Thread(ts); + t.Start(); + while (true && t.IsAlive) + { + if (!m_slUpdatePlugins.ContinueWork()) + { + t.Abort(); + break; + } + } + if (m_slUpdatePlugins != null) + { + m_slUpdatePlugins.EndLogging(); + m_slUpdatePlugins = null; + } + if (fUpdateLog != null) fUpdateLog.Dispose(); + + //Move files from temp folder to plugin folder + if (bUseTemp) + { + success = false; + if (WinUtil.IsAtLeastWindowsVista && + (NativeMethods.ShieldifyNativeDialog(DialogResult.Yes, () => Tools.AskYesNo(PluginTranslate.TryUAC, PluginTranslate.PluginUpdateCaption)) == DialogResult.Yes)) + { + success = FileCopier.CopyFiles(sTempPluginsFolder, m_PluginsFolder); + if (!success) + { + if (Tools.AskYesNo(PluginTranslate.PluginUpdateFailed, PluginTranslate.PluginUpdateCaption) == DialogResult.Yes) + { + System.Diagnostics.Process.Start(sTempPluginsFolder); + } + } + } + else if (Tools.AskYesNo(PluginTranslate.OpenTempFolder, PluginTranslate.PluginUpdateCaption) == DialogResult.Yes) + { + System.Diagnostics.Process.Start(sTempPluginsFolder); + } + } + + //Restart KeePass to use new plugin versions + PluginDebug.AddInfo("Update finished", "Succes: " + success.ToString(), DebugPrint); + if (success && !bUpdateTranslationsOnly) + { + if (Tools.AskYesNo(PluginTranslate.PluginUpdateSuccess, PluginTranslate.PluginUpdateCaption) == DialogResult.Yes) + { + if (m_bRestartInvoke) + { + m_host.MainWindow.Invoke(new KeePassLib.Delegates.VoidDelegate(Restart)); + } + else + Restart(); + } + } + } + + private delegate string GetUpdateUrl(string baseurl, UpdateInfo upd, string language); + private string GetUpdateUrlSF(string baseurl, UpdateInfo upd, string language) + { + if (language == null) + return baseurl + "files/latest/download"; + return baseurl + "files/Translations/" + language + "/download"; + } + + private string GetUpdateUrlGH(string baseurl, UpdateInfo upd, string language) + { + if (language == null) + return baseurl + "releases/download/v" + upd.VersionAvailable.ToString() + "/" + upd.Name + ".plgx"; + return baseurl.Replace("github.com", "raw.githubusercontent.com") + "master/Translations/" + language; + } + + /// + /// Update a single plugin + /// + /// Update information for plugin + /// Target folder for plugin file + /// Target folder for plugin translations + /// Only download newest translations + /// + public bool UpdatePlugin(UpdateInfo upd, string sPluginFolder, string sTranslationFolder, bool bTranslationsOnly) + { + string url = UrlUtil.EnsureTerminatingSeparator(upd.URL, true); + + GetUpdateUrl guu = null; + if (url.ToLowerInvariant().Contains("sourceforge")) + guu = GetUpdateUrlSF; + else if (url.ToLowerInvariant().Contains("github")) + guu = GetUpdateUrlGH; + else + { + PluginDebug.AddError("Plugin url not supported", 0, upd.URL); + return false; + } + + //Get installed translations + List lTranslations = new List(); + if (System.IO.Directory.Exists(m_PluginsTranslationsFolder)) + { + try + { + lTranslations = UrlUtil.GetFilePaths(m_PluginsTranslationsFolder, upd.Name + "*.language.xml", System.IO.SearchOption.TopDirectoryOnly); + } + catch (Exception) { } + } + bool ok = false; + + //Download plugin + if (!bTranslationsOnly) + { + m_slUpdatePlugins.SetText(string.Format(PluginTranslate.PluginUpdating, upd.Title, upd.Name + ".plgx"), LogStatusType.Info); + if (!m_slUpdatePlugins.ContinueWork()) return ok; + if (!DownloadFile(guu(url, upd, null), sPluginFolder + upd.Name + ".plgx")) + { + Tools.ShowError(string.Format(PluginTranslate.PluginUpdateFailedSpecific, upd.Title), PluginTranslate.PluginUpdateCaption); + } + else + ok = true; + } + if (!m_slUpdatePlugins.ContinueWork()) return ok; + + //Download translations + foreach (string lang in lTranslations) + { + string langUrl = lang.Substring(m_PluginsTranslationsFolder.Length); + m_slUpdatePlugins.SetText(string.Format(PluginTranslate.PluginUpdating, upd.Title, langUrl), LogStatusType.Info); + if (!m_slUpdatePlugins.ContinueWork()) return ok; + if (!DownloadFile(guu(url, upd, langUrl), sTranslationFolder + langUrl)) + Tools.ShowError(string.Format(PluginTranslate.PluginTranslationUpdateFailed, upd.Title, langUrl), PluginTranslate.PluginUpdateCaption); + } + + //If required, download translation for currently used language + string CurrentTranslation = m_PluginsTranslationsFolder + upd.Name + "." + m_LanguageIso + ".language.xml"; + if (PluginConfig.DownloadActiveLanguage && !lTranslations.Contains(CurrentTranslation)) + { + string langUrl = CurrentTranslation.Substring(m_PluginsTranslationsFolder.Length); + m_slUpdatePlugins.SetText(string.Format(PluginTranslate.PluginUpdating, upd.Title, langUrl), LogStatusType.Info); + if (!m_slUpdatePlugins.ContinueWork()) return ok; + DownloadFile(guu(url, upd, langUrl), sTranslationFolder + langUrl); + } + return ok; + } + + /// + /// Download single file + /// + /// + /// + /// + private bool DownloadFile(string source, string target) + { + const int MAXATTEMPTS = 3; + int iAttempts = 0; + while (iAttempts++ < MAXATTEMPTS) + { + try + { + KeePassLib.Serialization.IOConnectionInfo ioc = KeePassLib.Serialization.IOConnectionInfo.FromPath(source); + System.IO.Stream s = KeePassLib.Serialization.IOConnection.OpenRead(ioc); + if (s == null) throw new InvalidOperationException(); + System.IO.MemoryStream ms = new System.IO.MemoryStream(); + MemUtil.CopyStream(s, ms); + s.Close(); + byte[] pb = ms.ToArray(); + ms.Close(); + System.IO.File.WriteAllBytes(target, pb); + PluginDebug.AddInfo("Download success", 0, "Source: " + source, "Target: " + target, "Download attempt: " + iAttempts.ToString()); + return true; + } + catch (Exception ex) + { + PluginDebug.AddInfo("Download failed", 0, "Source: " + source, "Target: " + target, "Download attempt: " + iAttempts.ToString(), ex.Message); + + System.Net.WebException exWeb = ex as System.Net.WebException; + if (exWeb == null) continue; + System.Net.HttpWebResponse wrResponse = exWeb.Response as System.Net.HttpWebResponse; + if ((wrResponse == null) || (wrResponse.StatusCode != System.Net.HttpStatusCode.NotFound)) continue; + iAttempts = MAXATTEMPTS; + } + } + return false; + } + + private void Restart() + { + PluginDebug.AddInfo("Restart started", DebugPrint); + if (m_kpf != null) + { + m_kpf.DialogResult = DialogResult.Cancel; + m_kpf.Close(); + m_kpf.Dispose(); + Application.DoEvents(); + GlobalWindowManager.RemoveWindow(m_kpf); + } + if (m_slUpdateCheck != null) + { + m_slUpdateCheck.EndLogging(); + } + FieldInfo fi = m_host.MainWindow.GetType().GetField("m_bRestart", BindingFlags.NonPublic | BindingFlags.Instance); + if (fi != null) + { + PluginDebug.AddInfo("Restart started, m_bRestart found", DebugPrint); + HandleMutex(true); + fi.SetValue(m_host.MainWindow, true); + m_host.MainWindow.ProcessAppMessage((IntPtr)KeePass.Program.AppMessage.Exit, IntPtr.Zero); + HandleMutex(false); + } + else + PluginDebug.AddError("Restart started, m_bRestart not found" + DebugPrint); + } + + /// + /// Release (and potentially restore) the mutex used for limiting KeePass to a single instance + /// In some cases the restart with WinUtil.Restart is done while the global mutex is not yet released + /// + /// + private void HandleMutex(bool release) + { + List lStrings = new List(); + lStrings.Add("Mutex: " + KeePass.App.AppDefs.MutexName); + lStrings.Add("Release: " + release.ToString()); + lStrings.Add("Single Instance: " + KeePass.Program.Config.Integration.LimitToSingleInstance.ToString()); + if (!KeePass.Program.Config.Integration.LimitToSingleInstance) + { + lStrings.Add("Action required: No"); + PluginDebug.AddInfo("Handle global mutex", 0, lStrings.ToArray()); + return; + } + if (release) + { + bool bSuccess = GlobalMutexPool.ReleaseMutex(KeePass.App.AppDefs.MutexName); + lStrings.Add("Action required: Yes"); + lStrings.Add("Success: " + bSuccess.ToString()); + PluginDebug.AddInfo("Handle global mutex", 0, lStrings.ToArray()); + return; + } + else if (m_host.MainWindow.DocumentManager.Documents.Count > 0) + { + //Only recreate mutex if at least document is loaded (lock flag is not relevant here) + //If no db is open, Restart is in progress already + lStrings.Add("Action required: Yes"); + lStrings.Add("Success: See next entry"); + PluginDebug.AddInfo("Handle global mutex", 0, lStrings.ToArray()); + Thread t = new Thread(new ThreadStart(() => + { + Thread.Sleep(1000); + bool bSuccess = GlobalMutexPool.CreateMutex(KeePass.App.AppDefs.MutexName, true); + PluginDebug.AddInfo("Handle global mutex", 0, "Recreate mutex sucfessful: " + bSuccess.ToString()); + })); + t.Start(); + return; + } + lStrings.Add("Action required: No"); + PluginDebug.AddInfo("Handle global mutex", 0, lStrings.ToArray()); + } + + private void SetPluginSelectionStatus(bool select) + { + foreach (var p in Plugins) p.Selected = select; + } + #endregion + + #region Configuration + private void OptionsFormShown(object sender, Tools.OptionsFormsEventArgs e) + { + Options options = new Options(); + options.gCheckSync.Checked = PluginConfig.Active; + options.cbCheckSync.Checked = PluginConfig.CheckSync; + options.gOneClickUpdate.Checked = PluginConfig.OneClickUpdate; + options.cbDownloadCurrentTranslation.Checked = PluginConfig.DownloadActiveLanguage; + options.Plugin = this; + Tools.AddPluginToOptionsForm(this, options); + } + + private void OptionsFormClosed(object sender, Tools.OptionsFormsEventArgs e) + { + if (e.form.DialogResult != DialogResult.OK) return; + bool shown = false; + Options options = (Options)Tools.GetPluginFromOptions(this, out shown); + if (!shown) return; + PluginConfig.Active = options.gCheckSync.Checked; + PluginConfig.CheckSync = options.cbCheckSync.Checked; + PluginConfig.OneClickUpdate = options.gOneClickUpdate.Checked; + PluginConfig.DownloadActiveLanguage = options.cbDownloadCurrentTranslation.Checked; + PluginConfig.Write(); + } + #endregion + + public override void Terminate() + { + if (m_host == null) return; + Deactivate(); + PluginDebug.SaveOrShow(); + m_host = null; + } + + public void Deactivate() + { + GlobalWindowManager.WindowAdded -= WindowAdded; + m_host.MainWindow.ToolsMenu.DropDownItems.Remove(m_tsMenu); + m_tsMenu.Dispose(); + + Tools.OptionsFormShown -= OptionsFormShown; + Tools.OptionsFormClosed -= OptionsFormClosed; + } + + public override string UpdateUrl + { + get { return "https://raw.githubusercontent.com/rookiestyle/earlyupdatecheck/master/version.info"; } + } + + public override Image SmallIcon + { + get { return m_tsMenu.Image; } + } + + private string DebugPrint + { + get + { + string result = "DifferentThread: {0}, Check status: {1}"; + lock(m_lock) + { + result = string.Format(result, m_bRestartInvoke.ToString(), m_UpdateCheckStatus.ToString()); + } + return result; + } + } + } +} \ No newline at end of file diff --git a/src/EarlyUpdateCheck.csproj b/src/EarlyUpdateCheck.csproj new file mode 100644 index 0000000..8df3eec --- /dev/null +++ b/src/EarlyUpdateCheck.csproj @@ -0,0 +1,122 @@ + + + + + 5 + + + + + + 2.31 + 4.0 + + + + + {78C152F3-EAF8-4FFC-9BE3-F5DC0CD66E5D} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Debug + AnyCPU + 2.0 + Library + EarlyUpdateCheck + EarlyUpdateCheck + v4.5 + Properties + False + False + False + OnBuildSuccess + False + False + False + obj\$(Configuration)\ + 4 + + + + AnyCPU + 4194304 + False + Auto + 4096 + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + Project + + + bin\Release\ + False + None + False + True + TRACE + obj\ + + + none + true + ..\..\KeePass_Release\Plugins\ + + + ..\..\KeePass_Debug\Plugins\ + false + full + + + pdbonly + true + + + + + Form + + + TranslationUpdateForm.cs + + + + + UserControl + + + Options.cs + + + + + + + + + + + + + + + 2.45.0.30441 + + + + 1.0.0 + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Options.Designer.cs b/src/Options.Designer.cs new file mode 100644 index 0000000..9e1f0d3 --- /dev/null +++ b/src/Options.Designer.cs @@ -0,0 +1,187 @@ +namespace EarlyUpdateCheck +{ + partial class Options + { + /// + /// Erforderliche Designervariable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Verwendete Ressourcen bereinigen. + /// + /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Vom Komponenten-Designer generierter Code + + /// + /// Erforderliche Methode für die Designerunterstützung. + /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. + /// + private void InitializeComponent() + { + this.pCheckSync = new System.Windows.Forms.Panel(); + this.pOneClickUpdate = new System.Windows.Forms.Panel(); + this.gOneClickUpdate = new RookieUI.CheckedGroupBox(); + this.bUpdateTranslations = new System.Windows.Forms.Button(); + this.cbDownloadCurrentTranslation = new System.Windows.Forms.CheckBox(); + this.tbOneClickUpdateDesc = new System.Windows.Forms.TextBox(); + this.gCheckSync = new RookieUI.CheckedGroupBox(); + this.tbCheckSyncDesc = new System.Windows.Forms.TextBox(); + this.cbCheckSync = new System.Windows.Forms.CheckBox(); + this.pCheckSync.SuspendLayout(); + this.pOneClickUpdate.SuspendLayout(); + this.gOneClickUpdate.SuspendLayout(); + this.gCheckSync.SuspendLayout(); + this.SuspendLayout(); + // + // pCheckSync + // + this.pCheckSync.AutoSize = true; + this.pCheckSync.Controls.Add(this.gCheckSync); + this.pCheckSync.Dock = System.Windows.Forms.DockStyle.Top; + this.pCheckSync.Location = new System.Drawing.Point(3, 3); + this.pCheckSync.Name = "pCheckSync"; + this.pCheckSync.Padding = new System.Windows.Forms.Padding(0, 5, 0, 0); + this.pCheckSync.Size = new System.Drawing.Size(747, 174); + this.pCheckSync.TabIndex = 8; + // + // pOneClickUpdate + // + this.pOneClickUpdate.AutoSize = true; + this.pOneClickUpdate.Controls.Add(this.gOneClickUpdate); + this.pOneClickUpdate.Dock = System.Windows.Forms.DockStyle.Top; + this.pOneClickUpdate.Location = new System.Drawing.Point(3, 177); + this.pOneClickUpdate.Name = "pOneClickUpdate"; + this.pOneClickUpdate.Padding = new System.Windows.Forms.Padding(0, 5, 0, 0); + this.pOneClickUpdate.Size = new System.Drawing.Size(747, 198); + this.pOneClickUpdate.TabIndex = 9; + // + // gOneClickUpdate + // + this.gOneClickUpdate.CheckboxOffset = new System.Drawing.Point(5, 0); + this.gOneClickUpdate.Checked = true; + this.gOneClickUpdate.Controls.Add(this.bUpdateTranslations); + this.gOneClickUpdate.Controls.Add(this.cbDownloadCurrentTranslation); + this.gOneClickUpdate.Controls.Add(this.tbOneClickUpdateDesc); + this.gOneClickUpdate.DisableControlsIfUnchecked = false; + this.gOneClickUpdate.Dock = System.Windows.Forms.DockStyle.Top; + this.gOneClickUpdate.Location = new System.Drawing.Point(0, 5); + this.gOneClickUpdate.Name = "gOneClickUpdate"; + this.gOneClickUpdate.Padding = new System.Windows.Forms.Padding(15, 5, 15, 5); + this.gOneClickUpdate.Size = new System.Drawing.Size(747, 193); + this.gOneClickUpdate.TabIndex = 4; + this.gOneClickUpdate.TabStop = false; + this.gOneClickUpdate.Text = "SimpleUpdate"; + // + // bUpdateTranslations + // + this.bUpdateTranslations.AutoSize = true; + this.bUpdateTranslations.Dock = System.Windows.Forms.DockStyle.Top; + this.bUpdateTranslations.Location = new System.Drawing.Point(10, 158); + this.bUpdateTranslations.Name = "bUpdateTranslations"; + this.bUpdateTranslations.Size = new System.Drawing.Size(727, 30); + this.bUpdateTranslations.TabIndex = 7; + this.bUpdateTranslations.Text = "Translation update"; + this.bUpdateTranslations.UseVisualStyleBackColor = true; + this.bUpdateTranslations.Click += new System.EventHandler(this.bUpdateTranslations_Click); + // + // cbDownloadCurrentTranslation + // + this.cbDownloadCurrentTranslation.AutoSize = true; + this.cbDownloadCurrentTranslation.Dock = System.Windows.Forms.DockStyle.Top; + this.cbDownloadCurrentTranslation.Location = new System.Drawing.Point(10, 134); + this.cbDownloadCurrentTranslation.Name = "cbDownloadCurrentTranslation"; + this.cbDownloadCurrentTranslation.Size = new System.Drawing.Size(727, 24); + this.cbDownloadCurrentTranslation.TabIndex = 5; + this.cbDownloadCurrentTranslation.Text = "Download selected language"; + this.cbDownloadCurrentTranslation.UseVisualStyleBackColor = true; + // + // tbOneClickUpdateDesc + // + this.tbOneClickUpdateDesc.Dock = System.Windows.Forms.DockStyle.Top; + this.tbOneClickUpdateDesc.Location = new System.Drawing.Point(10, 24); + this.tbOneClickUpdateDesc.Multiline = true; + this.tbOneClickUpdateDesc.Name = "tbOneClickUpdateDesc"; + this.tbOneClickUpdateDesc.ReadOnly = true; + this.tbOneClickUpdateDesc.Size = new System.Drawing.Size(727, 110); + this.tbOneClickUpdateDesc.TabIndex = 6; + // + // gCheckSync + // + this.gCheckSync.CheckboxOffset = new System.Drawing.Point(5, 0); + this.gCheckSync.Checked = true; + this.gCheckSync.Controls.Add(this.tbCheckSyncDesc); + this.gCheckSync.Controls.Add(this.cbCheckSync); + this.gCheckSync.DisableControlsIfUnchecked = false; + this.gCheckSync.Dock = System.Windows.Forms.DockStyle.Top; + this.gCheckSync.Location = new System.Drawing.Point(0, 5); + this.gCheckSync.Name = "gCheckSync"; + this.gCheckSync.Padding = new System.Windows.Forms.Padding(15, 5, 15, 5); + this.gCheckSync.Size = new System.Drawing.Size(747, 169); + this.gCheckSync.TabIndex = 3; + this.gCheckSync.TabStop = false; + this.gCheckSync.Text = "CheckSync"; + this.gCheckSync.CheckedChanged += new System.EventHandler(this.gCheckSync_CheckedChanged); + // + // tbCheckSyncDesc + // + this.tbCheckSyncDesc.Dock = System.Windows.Forms.DockStyle.Fill; + this.tbCheckSyncDesc.Location = new System.Drawing.Point(10, 48); + this.tbCheckSyncDesc.Multiline = true; + this.tbCheckSyncDesc.Name = "tbCheckSyncDesc"; + this.tbCheckSyncDesc.ReadOnly = true; + this.tbCheckSyncDesc.Size = new System.Drawing.Size(727, 116); + this.tbCheckSyncDesc.TabIndex = 3; + // + // cbCheckSync + // + this.cbCheckSync.AutoSize = true; + this.cbCheckSync.Dock = System.Windows.Forms.DockStyle.Top; + this.cbCheckSync.Location = new System.Drawing.Point(10, 24); + this.cbCheckSync.Name = "cbCheckSync"; + this.cbCheckSync.Size = new System.Drawing.Size(727, 24); + this.cbCheckSync.TabIndex = 2; + this.cbCheckSync.Text = "CheckSync"; + this.cbCheckSync.UseVisualStyleBackColor = true; + // + // Options + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.pOneClickUpdate); + this.Controls.Add(this.pCheckSync); + this.Name = "Options"; + this.Padding = new System.Windows.Forms.Padding(3); + this.Size = new System.Drawing.Size(753, 480); + this.pCheckSync.ResumeLayout(false); + this.pOneClickUpdate.ResumeLayout(false); + this.gOneClickUpdate.ResumeLayout(false); + this.gOneClickUpdate.PerformLayout(); + this.gCheckSync.ResumeLayout(false); + this.gCheckSync.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + internal RookieUI.CheckedGroupBox gCheckSync; + internal System.Windows.Forms.CheckBox cbCheckSync; + private System.Windows.Forms.TextBox tbCheckSyncDesc; + internal RookieUI.CheckedGroupBox gOneClickUpdate; + private System.Windows.Forms.TextBox tbOneClickUpdateDesc; + internal System.Windows.Forms.CheckBox cbDownloadCurrentTranslation; + private System.Windows.Forms.Button bUpdateTranslations; + private System.Windows.Forms.Panel pCheckSync; + private System.Windows.Forms.Panel pOneClickUpdate; + } +} diff --git a/src/Options.cs b/src/Options.cs new file mode 100644 index 0000000..8844004 --- /dev/null +++ b/src/Options.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Windows.Forms; +using PluginTranslation; + +namespace EarlyUpdateCheck +{ + public partial class Options : UserControl + { + public EarlyUpdateCheckExt Plugin = null; + public Options() + { + InitializeComponent(); + gCheckSync.Text = PluginTranslate.Active; + cbCheckSync.Text = PluginTranslate.CheckSync; + tbCheckSyncDesc.Lines = PluginTranslate.CheckSyncDesc.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + gOneClickUpdate.Text = PluginTranslate.PluginUpdateOneClick; + tbOneClickUpdateDesc.Lines = PluginTranslate.PluginUpdateOneClickDesc.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + if (string.IsNullOrEmpty(KeePass.Program.Translation.Properties.Iso6391Code)) + cbDownloadCurrentTranslation.Text = string.Format(PluginTranslate.TranslationDownload_DownloadCurrent, "English"); + else + cbDownloadCurrentTranslation.Text = string.Format(PluginTranslate.TranslationDownload_DownloadCurrent, KeePass.Program.Translation.Properties.NameNative); + bUpdateTranslations.Text = PluginTranslate.TranslationDownload_Update; + if (EarlyUpdateCheckExt.ShouldShieldify) + KeePass.UI.UIUtil.SetShield(bUpdateTranslations, true); + } + + private void bUpdateTranslations_Click(object sender, EventArgs e) + { + List lPlugins = new List(); + foreach (UpdateInfo ui in Plugin.Plugins) + { if (ui == null) continue; + if (!lPlugins.Contains(ui.Name)) lPlugins.Add(ui.Name); + } + using (TranslationUpdateForm t = new TranslationUpdateForm()) + { + t.InitEx(lPlugins); + if (t.ShowDialog() == DialogResult.OK) + { + lPlugins = t.SelectedPlugins; + Plugin.UpdatePluginTranslations(PluginConfig.DownloadActiveLanguage, lPlugins); + } + } + } + + private void gCheckSync_CheckedChanged(object sender, RookieUI.CheckedGroupCheckEventArgs e) + { + cbCheckSync.Enabled = gCheckSync.Checked; + } + } +} diff --git a/src/PluginTools.cs b/src/PluginTools.cs new file mode 100644 index 0000000..3ea6c3c --- /dev/null +++ b/src/PluginTools.cs @@ -0,0 +1,885 @@ +using KeePass.Forms; +using KeePass.UI; +using KeePassLib.Utility; +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +namespace PluginTools +{ + public static class Tools + { + public static Version KeePassVersion { get; private set; } + public static string DefaultCaption = string.Empty; + public static string PluginURL = string.Empty; + public static string KeePassLanguageIso6391 { get; private set; } + + private static bool MonoWorkaroundRequired = KeePassLib.Native.NativeLib.IsUnix(); + + static Tools() + { + KeePass.UI.GlobalWindowManager.WindowAdded += OnWindowAdded; + KeePass.UI.GlobalWindowManager.WindowRemoved += OnWindowRemoved; + KeePassVersion = typeof(KeePass.Program).Assembly.GetName().Version; + KeePassLanguageIso6391 = KeePass.Program.Translation.Properties.Iso6391Code; + if (string.IsNullOrEmpty(KeePassLanguageIso6391)) KeePassLanguageIso6391 = "en"; + m_sPuginClassname = typeof(Tools).Assembly.GetName().Name + "Ext"; + } + + #region Form and field handling + public static object GetField(string field, object obj) + { + BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; + return GetField(field, obj, bf); + } + + public static object GetField(string field, object obj, BindingFlags bf) + { + if (obj == null) return null; + FieldInfo fi = obj.GetType().GetField(field, bf); + if (fi == null) return null; + return fi.GetValue(obj); + } + + public static Control GetControl(string control) + { + return GetControl(control, KeePass.Program.MainForm); + } + + public static Control GetControl(string control, Control form) + { + if (form == null) return null; + if (string.IsNullOrEmpty(control)) return null; + Control[] cntrls = form.Controls.Find(control, true); + if (cntrls.Length == 0) return null; + return cntrls[0]; + } + + public static ToolStripMenuItem FindToolStripMenuItem(ToolStripItemCollection tsic, string key, bool searchAllChildren) + { + if (tsic == null) return null; + ToolStripItem[] tsi = FindToolStripMenuItems(tsic, key, searchAllChildren); + if (tsi.Length > 0) return tsi[0] as ToolStripMenuItem; + return null; + } + + public static ToolStripItem[] FindToolStripMenuItems(ToolStripItemCollection tsic, string key, bool searchAllChildren) + { + if (tsic == null) return new ToolStripItem[] { }; + ToolStripItem[] tsi = tsic.Find(key, searchAllChildren); + if (!MonoWorkaroundRequired || !searchAllChildren) return tsi; + + //Mono does not support 'searchAllChildren' for ToolStripItemCollection + //Iterate over all items and search for given item + List lItems = new List(tsi); + foreach (var item in tsic) + { + ToolStripMenuItem tsmi = item as ToolStripMenuItem; + if (tsmi == null) continue; + lItems.AddRange(FindToolStripMenuItems(tsmi.DropDownItems, key, searchAllChildren)); + } + return lItems.ToArray(); + } + + #endregion + + #region Plugin options and instance + public static object GetPluginInstance(string PluginName) + { + string comp = PluginName + "." + PluginName + "Ext"; + BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; + try + { + var PluginManager = GetField("m_pluginManager", KeePass.Program.MainForm); + var PluginList = GetField("m_vPlugins", PluginManager); + MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); + IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); + while (PluginIterator.MoveNext()) + { + object result = GetField("m_pluginInterface", PluginIterator.Current); + if (comp == result.GetType().ToString()) return result; + } + } + + catch (Exception) { } + return null; + } + + public static Dictionary GetLoadedPluginsName() + { + Dictionary dPlugins = new Dictionary(); + BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic; + try + { + var PluginManager = GetField("m_pluginManager", KeePass.Program.MainForm); + var PluginList = GetField("m_vPlugins", PluginManager); + MethodInfo IteratorMethod = PluginList.GetType().GetMethod("System.Collections.Generic.IEnumerable.GetEnumerator", bf); + IEnumerator PluginIterator = (IEnumerator)(IteratorMethod.Invoke(PluginList, null)); + while (PluginIterator.MoveNext()) + { + object result = GetField("m_pluginInterface", PluginIterator.Current); + dPlugins[result.GetType().FullName] = result.GetType().Assembly.GetName().Version; + } + } + catch (Exception) { } + return dPlugins; + } + + + public static event EventHandler OptionsFormShown; + public static event EventHandler OptionsFormClosed; + + private static bool OptionsEnabled = (KeePass.Program.Config.UI.UIFlags & (ulong)KeePass.App.Configuration.AceUIFlags.DisableOptions) != (ulong)KeePass.App.Configuration.AceUIFlags.DisableOptions; + private static bool m_ActivatePluginTab = false; + private static string m_sPuginClassname = string.Empty; + private static OptionsForm m_of = null; + private const string c_tabRookiestyle = "m_tabRookiestyle"; + private const string c_tabControlRookiestyle = "m_tabControlRookiestyle"; + private static string m_TabPageName = string.Empty; + private static bool m_OptionsShown = false; + private static bool m_PluginContainerShown = false; + + public static void AddPluginToOptionsForm(KeePass.Plugins.Plugin p, UserControl uc) + { + m_OptionsShown = m_PluginContainerShown = false; + TabPage tPlugin = new TabPage(DefaultCaption); + tPlugin.CreateControl(); + tPlugin.Name = m_TabPageName = c_tabRookiestyle + p.GetType().Name; + uc.Dock = DockStyle.Fill; + uc.Padding = new Padding(15, 10, 15, 10); + tPlugin.Controls.Add(uc); + TabControl tcPlugins = AddPluginTabContainer(); + int i = 0; + bool insert = false; + for (int j = 0; j < tcPlugins.TabPages.Count; j++) + { + if (string.Compare(tPlugin.Text, tcPlugins.TabPages[j].Text, StringComparison.CurrentCultureIgnoreCase) < 0) + { + i = j; + insert = true; + break; + } + } + if (!insert) i = tcPlugins.TabPages.Count; + tcPlugins.TabPages.Insert(i, tPlugin); + AddPluginToOverview(tPlugin.Name.Replace(c_tabRookiestyle, string.Empty), tcPlugins); + if (p.SmallIcon != null) + { + tcPlugins.ImageList.Images.Add(tPlugin.Name, p.SmallIcon); + tPlugin.ImageKey = tPlugin.Name; + } + TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; + if (!string.IsNullOrEmpty(PluginURL)) AddPluginLink(uc); + } + + public static void AddPluginToOverview(string sPluginName) + { + AddPluginToOverview(sPluginName, null); + } + + private static void AddPluginToOverview(string sPluginName, TabControl tcPlugins) + { + if (tcPlugins == null) tcPlugins = AddPluginTabContainer(); + TabPage tpOverview = null; + ListView lv = null; + string sTabName = c_tabRookiestyle + "_PluginOverview"; + string sListViewName = c_tabRookiestyle + "_PluginOverviewListView"; + if (tcPlugins.TabPages.ContainsKey(sTabName)) + { + tpOverview = tcPlugins.TabPages[sTabName]; + lv = (ListView)tpOverview.Controls.Find(sListViewName, true)[0]; + } + else + { + tpOverview = new TabPage("Overview"); + tpOverview.CreateControl(); + tpOverview.Name = sTabName; + UserControl uc = new UserControl(); + uc.Dock = DockStyle.Fill; + uc.Padding = new Padding(15, 10, 15, 10); + tpOverview.Controls.Add(uc); + lv = new ListView(); + lv.Name = sListViewName; + lv.Dock = DockStyle.Fill; + lv.View = View.Details; + lv.Columns.Add("Plugin"); + lv.Columns.Add("Version"); + lv.CheckBoxes = true; + tpOverview.Layout += TpOverview_Layout; + Label lInfo = new Label(); + lInfo.Text = "Use the checkbox to activate/deactivate debug mode"; + lInfo.Dock = DockStyle.Bottom; + uc.Controls.Add(lv); + uc.Controls.Add(lInfo); + } + lv.ItemCheck += Lv_ItemCheck; + lv.Sorting = SortOrder.Ascending; + lv.FullRowSelect = true; + ListViewItem lvi = new ListViewItem(); + lvi.Name = sPluginName; + lvi.Checked = PluginDebug.DebugMode; + lvi.Text = DefaultCaption; + Version v = new Version(0, 0); + GetLoadedPluginsName().TryGetValue(sPluginName.Replace("Ext", string.Empty) + "." + sPluginName, out v); + string ver = v.ToString(); + if (ver.EndsWith(".0")) ver = ver.Substring(0, ver.Length - 2); + else ver += " (Dev)"; + lvi.SubItems.Add(ver); + lv.Items.Add(lvi); + tcPlugins.TabPages.Remove(tpOverview); + tcPlugins.TabPages.Add(tpOverview); + } + + private static void TpOverview_Layout(object sender, LayoutEventArgs e) + { + string sListViewName = c_tabRookiestyle + "_PluginOverviewListView"; + ListView lv = (sender as TabPage).Controls.Find(sListViewName, true)[0] as ListView; + lv.BeginUpdate(); + lv.Columns[1].DisplayIndex = 0; + lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); + int w = lv.Columns[1].Width; + lv.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); + lv.Columns[1].Width = Math.Max(w, lv.Columns[1].Width); + lv.Columns[0].Width = lv.ClientSize.Width - lv.Columns[1].Width; + if (lv.Columns[0].Width < 150) + { + lv.Columns[1].Width = 100; + lv.Columns[0].Width = lv.ClientSize.Width - lv.Columns[1].Width; + } + lv.Columns[1].DisplayIndex = 1; + lv.EndUpdate(); + } + + private static void Lv_ItemCheck(object sender, ItemCheckEventArgs e) + { + ListViewItem lvi = (sender as ListView).Items[e.Index]; + if (lvi == null) return; + if (lvi.Text != DefaultCaption) return; + PluginDebug.DebugMode = e.NewValue == CheckState.Checked; + } + + private static void OnPluginTabsSelected(object sender, TabControlEventArgs e) + { + m_OptionsShown |= (e.TabPage.Name == m_TabPageName); + m_PluginContainerShown |= (m_OptionsShown || (e.TabPage.Name == c_tabRookiestyle)); + } + + public static UserControl GetPluginFromOptions(KeePass.Plugins.Plugin p, out bool PluginOptionsShown) + { + PluginOptionsShown = m_OptionsShown && m_PluginContainerShown; + TabPage tPlugin = Tools.GetControl(c_tabRookiestyle + p.GetType().Name, m_of) as TabPage; + if (tPlugin == null) return null; + return tPlugin.Controls[0] as UserControl; + } + + public static void ShowOptions() + { + m_ActivatePluginTab = true; + if (OptionsEnabled) + KeePass.Program.MainForm.ToolsMenu.DropDownItems["m_menuToolsOptions"].PerformClick(); + else + { + m_of = new OptionsForm(); + m_of.InitEx(KeePass.Program.MainForm.ClientIcons); + m_of.ShowDialog(); + } + } + + private static void AddPluginLink(UserControl uc) + { + LinkLabel llUrl = new LinkLabel(); + llUrl.Links.Add(0, 0, PluginURL); + llUrl.Text = PluginURL; + uc.Controls.Add(llUrl); + llUrl.Dock = DockStyle.Bottom; + llUrl.LinkClicked += new LinkLabelLinkClickedEventHandler(PluginURLClicked); + } + + private static void PluginURLClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + string target = e.Link.LinkData as string; + System.Diagnostics.Process.Start(target); + } + + private static void OnOptionsFormShown(object sender, EventArgs e) + { + m_of.Shown -= OnOptionsFormShown; + TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; + if (!tcMain.TabPages.ContainsKey(c_tabRookiestyle)) return; + TabPage tPlugins = tcMain.TabPages[c_tabRookiestyle]; + TabControl tcPlugins = Tools.GetControl(c_tabControlRookiestyle, tPlugins) as TabControl; + if (m_ActivatePluginTab) + { + tcMain.SelectedIndex = tcMain.TabPages.IndexOfKey(c_tabRookiestyle); + KeePass.Program.Config.Defaults.OptionsTabIndex = (uint)tcMain.SelectedIndex; + tcPlugins.SelectedIndex = tcPlugins.TabPages.IndexOfKey(c_tabRookiestyle + m_sPuginClassname); + } + m_ActivatePluginTab = false; + tcMain.Selected += OnPluginTabsSelected; + tcPlugins.Selected += OnPluginTabsSelected; + tcMain.ImageList.Images.Add(c_tabRookiestyle + "Icon", (Image)KeePass.Program.Resources.GetObject("B16x16_BlockDevice")); + tPlugins.ImageKey = c_tabRookiestyle + "Icon"; + m_PluginContainerShown |= tcMain.SelectedTab == tPlugins; + m_OptionsShown |= (tcPlugins.SelectedTab.Name == m_TabPageName); + CheckKeeTheme(tPlugins); + } + + private static void CheckKeeTheme(Control c) + { + Control check = GetControl("Rookiestyle_KeeTheme_Check", m_of); + if (check != null) return; + PluginDebug.AddInfo("Checking for KeeTheme"); + check = new Control(); + check.Name = "Rookiestyle_KeeTheme_Check"; + check.Visible = false; + m_of.Controls.Add(check); + KeePass.Plugins.Plugin p = (KeePass.Plugins.Plugin)GetPluginInstance("KeeTheme"); + if (p == null) return; + var t = GetField("_theme", p); + if (t == null) return; + bool bKeeThemeEnabled = (bool)t.GetType().GetProperty("Enabled").GetValue(t, null); + if (!bKeeThemeEnabled) return; + var v = GetField("_controlVisitor", p); + if (v == null) return; + MethodInfo miVisit = v.GetType().GetMethod("Visit", new Type[] { typeof(Control) }); + if (miVisit == null) return; + miVisit.Invoke(v, new object[] { c }); + } + + private static void OnWindowAdded(object sender, KeePass.UI.GwmWindowEventArgs e) + { + if (OptionsFormShown == null) return; + if (e.Form is OptionsForm) + { + m_of = e.Form as OptionsForm; + m_of.Shown += OnOptionsFormShown; + OptionsFormsEventArgs o = new OptionsFormsEventArgs(m_of); + OptionsFormShown(sender, o); + } + } + + private static void OnWindowRemoved(object sender, KeePass.UI.GwmWindowEventArgs e) + { + if (OptionsFormClosed == null) return; + if (e.Form is OptionsForm) + { + OptionsFormsEventArgs o = new OptionsFormsEventArgs(m_of); + OptionsFormClosed(sender, o); + } + } + + private static TabControl AddPluginTabContainer() + { + TabControl tcMain = Tools.GetControl("m_tabMain", m_of) as TabControl; + TabPage tPlugins = null; + TabControl tcPlugins = null; + if (tcMain.TabPages.ContainsKey(c_tabRookiestyle)) + { + tPlugins = tcMain.TabPages[c_tabRookiestyle]; + tcPlugins = (TabControl)tPlugins.Controls[c_tabControlRookiestyle]; + tcPlugins.Multiline = false; //Older version of PluginTools might still be used by other plugins + return tcPlugins; + } + tPlugins = new TabPage(KeePass.Resources.KPRes.Plugin + " " + m_of.Text); + tPlugins.Name = c_tabRookiestyle; + tPlugins.CreateControl(); + if (!OptionsEnabled) + { + while (tcMain.TabCount > 0) + tcMain.TabPages.RemoveAt(0); + } + tcMain.TabPages.Add(tPlugins); + tcPlugins = new TabControl(); + tcPlugins.Name = c_tabControlRookiestyle; + tcPlugins.Dock = DockStyle.Fill; + tcPlugins.Multiline = false; + tcPlugins.CreateControl(); + if (tcPlugins.ImageList == null) + tcPlugins.ImageList = new ImageList(); + tPlugins.Controls.Add(tcPlugins); + return tcPlugins; + } + + public class OptionsFormsEventArgs : EventArgs + { + public Form form; + + public OptionsFormsEventArgs(Form form) + { + this.form = form; + } + } + #endregion + + #region MessageBox shortcuts + public static DialogResult ShowError(string msg) + { + return ShowError(msg, DefaultCaption); + } + + public static DialogResult ShowInfo(string msg) + { + return ShowInfo(msg, DefaultCaption); + } + + public static DialogResult AskYesNo(string msg) + { + return AskYesNo(msg, DefaultCaption); + } + + public static DialogResult ShowError(string msg, string caption) + { + PluginDebug.AddError("Show error", 6, caption, msg); + return MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + public static DialogResult ShowInfo(string msg, string caption) + { + PluginDebug.AddInfo("Show info", 6, caption, msg); + return MessageBox.Show(msg, caption, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + public static DialogResult AskYesNo(string msg, string caption) + { + DialogResult result = MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question); + PluginDebug.AddInfo("Ask question", 6, caption, msg, "Result: " + result.ToString()); + return result; + } + #endregion + + #region GlobalWindowManager + public static void GlobalWindowManager(Form form) + { + if ((form == null) || (form.IsDisposed)) return; + form.Load += FormLoaded; + form.FormClosed += FormClosed; + } + + private static void FormLoaded(object sender, EventArgs e) + { + KeePass.UI.GlobalWindowManager.AddWindow(sender as Form, sender as IGwmWindow); + } + + private static void FormClosed(object sender, FormClosedEventArgs e) + { + KeePass.UI.GlobalWindowManager.RemoveWindow(sender as Form); + } + #endregion + } + + public static class DPIAwareness + { + public static readonly Size Size16 = new Size(DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16)); + + public static Image Scale16x16(Image img) + { + return Scale(img, 16, 16); + } + + public static Image Scale(Image img, int x, int y) + { + if (img == null) return null; + return GfxUtil.ScaleImage(img, DpiUtil.ScaleIntX(x), DpiUtil.ScaleIntY(y)); + } + } + + public static class PluginDebug + { + [Flags] + public enum LogLevelFlags + { + None = 0, + Info = 1, + Warning = 2, + Error = 4, + Success = 8, + All = Info | Warning | Error | Success + } + + public static string DebugFile { get; private set; } + public static LogLevelFlags LogLevel = LogLevelFlags.All; + + private static bool AutoSave = false; + private static bool AutoOpen = false; + private static bool AskOpen = true; + private static List m_DebugEntries = new List(); + private static string PluginName = string.Empty; + private static string PluginVersion; + private static bool m_DebugMode = false; + public static bool DebugMode + { + get { return m_DebugMode; } + set + { + if (m_DebugMode == value) return; + bool b = m_DebugMode; + m_DebugMode = true; + AddInfo("DebugMode changed", "Old: " + b.ToString(), "New: "+value.ToString()); + m_DebugMode = value; + } + } + private static Dictionary m_plugins = new Dictionary(); + public static Version DotNetVersion { get; private set; } + private static int m_DotNetRelease = 0; + + private static DateTime m_Start = DateTime.UtcNow; + + //Init + static PluginDebug() + { + PluginName = Assembly.GetExecutingAssembly().GetName().Name; + PluginVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); + + ulong uInst = KeePass.Util.WinUtil.GetMaxNetFrameworkVersion(); + DotNetVersion = new Version(StrUtil.VersionToString(uInst)); + RegistryKey rkRel = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full", false); + try { m_DotNetRelease = (int)rkRel.GetValue("Release"); } + catch { } + if (rkRel != null) rkRel.Close(); + + DebugFile = System.IO.Path.GetTempPath() + "Debug_" + PluginName + "_" + m_Start.ToString("yyyyMMddTHHmmssZ") + ".xml"; + + string level = KeePass.Program.CommandLineArgs["debuglevel"]; + if (string.IsNullOrEmpty(level)) + level = LogLevelFlags.All.ToString(); + try + { + LogLevel = (LogLevelFlags)Enum.Parse(LogLevel.GetType(), level); + } + catch { } + AutoSave = KeePass.Program.CommandLineArgs["debugautosave"] != null; + AutoOpen = KeePass.Program.CommandLineArgs["debugautoopen"] != null; + AskOpen = KeePass.Program.CommandLineArgs["debugsaveonly"] == null; + + DebugMode = KeePass.Program.CommandLineArgs[KeePass.App.AppDefs.CommandLineOptions.Debug] != null; + if (!DebugMode) + { + try + { + string[] plugins = KeePass.Program.CommandLineArgs["debugplugin"].ToLowerInvariant().Split(new char[] { ',' }); + DebugMode |= Array.Find(plugins, x => x.Trim() == PluginName.ToLowerInvariant()) != null; + DebugMode |= Array.Find(plugins, x => x.Trim() == "all") != null; + } + catch { } + } + KeePass.Program.MainForm.FormLoadPost += LoadPluginNames; + if (AutoSave) + AddInfo("AutoSave mode active", 0); + } + + #region Handle debug messages + public static void AddInfo(string msg) + { + AddMessage(LogLevelFlags.Info, msg, 5, null); + } + + public static void AddInfo(string msg, params string[] parameters) + { + AddMessage(LogLevelFlags.Info, msg, 5, parameters); + } + + public static void AddInfo(string msg, int CallstackFrames) + { + AddMessage(LogLevelFlags.Info, msg, CallstackFrames, null); + } + + public static void AddInfo(string msg, int CallstackFrames, params string[] parameters) + { + AddMessage(LogLevelFlags.Info, msg, CallstackFrames, parameters); + } + + public static void AddWarning(string msg) + { + AddMessage(LogLevelFlags.Warning, msg, 5, null); + } + + public static void AddWarning(string msg, params string[] parameters) + { + AddMessage(LogLevelFlags.Warning, msg, 5, parameters); + } + + public static void AddWarning(string msg, int CallstackFrames) + { + AddMessage(LogLevelFlags.Warning, msg, CallstackFrames, null); + } + + public static void AddWarning(string msg, int CallstackFrames, params string[] parameters) + { + AddMessage(LogLevelFlags.Warning, msg, CallstackFrames, parameters); + } + + public static void AddError(string msg) + { + AddMessage(LogLevelFlags.Error, msg, 5, null); + } + + public static void AddError(string msg, params string[] parameters) + { + AddMessage(LogLevelFlags.Error, msg, 5, parameters); + } + + public static void AddError(string msg, int CallstackFrames) + { + AddMessage(LogLevelFlags.Error, msg, CallstackFrames, null); + } + + public static void AddError(string msg, int CallstackFrames, params string[] parameters) + { + AddMessage(LogLevelFlags.Error, msg, CallstackFrames, parameters); + } + + public static void AddSuccess(string msg) + { + AddMessage(LogLevelFlags.Success, msg, 5, null); + } + + public static void AddSuccess(string msg, params string[] parameters) + { + AddMessage(LogLevelFlags.Success, msg, 5, parameters); + } + + public static void AddSuccess(string msg, int CallstackFrames) + { + AddMessage(LogLevelFlags.Success, msg, CallstackFrames, null); + } + + public static void AddSuccess(string msg, int CallstackFrames, params string[] parameters) + { + AddMessage(LogLevelFlags.Success, msg, CallstackFrames, parameters); + } + + private static void AddMessage(LogLevelFlags severity, string msg, int CallstackFrames, string[] parameters) + { + if (m_Saving || !DebugMode || ((severity & LogLevel) != severity)) return; + if (m_DebugEntries.Count > 0) + { + DebugEntry prev = m_DebugEntries[m_DebugEntries.Count - 1]; + if ((prev.severity == severity) && (prev.msg == msg) && ParamsEqual(prev.parameters, parameters)) + { + m_DebugEntries[m_DebugEntries.Count - 1].counter++; + return; + } + } + DebugEntry m = new DebugEntry(); + m.severity = severity; + m.msg = msg; + m.utc = DateTime.UtcNow; + m.counter = 1; + m.parameters = parameters; + if (CallstackFrames != 0) + { + System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(true); + for (int i = 0; i < st.FrameCount; i++) + { + if (m.sf.Count == CallstackFrames) break; + System.Diagnostics.StackFrame sf = st.GetFrame(i); + if (sf.GetMethod().DeclaringType.FullName != "PluginTools.PluginDebug") + m.sf.Add(sf); + } + } + m_DebugEntries.Add(m); + if (AutoSave) SaveDebugMessages(); + } + + private static bool ParamsEqual(string[] a, string[] b) + { + if ((a == null) && (b == null)) return true; + if ((a == null) && (b != null)) return false; + if ((a != null) && (b == null)) return false; + if (a.Length != b.Length) return false; + for (int i = 0; i < a.Length; i++) + if (a[i] != b[i]) return false; + return true; + } + + public static bool HasMessage(LogLevelFlags severity, string msg) + { + return m_DebugEntries.Find(x => (x.severity == severity) && (x.msg == msg)) != null; + } + #endregion + + public static void SaveOrShow() + { + if (m_DebugEntries.Count == 0) return; + SaveDebugMessages(); + if (AutoOpen || (AskOpen && Tools.AskYesNo("DebugFile: "+DebugFile+"\n\nOpen debug file?") == DialogResult.Yes)) + System.Diagnostics.Process.Start(DebugFile); + } + + private static System.Xml.XmlWriter m_xw = null; + private static System.IO.StringWriter m_sw = null; + private static void StartXml() + { + m_sw = new System.IO.StringWriter(); + System.Xml.XmlWriterSettings ws = new System.Xml.XmlWriterSettings(); + ws.OmitXmlDeclaration = true; + ws.Indent = true; + ws.IndentChars = "\t"; + m_xw = System.Xml.XmlWriter.Create(m_sw, ws); + } + + private static string Xml + { + get + { + if (m_xw == null) return string.Empty; + m_sw.Flush(); + m_xw.Flush(); + string s = m_sw.ToString(); + m_xw = null; + m_sw = null; + return s; + } + } + + public static string DebugMessages + { + get + { + StartXml(); + LoadPluginNames(null, null); + string sEncoding = "\n"; + m_xw.WriteStartElement("DebugInfo"); + #region General info + m_xw.WriteStartElement("General"); + m_xw.WriteStartElement("Plugin"); + m_xw.WriteElementString("PluginName", PluginName); + m_xw.WriteElementString("PluginVersion", PluginVersion); + m_xw.WriteEndElement(); + m_xw.WriteStartElement("DebugTime"); + m_xw.WriteElementString("DebugStart", m_Start.ToString("yyyyMMddTHHmmssZ")); + m_xw.WriteElementString("DebugEnd", DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ")); + m_xw.WriteEndElement(); + m_xw.WriteElementString("LogLevel", LogLevel.ToString()); + + #region Add OS info + string os = string.Empty; + if (KeePass.Util.WinUtil.IsWindows9x) + os = "Windows 9x"; + else if (KeePass.Util.WinUtil.IsWindows2000) + os = "Windows 2000"; + else if (KeePass.Util.WinUtil.IsWindowsXP) + os = "Windows XP"; + else + { + if (KeePass.Util.WinUtil.IsAtLeastWindows10) + os = ">= Windows 10"; + else if (KeePass.Util.WinUtil.IsAtLeastWindows8) + os = ">= Windows 8"; + else if (KeePass.Util.WinUtil.IsAtLeastWindows7) + os = ">= Windows 7"; + else if (KeePass.Util.WinUtil.IsAtLeastWindowsVista) + os = ">= Windows Vista"; + else if (KeePass.Util.WinUtil.IsAtLeastWindows2000) + os = ">= Windows 2000"; + else os = "Unknown"; + } + if (KeePass.Util.WinUtil.IsAppX) + os += " (AppX)"; + os += " - " + Environment.OSVersion.ToString(); + m_xw.WriteElementString("OS", KeePass.Util.WinUtil.GetOSStr() + " " + os); + #endregion + m_xw.WriteElementString("DotNet", DotNetVersion.ToString() + (m_DotNetRelease > 0 ? " (" + m_DotNetRelease.ToString() + ")" : string.Empty)); + m_xw.WriteElementString("KeePass", Tools.KeePassVersion.ToString()); + + m_xw.WriteStartElement("LoadedPlugins"); + foreach (KeyValuePair kvp in m_plugins) + { + m_xw.WriteStartElement("Plugin"); + m_xw.WriteElementString("PluginName", kvp.Key); + m_xw.WriteElementString("PluginVersion", kvp.Value.ToString()); + m_xw.WriteEndElement(); + } + m_xw.WriteEndElement(); + m_xw.WriteEndElement(); + #endregion + + if (m_DebugEntries.Count == 0) + m_xw.WriteElementString("DebugMessages", null); + else + { + m_xw.WriteStartElement("DebugMessages"); + foreach (var m in m_DebugEntries) + m.GetXml(m_xw); + m_xw.WriteEndElement(); + } + + m_xw.WriteEndElement(); + return sEncoding + Xml; + } + } + + private static bool m_Saving = false; + public static void SaveDebugMessages() + { + if (m_Saving) return; + m_Saving = true; + try + { + System.IO.File.WriteAllText(DebugFile, DebugMessages); + } + catch (Exception ex) + { + Tools.ShowError("Can't save debug file: " + DebugFile + "\n\n" + ex.Message); + } + m_Saving = false; + } + + private static bool m_bAllPluginsLoaded = false; + private static void LoadPluginNames(object sender, EventArgs e) + { + if (m_bAllPluginsLoaded) return; + m_plugins = Tools.GetLoadedPluginsName(); + if (sender == null) return; + m_bAllPluginsLoaded = true; + KeePass.Program.MainForm.FormLoadPost -= LoadPluginNames; + } + + private class DebugEntry + { + public LogLevelFlags severity; + public string msg; + public DateTime utc; + public int counter; + public List sf = new List(); + public string[] parameters = null; + + public void GetXml(System.Xml.XmlWriter xw) + { + xw.WriteStartElement("DebugEntry"); + xw.WriteElementString("Message", msg); + xw.WriteElementString("Counter", counter.ToString()); + xw.WriteElementString("Severity", severity.ToString()); + xw.WriteElementString("DateTimeUtc", utc.ToString("yyyyMMddTHHmmssZ")); + if ((parameters == null) || parameters.Length == 0) + xw.WriteElementString("Parameters", null); + else + { + xw.WriteStartElement("Parameters"); + foreach (string p in parameters) + xw.WriteElementString("Param", p); + xw.WriteEndElement(); + } + if (sf.Count == 0) + xw.WriteElementString("StackFrames", null); + else + { + xw.WriteStartElement("StackFrames"); + foreach (var f in sf) + { + xw.WriteStartElement("StackFrame"); + xw.WriteElementString("Method", f.GetMethod().Name + " ("+ f.GetMethod().DeclaringType.FullName + ")"); + xw.WriteElementString("FileName", System.IO.Path.GetFileName(f.GetFileName())); + xw.WriteElementString("Line", f.GetFileLineNumber().ToString()); + xw.WriteEndElement(); + } + xw.WriteEndElement(); + } + xw.WriteEndElement(); + } + } + } +} \ No newline at end of file diff --git a/src/PluginTranslation.cs b/src/PluginTranslation.cs new file mode 100644 index 0000000..c7d08e9 --- /dev/null +++ b/src/PluginTranslation.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.Xml; +using System.Xml.Serialization; +using System.IO; +using System.Reflection; + +using KeePass.Plugins; +using KeePass.Util; +using KeePassLib.Utility; + +using PluginTools; +using System.Windows.Forms; + +namespace PluginTranslation +{ + public class TranslationChangedEventArgs: EventArgs + { + public string OldLanguageIso6391 = string.Empty; + public string NewLanguageIso6391 = string.Empty; + + public TranslationChangedEventArgs(string OldLanguageIso6391, string NewLanguageIso6391) + { + this.OldLanguageIso6391 = OldLanguageIso6391; + this.NewLanguageIso6391 = NewLanguageIso6391; + } + } + + public static class PluginTranslate + { + public static long TranslationVersion = 0; + public static event EventHandler TranslationChanged = null; + private static string LanguageIso6391 = string.Empty; + #region Definitions of translated texts go here + public const string PluginName = "Early Update Check"; + public static readonly string Active = @"Active"; + public static readonly string CheckSync = @"Update check in foreground"; + public static readonly string CheckSyncDesc = @"EarlyUpdateCheck will always start the update check at the earliest possible time. + +If this option is active, EarlyUpdateCheck will additionally ensure the update check is finished BEFORE the 'Open Database' window is shown. +You may have the upgrade check continue in background if you don't want to wait for its completion."; + public static readonly string EnterBackgroundMode = @"Continue in background"; + public static readonly string PluginUpdateOneClick = @"One-Click plugin update"; + public static readonly string PluginUpdateOneClickDesc = @"Install new versions of my plugins by clicking the plugin in the 'Update Check' window. +This requires write access to KeePass' plugin folder. +KeePass needs to be restarted afterwards in order to use the new version."; + public static readonly string PluginUpdate = @"Update"; + public static readonly string PluginUpdateSelected = @"Start update"; + public static readonly string PluginUpdateCaption = @"Early Update Check - Plugin Updater"; + public static readonly string PluginUpdating = @"Updating {0}, please wait..."; + public static readonly string PluginUpdateSuccess = @"The update was successful, the new version(s) will be active after a restart of KeePass. +Restart now?"; + public static readonly string PluginUpdateFailed = @"Moving downloaded files failed. Open temporary folder instead?"; + public static readonly string PluginUpdateFailedSpecific = @"Plugin: {0} +The update failed"; + public static readonly string PluginTranslationUpdateFailed = @"Plugin: {0} +Update of language file {1} failed"; + public static readonly string TryUAC = @"Update could not be finished. Try alternative method? +This might show the UAC prompt."; + public static readonly string OpenTempFolder = @"Open temporary folder containing the updated files?"; + public static readonly string TranslationDownload_Update = @"Manually update translations"; + public static readonly string TranslationDownload_DownloadCurrent = @"Always download translations for active language: {0}"; + public static readonly string TranslationUpdateForm = @"Early Update Check - Update translations"; + public static readonly string SelectPluginsForTranslationUpdate = @"Please select plugins for which translations shall be updated"; + #endregion + + #region NO changes in this area + private static StringDictionary m_translation = new StringDictionary(); + + public static void Init(Plugin plugin, string LanguageCodeIso6391) + { + List lDebugStrings = new List(); + m_translation.Clear(); + bool bError = true; + LanguageCodeIso6391 = InitTranslation(plugin, lDebugStrings, LanguageCodeIso6391, out bError); + if (bError && (LanguageCodeIso6391.Length > 2)) + { + LanguageCodeIso6391 = LanguageCodeIso6391.Substring(0, 2); + lDebugStrings.Add("Trying fallback: " + LanguageCodeIso6391); + LanguageCodeIso6391 = InitTranslation(plugin, lDebugStrings, LanguageCodeIso6391, out bError); + } + if (bError) + { + PluginDebug.AddError("Reading translation failed", 0, lDebugStrings.ToArray()); + LanguageCodeIso6391 = "en"; + } + else + { + List lTranslatable = new List( + typeof(PluginTranslate).GetFields(BindingFlags.Static | BindingFlags.Public) + ).FindAll(x => x.IsInitOnly); + lDebugStrings.Add("Parsing complete"); + lDebugStrings.Add("Translated texts read: " + m_translation.Count.ToString()); + lDebugStrings.Add("Translatable texts: " + lTranslatable.Count.ToString()); + foreach (FieldInfo f in lTranslatable) + { + if (m_translation.ContainsKey(f.Name)) + { + lDebugStrings.Add("Key found: " + f.Name); + f.SetValue(null, m_translation[f.Name]); + } + else + lDebugStrings.Add("Key not found: " + f.Name); + } + PluginDebug.AddInfo("Reading translations finished", 0, lDebugStrings.ToArray()); + } + if (TranslationChanged != null) + { + TranslationChanged(null, new TranslationChangedEventArgs(LanguageIso6391, LanguageCodeIso6391)); + } + LanguageIso6391 = LanguageCodeIso6391; + lDebugStrings.Clear(); + } + + private static string InitTranslation(Plugin plugin, List lDebugStrings, string LanguageCodeIso6391, out bool bError) + { + if (string.IsNullOrEmpty(LanguageCodeIso6391)) + { + lDebugStrings.Add("No language identifier supplied, using 'en' as fallback"); + LanguageCodeIso6391 = "en"; + } + string filename = GetFilename(plugin.GetType().Namespace, LanguageCodeIso6391); + lDebugStrings.Add("Translation file: " + filename); + + if (!File.Exists(filename)) //If e. g. 'plugin.zh-tw.language.xml' does not exist, try 'plugin.zh.language.xml' + { + lDebugStrings.Add("File does not exist"); + bError = true; + return LanguageCodeIso6391; + } + else + { + string translation = string.Empty; + try { translation = File.ReadAllText(filename); } + catch (Exception ex) + { + lDebugStrings.Add("Error reading file: " + ex.Message); + LanguageCodeIso6391 = "en"; + bError = true; + return LanguageCodeIso6391; + } + XmlSerializer xs = new XmlSerializer(m_translation.GetType()); + lDebugStrings.Add("File read, parsing content"); + try + { + m_translation = (StringDictionary)xs.Deserialize(new StringReader(translation)); + } + catch (Exception ex) + { + lDebugStrings.Add("Error parsing file: " + ex.Message); + LanguageCodeIso6391 = "en"; + MessageBox.Show("Error parsing translation file\n" + ex.Message, PluginName, MessageBoxButtons.OK, MessageBoxIcon.Error); + bError = true; + return LanguageCodeIso6391; + } + bError = false; + return LanguageCodeIso6391; + } + } + + private static string GetFilename(string plugin, string lang) + { + string filename = UrlUtil.GetFileDirectory(WinUtil.GetExecutable(), true, true); + filename += KeePass.App.AppDefs.PluginsDir + UrlUtil.LocalDirSepChar + "Translations" + UrlUtil.LocalDirSepChar; + filename += plugin + "." + lang + ".language.xml"; + return filename; + } + #endregion + } + + #region NO changes in this area + [XmlRoot("Translation")] + public class StringDictionary : Dictionary, IXmlSerializable + { + public System.Xml.Schema.XmlSchema GetSchema() + { + return null; + } + + public void ReadXml(XmlReader reader) + { + bool wasEmpty = reader.IsEmptyElement; + reader.Read(); + if (wasEmpty) return; + bool bFirst = true; + while (reader.NodeType != XmlNodeType.EndElement) + { + if (bFirst) + { + bFirst = false; + try + { + reader.ReadStartElement("TranslationVersion"); + PluginTranslate.TranslationVersion = reader.ReadContentAsLong(); + reader.ReadEndElement(); + } + catch { } + } + reader.ReadStartElement("item"); + reader.ReadStartElement("key"); + string key = reader.ReadContentAsString(); + reader.ReadEndElement(); + reader.ReadStartElement("value"); + string value = reader.ReadContentAsString(); + reader.ReadEndElement(); + this.Add(key, value); + reader.ReadEndElement(); + reader.MoveToContent(); + } + reader.ReadEndElement(); + } + + public void WriteXml(XmlWriter writer) + { + writer.WriteStartElement("TranslationVersion"); + writer.WriteString(PluginTranslate.TranslationVersion.ToString()); + writer.WriteEndElement(); + foreach (string key in this.Keys) + { + writer.WriteStartElement("item"); + writer.WriteStartElement("key"); + writer.WriteString(key); + writer.WriteEndElement(); + writer.WriteStartElement("value"); + writer.WriteString(this[key]); + writer.WriteEndElement(); + writer.WriteEndElement(); + } + } + } + #endregion +} \ No newline at end of file diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3fb0b15 --- /dev/null +++ b/src/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Using directives +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Early update check")] +[assembly: AssemblyDescription("Perform KeePass update check BEFORE opening a database")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("rookiestyle")] +[assembly: AssemblyProduct ("KeePass Plugin")] +[assembly: AssemblyCopyright("Copyright 2020")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible (false)] +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion("2.0")] +[assembly: AssemblyFileVersion("2.0")] +[assembly: Guid("672570AF-CC57-4980-86F9-D48FD1CC707D")] \ No newline at end of file diff --git a/src/TranslationUpdateForm.Designer.cs b/src/TranslationUpdateForm.Designer.cs new file mode 100644 index 0000000..632cc0a --- /dev/null +++ b/src/TranslationUpdateForm.Designer.cs @@ -0,0 +1,143 @@ +namespace EarlyUpdateCheck +{ + partial class TranslationUpdateForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.panel1 = new System.Windows.Forms.Panel(); + this.bCancel = new System.Windows.Forms.Button(); + this.bOK = new System.Windows.Forms.Button(); + this.clbPlugins = new System.Windows.Forms.CheckedListBox(); + this.lSelectPlugins = new System.Windows.Forms.Label(); + this.tableLayoutPanel1.SuspendLayout(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 1; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.clbPlugins, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.lSelectPlugins, 0, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(10, 5, 10, 5); + this.tableLayoutPanel1.RowCount = 3; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(800, 450); + this.tableLayoutPanel1.TabIndex = 0; + // + // panel1 + // + this.panel1.Controls.Add(this.bCancel); + this.panel1.Controls.Add(this.bOK); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(13, 398); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(774, 44); + this.panel1.TabIndex = 0; + // + // bCancel + // + this.bCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.bCancel.Location = new System.Drawing.Point(671, 10); + this.bCancel.Name = "bCancel"; + this.bCancel.Size = new System.Drawing.Size(100, 30); + this.bCancel.TabIndex = 1; + this.bCancel.Text = "Cancel"; + this.bCancel.UseVisualStyleBackColor = true; + // + // bOK + // + this.bOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.bOK.AutoSize = true; + this.bOK.DialogResult = System.Windows.Forms.DialogResult.OK; + this.bOK.Location = new System.Drawing.Point(551, 10); + this.bOK.Name = "bOK"; + this.bOK.Size = new System.Drawing.Size(100, 30); + this.bOK.TabIndex = 0; + this.bOK.Text = "OK"; + this.bOK.UseVisualStyleBackColor = true; + // + // clbPlugins + // + this.clbPlugins.CheckOnClick = true; + this.clbPlugins.Dock = System.Windows.Forms.DockStyle.Fill; + this.clbPlugins.FormattingEnabled = true; + this.clbPlugins.Location = new System.Drawing.Point(13, 58); + this.clbPlugins.Name = "clbPlugins"; + this.clbPlugins.Size = new System.Drawing.Size(774, 334); + this.clbPlugins.TabIndex = 1; + this.clbPlugins.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.clbPlugins_ItemCheck); + // + // lSelectPlugins + // + this.lSelectPlugins.AutoSize = true; + this.lSelectPlugins.Location = new System.Drawing.Point(13, 5); + this.lSelectPlugins.Name = "lSelectPlugins"; + this.lSelectPlugins.Size = new System.Drawing.Size(108, 20); + this.lSelectPlugins.TabIndex = 2; + this.lSelectPlugins.Text = "Select plugins"; + // + // TranslationUpdateForm + // + this.AcceptButton = this.bOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.bCancel; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.tableLayoutPanel1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "TranslationUpdateForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "TranslationUpdateForm"; + this.Load += new System.EventHandler(this.TranslationUpdateForm_Load); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.CheckedListBox clbPlugins; + private System.Windows.Forms.Label lSelectPlugins; + private System.Windows.Forms.Button bCancel; + private System.Windows.Forms.Button bOK; + } +} \ No newline at end of file diff --git a/src/TranslationUpdateForm.cs b/src/TranslationUpdateForm.cs new file mode 100644 index 0000000..f6befb9 --- /dev/null +++ b/src/TranslationUpdateForm.cs @@ -0,0 +1,55 @@ +using KeePass.Resources; +using PluginTranslation; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace EarlyUpdateCheck +{ + public partial class TranslationUpdateForm : Form + { + public TranslationUpdateForm() + { + InitializeComponent(); + } + + public void InitEx(List lPlugins) + { + Text = PluginTranslate.TranslationUpdateForm; + lSelectPlugins.Text = PluginTranslate.SelectPluginsForTranslationUpdate; + bOK.Text = PluginTranslate.TranslationDownload_Update; + bOK.Text = PluginTranslate.PluginUpdateSelected; + bCancel.Text = KPRes.Cancel; + + clbPlugins.Items.Clear(); + lPlugins.Sort(); + foreach (string plugin in lPlugins) + clbPlugins.Items.Add(plugin, true); + } + + public List SelectedPlugins + { + get + { + List lPlugins = new List(); + foreach (string p in clbPlugins.CheckedItems) + lPlugins.Add(p); + return lPlugins; + } + } + + private void clbPlugins_ItemCheck(object sender, ItemCheckEventArgs e) + { + bOK.Enabled = (e.NewValue == CheckState.Checked) || (clbPlugins.CheckedItems.Count > 1); + } + + private void TranslationUpdateForm_Load(object sender, EventArgs e) + { + bOK.Left = bCancel.Left - bOK.Width - 15; + } + } +} diff --git a/src/Util.cs b/src/Util.cs new file mode 100644 index 0000000..510a549 --- /dev/null +++ b/src/Util.cs @@ -0,0 +1,234 @@ +using PluginTools; +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Windows.Forms; + +namespace EarlyUpdateCheck +{ + public enum UpdateCheckType + { + NotRequired = 0, + Required = 1, + OnlyTranslations = 2, + } + + public class UpdateInfo + { + public string Name; + public string Title; + public string URL; + public string VersionInfoURL; + public bool Selected; + + public string NameLowerInvariant { get { return Name.ToLowerInvariant(); } } + public Version VersionInstalled; + public Version VersionAvailable; + + public UpdateInfo(string Name, string Title, string URL, string VersionInfoURL, Version Version) + { + this.Name = Name; + this.Title = Title; + this.URL = URL; + this.VersionInfoURL = VersionInfoURL; + this.VersionInstalled = Version; + this.VersionAvailable = new Version(0, 0); + this.Selected = false; + } + + public override string ToString() + { + return Name + " - " + VersionInstalled.ToString() + " / " + VersionAvailable.ToString(); + } + + public static string GetName(UpdateInfo ui) + { + return ui.Name; + } + } + + public static class PluginConfig + { + public static bool Active = true; + public static bool CheckSync = true; + public static bool OneClickUpdate = true; + public static bool DownloadActiveLanguage = true; + + public static void Read() + { + PluginConfig.Active = KeePass.Program.Config.CustomConfig.GetBool("EarlyUpdateCheck.Active", PluginConfig.Active); + PluginConfig.CheckSync = KeePass.Program.Config.CustomConfig.GetBool("EarlyUpdateCheck.CheckSync", PluginConfig.CheckSync); + PluginConfig.OneClickUpdate = KeePass.Program.Config.CustomConfig.GetBool("EarlyUpdateCheck.OneClickUpdate", PluginConfig.OneClickUpdate); + PluginConfig.DownloadActiveLanguage = KeePass.Program.Config.CustomConfig.GetBool("EarlyUpdateCheck.DownloadActiveLanguage", PluginConfig.DownloadActiveLanguage); + } + + public static void Write() + { + KeePass.Program.Config.CustomConfig.SetBool("EarlyUpdateCheck.Active", PluginConfig.Active); + KeePass.Program.Config.CustomConfig.SetBool("EarlyUpdateCheck.CheckSync", PluginConfig.CheckSync); + KeePass.Program.Config.CustomConfig.SetBool("EarlyUpdateCheck.OneClickUpdate", PluginConfig.OneClickUpdate); + KeePass.Program.Config.CustomConfig.SetBool("EarlyUpdateCheck.DownloadActiveLanguage", PluginConfig.DownloadActiveLanguage); + } + } + + public static class FileCopier + { + [DllImport("shell32.dll", CharSet = CharSet.Unicode)] + private static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + private struct SHFILEOPSTRUCT + { + public IntPtr hwnd; + public FILE_OP_TYPE wFunc; + [MarshalAs(UnmanagedType.LPWStr)] + public string pFrom; + [MarshalAs(UnmanagedType.LPWStr)] + public string pTo; + public FILE_OP_FLAGS fFlags; + [MarshalAs(UnmanagedType.Bool)] + public bool fAnyOperationsAborted; + public IntPtr hNameMappings; + [MarshalAs(UnmanagedType.LPWStr)] + public string lpszProgressTitle; + } + + private enum FILE_OP_TYPE : uint + { + FO_MOVE = 0x0001, + FO_COPY = 0x0002, + FO_DELETE = 0x0003, + FO_RENAME = 0x0004, + } + + [Flags] + private enum FILE_OP_FLAGS : ushort + { + FOF_MULTIDESTFILES = 0x0001, + FOF_CONFIRMMOUSE = 0x0002, + FOF_SILENT = 0x0004, + FOF_RENAMEONCOLLISION = 0x0008, + FOF_NOCONFIRMATION = 0x0010, + FOF_WANTMAPPINGHANDLE = 0x0020, + FOF_ALLOWUNDO = 0x0040, + FOF_FILESONLY = 0x0080, + FOF_SIMPLEPROGRESS = 0x0100, + FOF_NOCONFIRMMKDIR = 0x0200, + FOF_NOERRORUI = 0x0400, + FOF_NOCOPYSECURITYATTRIBS = 0x0800, + FOF_NORECURSION = 0x1000, + FOF_NO_CONNECTED_ELEMENTS = 0x2000, + FOF_WANTNUKEWARNING = 0x4000, + FOF_NORECURSEREPARSE = 0x8000, + } + + public static bool CopyFiles(string from, string to) + { + bool success = false; + + from += "*\0\0"; + to += "\0\0"; + + SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT(); + lpFileOp.hwnd = IntPtr.Zero; + lpFileOp.wFunc = FILE_OP_TYPE.FO_COPY; + lpFileOp.pFrom = from; + lpFileOp.pTo = to; + lpFileOp.fFlags = FILE_OP_FLAGS.FOF_NOCONFIRMATION; + lpFileOp.fAnyOperationsAborted = false; + lpFileOp.hNameMappings = IntPtr.Zero; + lpFileOp.lpszProgressTitle = string.Empty; + + int result = SHFileOperation(ref lpFileOp); + if (result == 0) + success = !lpFileOp.fAnyOperationsAborted; + PluginDebug.AddInfo("Copy in UAC mode: " + success.ToString()); + return success; + } + } + + public static class NativeMethods + { + [DllImport("kernel32")] + public static extern uint GetCurrentThreadId(); + + public delegate bool EnumWindowsProcedure(IntPtr windowHandle, IntPtr param); + [DllImport("user32")] + public static extern bool EnumChildWindows(IntPtr windowHandle, EnumWindowsProcedure enumProc, IntPtr param); + + [DllImport("user32")] + public static extern bool EnumThreadWindows(uint threadId, EnumWindowsProcedure enumProc, IntPtr param); + + [DllImport("user32", EntryPoint = "GetClassNameW", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern int GetClassName(IntPtr windowHandle, System.Text.StringBuilder buffer, int bufferSize); + + [DllImport("user32", EntryPoint = "GetDlgCtrlID")] + public static extern int GetDialogControlId(IntPtr windowHandle); + + [DllImport("user32")] + public static extern uint SendMessage(IntPtr param, uint message, uint wParam, uint lParam); + + //Credits go to Falahati: https://github.com/falahati/UACHelper - file WinForm.cs + public static DialogResult ShieldifyNativeDialog(DialogResult button, KeePassLib.Delegates.GFunc dialogShowCode) + { + var callingThreadId = NativeMethods.GetCurrentThreadId(); + var thread = new Thread(() => + { + try + { + var found = false; + while (!found) + { + Thread.Sleep(100); + NativeMethods.EnumThreadWindows(callingThreadId, (wnd, param) => + { + var buffer = new System.Text.StringBuilder(256); + NativeMethods.GetClassName(wnd, buffer, buffer.Capacity); + if (buffer.ToString() == @"#32770") + { + ShieldifyNativeDialog(button, wnd); + found = true; + return false; + } + return true; + }, IntPtr.Zero); + } + } + catch { } + }); + thread.Start(); + var result = dialogShowCode(); + thread.Abort(); + return result; + } + + public static bool ShieldifyNativeDialog(DialogResult button, IntPtr windowHandle) + { + int numberOfItems = 0; + bool notFound = NativeMethods.EnumChildWindows(windowHandle, (wnd, param) => + { + var buffer = new System.Text.StringBuilder(256); + NativeMethods.GetClassName(wnd, buffer, buffer.Capacity); + numberOfItems++; + if (buffer.ToString().ToLower().Contains(@"button")) + { + if (NativeMethods.GetDialogControlId(wnd) == (int)button) + { + NativeMethods.SendMessage(wnd, 0x160C, 0, 0xFFFFFFFF); + return false; + } + } + else + { + if (ShieldifyNativeDialog(button, wnd)) + { + return false; + } + } + return true; + }, IntPtr.Zero); + + return !notFound && numberOfItems > 0; + } + } +} diff --git a/version.info b/version.info new file mode 100644 index 0000000..2bf9877 --- /dev/null +++ b/version.info @@ -0,0 +1,5 @@ +: +Early update check:2.0 +Early update check!de:3 +Early update check!ru:2 +: \ No newline at end of file