[Pkg-cli-apps-commits] [keepass2] 01/05: Imported Upstream version 2.30

Julian Taylor jtaylor.debian at googlemail.com
Mon Aug 24 22:14:15 UTC 2015


This is an automated email from the git hooks/post-receive script.

jtaylor-guest pushed a commit to branch master
in repository keepass2.

commit aa098f2b542fbc56b1a553d9a008e542180f9a65
Author: Julian Taylor <jtaylor.debian at googlemail.com>
Date:   Mon Aug 24 23:51:46 2015 +0200

    Imported Upstream version 2.30
---
 Build/KeePassLibSD_Distrib/KeePassLibSD.dll        | Bin 343448 -> 343960 bytes
 Build/KeePassLib_Distrib/KeePassLib.dll            | Bin 251800 -> 252312 bytes
 Build/KeePassLib_Distrib/KeePassLib.xml            |  42 ++-----
 Docs/Chm/default.css                               |  18 ++-
 Docs/Chm/help/base/autourl.html                    |   4 +-
 Docs/Chm/help/base/disclaimer.html                 |  52 +++++++--
 Docs/Chm/help/base/faq_tech.html                   |   3 +-
 Docs/Chm/help/base/keys.html                       |   8 +-
 Docs/Chm/help/base/placeholders.html               |  58 +++++++++-
 Docs/Chm/help/base/security.html                   |  12 ++
 Docs/Chm/help/v2/setup.html                        |   4 +-
 Docs/Chm/help/v2/xml_replace.html                  |  22 ++++
 Docs/Chm/help/v2_dev/scr_sc_index.html             |  16 ++-
 Docs/History.txt                                   |  62 ++++++++++
 Ext/KeePass.exe.config                             |   4 +-
 Ext/KeePass.iss                                    |  11 +-
 Ext/KeePassMsi/KeePassMsi.vdproj                   |  14 +--
 KeePass/App/Configuration/AceIntegration.cs        |   5 +
 KeePass/DataExchange/CsvStreamReaderEx.cs          |   6 +-
 KeePass/DataExchange/Formats/LastPassCsv2.cs       |   2 +-
 KeePass/DataExchange/Formats/RoboFormHtml69.cs     |   2 +-
 KeePass/DataExchange/Formats/XslTransform2x.cs     |  24 +++-
 KeePass/DataExchange/ImportUtil.cs                 |   3 +-
 KeePass/DataExchange/KdbManager.cs                 |  32 +++++-
 KeePass/DataExchange/PwExportInfo.cs               |   9 +-
 KeePass/Forms/EditStringForm.cs                    | 126 ++++++++++++---------
 KeePass/Forms/MainForm.cs                          |  16 +--
 KeePass/Forms/MainForm_Functions.cs                |  79 +++++++++++--
 KeePass/Forms/OptionsForm.Designer.cs              |   1 -
 KeePass/Forms/OptionsForm.cs                       |  33 +++++-
 KeePass/Forms/PwEntryForm.cs                       |   6 +-
 KeePass/Plugins/IPluginHost.cs                     |   2 +-
 KeePass/Properties/AssemblyInfo.cs                 |   4 +-
 KeePass/Resources/KPRes.Generated.cs               |  26 +++++
 KeePass/UI/CustomRichTextBoxEx.cs                  |  26 +++++
 KeePass/UI/MruList.cs                              |  12 +-
 KeePass/UI/OpenWithMenu.cs                         |  70 ++++++++++--
 KeePass/UI/UIUtil.cs                               |  43 +++++++
 KeePass/Util/AppLocator.cs                         |  60 ++++++++++
 KeePass/Util/AutoType.cs                           |  38 +++++--
 KeePass/Util/CommandLineArgs.cs                    |   7 +-
 .../Collections/ProtectedStringDictionary.cs       |   9 +-
 KeePassLib/Cryptography/CryptoRandom.cs            |  21 +++-
 KeePassLib/Cryptography/HmacOtp.cs                 |   2 +-
 KeePassLib/Keys/CompositeKey.cs                    |  42 ++++---
 KeePassLib/Native/NativeLib.cs                     |  23 +++-
 KeePassLib/Properties/AssemblyInfo.cs              |   4 +-
 KeePassLib/PwDefs.cs                               |   6 +-
 KeePassLib/Security/ProtectedBinary.cs             |   3 +-
 KeePassLib/Security/ProtectedString.cs             |   6 +-
 KeePassLib/Serialization/KdbxFile.Read.Streamed.cs |  14 ++-
 KeePassLib/Utility/GfxUtil.cs                      |   2 +-
 KeePassLib/Utility/MemUtil.cs                      |  55 ++++-----
 KeePassLib/Utility/MessageService.cs               |  26 +++--
 KeePassLib/Utility/MonoWorkarounds.cs              |  10 ++
 KeePassLib/Utility/StrUtil.cs                      |   4 +-
 KeePassLibSD/Properties/AssemblyInfo.cs            |   2 +-
 ShInstUtil/ShInstUtil.rc                           |   8 +-
 Translation/DefaultText.xml                        |   6 +
 Translation/TrlUtil/Properties/AssemblyInfo.cs     |   4 +-
 60 files changed, 921 insertions(+), 288 deletions(-)

diff --git a/Build/KeePassLibSD_Distrib/KeePassLibSD.dll b/Build/KeePassLibSD_Distrib/KeePassLibSD.dll
index ff4e5b4..d3f01d8 100644
Binary files a/Build/KeePassLibSD_Distrib/KeePassLibSD.dll and b/Build/KeePassLibSD_Distrib/KeePassLibSD.dll differ
diff --git a/Build/KeePassLib_Distrib/KeePassLib.dll b/Build/KeePassLib_Distrib/KeePassLib.dll
index 89aed19..bb1ed1d 100644
Binary files a/Build/KeePassLib_Distrib/KeePassLib.dll and b/Build/KeePassLib_Distrib/KeePassLib.dll differ
diff --git a/Build/KeePassLib_Distrib/KeePassLib.xml b/Build/KeePassLib_Distrib/KeePassLib.xml
index de2ad89..d6122e8 100644
--- a/Build/KeePassLib_Distrib/KeePassLib.xml
+++ b/Build/KeePassLib_Distrib/KeePassLib.xml
@@ -977,56 +977,38 @@
             <summary>
             Set all bytes in a byte array to zero.
             </summary>
-            <param name="pbArray">Input array. All bytes of this array will be set
-            to zero.</param>
+            <param name="pbArray">Input array. All bytes of this array
+            will be set to zero.</param>
         </member>
         <member name="M:KeePassLib.Utility.MemUtil.BytesToUInt16(System.Byte[])">
             <summary>
-            Convert 2 bytes to a 16-bit unsigned integer using Little-Endian
-            encoding.
+            Convert 2 bytes to a 16-bit unsigned integer (little-endian).
             </summary>
-            <param name="pb">Input bytes. Array must contain at least 2 bytes.</param>
-            <returns>16-bit unsigned integer.</returns>
         </member>
         <member name="M:KeePassLib.Utility.MemUtil.BytesToUInt32(System.Byte[])">
             <summary>
-            Convert 4 bytes to a 32-bit unsigned integer using Little-Endian
-            encoding.
+            Convert 4 bytes to a 32-bit unsigned integer (little-endian).
             </summary>
-            <param name="pb">Input bytes.</param>
-            <returns>32-bit unsigned integer.</returns>
         </member>
         <member name="M:KeePassLib.Utility.MemUtil.BytesToUInt64(System.Byte[])">
             <summary>
-            Convert 8 bytes to a 64-bit unsigned integer using Little-Endian
-            encoding.
+            Convert 8 bytes to a 64-bit unsigned integer (little-endian).
             </summary>
-            <param name="pb">Input bytes.</param>
-            <returns>64-bit unsigned integer.</returns>
         </member>
         <member name="M:KeePassLib.Utility.MemUtil.UInt16ToBytes(System.UInt16)">
             <summary>
-            Convert a 16-bit unsigned integer to 2 bytes using Little-Endian
-            encoding.
+            Convert a 16-bit unsigned integer to 2 bytes (little-endian).
             </summary>
-            <param name="uValue">16-bit input word.</param>
-            <returns>Two bytes representing the 16-bit value.</returns>
         </member>
         <member name="M:KeePassLib.Utility.MemUtil.UInt32ToBytes(System.UInt32)">
             <summary>
-            Convert a 32-bit unsigned integer to 4 bytes using Little-Endian
-            encoding.
+            Convert a 32-bit unsigned integer to 4 bytes (little-endian).
             </summary>
-            <param name="uValue">32-bit input word.</param>
-            <returns>Four bytes representing the 32-bit value.</returns>
         </member>
         <member name="M:KeePassLib.Utility.MemUtil.UInt64ToBytes(System.UInt64)">
             <summary>
-            Convert a 64-bit unsigned integer to 8 bytes using Little-Endian
-            encoding.
+            Convert a 64-bit unsigned integer to 8 bytes (little-endian).
             </summary>
-            <param name="uValue">64-bit input word.</param>
-            <returns>Eight bytes representing the 64-bit value.</returns>
         </member>
         <member name="M:KeePassLib.Utility.MemUtil.Hash32(System.Byte[],System.Int32,System.Int32)">
             <summary>
@@ -2400,9 +2382,9 @@
         </member>
         <member name="M:KeePassLib.Utility.StrUtil.SplitCommandLine(System.String,System.String@,System.String@)">
             <summary>
-            Split up a command-line into application and argument.
+            Split up a command line into application and argument.
             </summary>
-            <param name="strCmdLine">Command-line to split.</param>
+            <param name="strCmdLine">Command line to split.</param>
             <param name="strApp">Application path.</param>
             <param name="strArgs">Arguments.</param>
         </member>
@@ -2696,8 +2678,8 @@
         </member>
         <member name="T:KeePassLib.Cryptography.CryptoRandom">
             <summary>
-            Cryptographically strong random number generator. The returned values
-            are unpredictable and cannot be reproduced.
+            Cryptographically strong random number generator. The returned
+            values are unpredictable and cannot be reproduced.
             <c>CryptoRandom</c> is a singleton class.
             </summary>
         </member>
diff --git a/Docs/Chm/default.css b/Docs/Chm/default.css
index 06389b0..73a5ae7 100644
--- a/Docs/Chm/default.css
+++ b/Docs/Chm/default.css
@@ -5,8 +5,8 @@
 body, p, div, h1, h2, h3, h4, h5, h6, ol, ul, li, td, th, dd, dt, a {
 	font-family: Verdana, Arial, sans-serif;
 	font-size: 13px;
-	color: #000000;
 	font-weight: normal;
+	color: #000000;
 }
 
 /* --------------------------------------------------------------------- */
@@ -381,3 +381,19 @@ div.tipdiv {
 .spr-m-feed-s     { background-position:  -19px -158px; width: 16px; height: 16px; }
 .spr-m-w3valid-b  { background-position:   -1px -176px; width: 80px; height: 15px; }
 .spr-m-kp-b       { background-position:  -83px -176px; width: 80px; height: 15px; }
+
+/* --------------------------------------------------------------------- */
+
+.cc_message, .cc_more_info, .cc_btn {
+	font-family: Verdana, Arial, sans-serif !important;
+	font-size: 13px !important;
+}
+
+.cc_message {
+	color: #FFFFFF !important;
+}
+
+.cc_container {
+	background-color: rgba(0, 0, 0, 0.92) !important;
+	padding: 5px 5px 5px 10px !important;
+}
diff --git a/Docs/Chm/help/base/autourl.html b/Docs/Chm/help/base/autourl.html
index 5105571..d31ebb8 100644
--- a/Docs/Chm/help/base/autourl.html
+++ b/Docs/Chm/help/base/autourl.html
@@ -184,9 +184,9 @@ Mozilla Firefox, Opera and Google Chrome).</p>
 <p>URL scheme overrides can also be used to define new protocols. For example,
 if you want to define a protocol <code>kdbx://</code> that opens another KeePass database,
 specify the following as override for the kdbx scheme (on Windows):<br />
-<code>cmd://"{APPDIR}\KeePass.exe" "{URL:RMVSCM}" -pw-enc:"{PASSWORD_ENC}"</code><br />
+<code>cmd://"{APPDIR}\KeePass.exe" "{BASE:RMVSCM}" -pw-enc:"{PASSWORD_ENC}"</code><br />
 or on Unix-like systems (Mono):<br />
-<code>cmd://mono "{APPDIR}/KeePass.exe" "{URL:RMVSCM}" -pw-enc:"{PASSWORD_ENC}"</code><br />
+<code>cmd://mono "{APPDIR}/KeePass.exe" "{BASE:RMVSCM}" -pw-enc:"{PASSWORD_ENC}"</code><br />
 If an entry now has an URL looking like <code>kdbx://<i>PathToYourDatabase.kdbx</i></code>
 and the master password for this database in the password field,
 double-clicking the URL of the entry in the main window opens the other database.
diff --git a/Docs/Chm/help/base/disclaimer.html b/Docs/Chm/help/base/disclaimer.html
index 92b60d6..d9c3334 100644
--- a/Docs/Chm/help/base/disclaimer.html
+++ b/Docs/Chm/help/base/disclaimer.html
@@ -67,10 +67,10 @@ or the complete publication including all offers and information might be
 extended, changed or partly or completely deleted by the author without
 separate announcement.</p>
 
-<p><b>2. Referrals and links</b></p>
+<p><b>2. Referrals and Links</b></p>
 
 <p>The author is not responsible for any contents linked or referred to from
-his pages - unless he has full knowledge of illegal contents and would be able
+his pages – unless he has full knowledge of illegal contents and would be able
 to prevent the visitors of his site from viewing those pages. If any damage
 occurs by the use of information presented there, only the author of the
 respective pages might be liable, not the one who has linked to these pages.
@@ -86,12 +86,12 @@ or, if not possible, to indicate the copyright of the respective object.</p>
 duplication or use of objects such as images, diagrams, sounds or texts in other
 electronic or printed publications is not permitted without the author's agreement.</p>
 
-<p><b>4. Privacy policy</b></p>
+<p><b>4. Privacy Policy & Cookies</b></p>
 
 <p>If the opportunity for the input of personal or business data (email addresses,
 name, addresses) is given, the input of these data takes place voluntarily. The
-use and payment of all offered services are permitted - if and so far technically
-possible and reasonable - without specification of any personal data or under
+use and payment of all offered services are permitted – if and so far technically
+possible and reasonable – without specification of any personal data or under
 specification of anonymized data or an alias. The use of published postal
 addresses, telephone or fax numbers and email addresses for marketing purposes
 is prohibited, offenders sending unwanted spam messages will be punished.</p>
@@ -104,12 +104,26 @@ If you would like more information about this practice and to know your choices
 about not having this information used by Google, click
 <a href="http://www.google.com/privacy_ads.html" target="_blank">here</a>.</p>
 
-<p><b>5. Legal validity of this disclaimer</b></p>
+<p>We use cookies to personalise content and ads, to provide social media
+features and to analyse our traffic. We also share information about your use
+of our site with our social media, advertising and analytics partners.</p>
+
+<p>By using our services, you agree to our use of cookies.</p>
+
+<p>Details:</p>
+<ul>
+<li>Google: <a href="http://www.google.com/intl/en-GB/policies/privacy/partners/"
+target="_blank">How Google uses data when you use our partners' sites or apps</a>.</li>
+<li>Flattr: <a href="https://flattr.com/privacy"
+target="_blank">Flattr Privacy Policy</a>.</li>
+</ul>
+
+<p><b>5. Legal Validity of this Disclaimer</b></p>
 
 <p>This disclaimer is to be regarded as part of the internet publication which
 you were referred from. If sections or individual terms of this statement are
 not legal or correct, the content or validity of the other parts remain
-uninfluenced by this fact. </p>
+uninfluenced by this fact.</p>
 
 <br />
 
@@ -185,14 +199,14 @@ oder Verwendung solcher Grafiken, Tondokumente, Videosequenzen und
 Texte in anderen elektronischen oder gedruckten Publikationen ist
 ohne ausdrückliche Zustimmung des Autors nicht gestattet.</p>
 
-<p><b>4. Datenschutz</b></p>
+<p><b>4. Datenschutz & Cookies</b></p>
 
 <p>Sofern innerhalb des Internetangebotes die Möglichkeit zur
 Eingabe persönlicher oder geschäftlicher Daten (Emailadressen, Namen,
 Anschriften) besteht, so erfolgt die Preisgabe dieser Daten seitens
 des Nutzers auf ausdrücklich freiwilliger Basis. Die Inanspruchnahme
-und Bezahlung aller angebotenen Dienste ist - soweit technisch
-möglich und zumutbar - auch ohne Angabe solcher Daten bzw.
+und Bezahlung aller angebotenen Dienste ist – soweit technisch
+möglich und zumutbar – auch ohne Angabe solcher Daten bzw.
 unter Angabe anonymisierter Daten oder eines Pseudonyms gestattet.
 Die Nutzung der im Rahmen des Impressums oder vergleichbarer
 Angaben veröffentlichten Kontaktdaten wie Postanschriften,
@@ -212,6 +226,24 @@ erfahren möchten oder wissen möchten, welche Möglichkeiten Sie ha
 damit diese Informationen nicht von Google verwendet werden können, klicken Sie
 <a href="http://www.google.de/privacy_ads.html" target="_blank">hier</a>.</p>
 
+<p>Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren,
+Funktionen für soziale Medien anbieten zu können und die Zugriffe
+auf unsere Website zu analysieren. Außerdem geben wir Informationen
+zu Ihrer Nutzung unserer Website an unsere Partner für soziale Medien,
+Werbung und Analysen weiter.</p>
+
+<p>Mit der Nutzung unserer Dienste erklären Sie sich damit einverstanden,
+dass wir Cookies verwenden.</p>
+
+<p>Details:</p>
+<ul>
+<li>Google: <a href="http://www.google.com/intl/de/policies/privacy/partners/"
+target="_blank">Datennutzung durch Google bei Ihrer Nutzung von Websites oder
+Apps unserer Partner</a>.</li>
+<li>Flattr: <a href="https://flattr.com/privacy"
+target="_blank">Flattr Privacy Policy</a>.</li>
+</ul>
+
 <p><b>5. Rechtswirksamkeit dieses Haftungsausschlusses</b></p>
 
 <p>Dieser Haftungsausschluss ist als Teil des Internetangebotes
diff --git a/Docs/Chm/help/base/faq_tech.html b/Docs/Chm/help/base/faq_tech.html
index 47ead63..faadf42 100644
--- a/Docs/Chm/help/base/faq_tech.html
+++ b/Docs/Chm/help/base/faq_tech.html
@@ -269,8 +269,7 @@ Each entry can be assigned its own icon.<br />
 You can import your own icons into KeePass databases. For this, click the <i>'Add...'</i>
 button in the icon picker dialog.<br />
 <br />
-Images are automatically resized to 16x16, if they are larger or smaller. Supported
-formats are BMP, EMF, GIF, ICO, JPEG, PNG, TIFF and WMF.
+Supported formats are BMP, EMF, GIF, ICO, JPEG, PNG, TIFF and WMF.
 
 <br />
 </td>
diff --git a/Docs/Chm/help/base/keys.html b/Docs/Chm/help/base/keys.html
index e34c368..dace6d7 100644
--- a/Docs/Chm/help/base/keys.html
+++ b/Docs/Chm/help/base/keys.html
@@ -169,10 +169,12 @@ same name and password;
 you need to copy the <i>complete</i> account (i.e. SID, ...). This is not
 a simple task, so if you don't know how to do this, it is highly recommended
 that you don't enable this option.
-Instructions on how to restore a backed up account can be found in a
-Microsoft TechNet article:
+Detailed instructions how to recover a Windows user account can be found here:
+<a href="https://sourceforge.net/p/keepass/wiki/Recover%20Windows%20User%20Account%20Credentials/"
+target="_blank">Recover Windows User Account Credentials</a>
+(a short technical tutorial can be found in a Microsoft TechNet article:
 <a href="http://technet.microsoft.com/en-us/library/ee681624%28WS.10%29.aspx"
-target="_blank">How to recover a Vault corrupted by lost DPAPI keys</a>.<br />
+target="_blank">How to recover a Vault corrupted by lost DPAPI keys</a>).<br />
 <br />
 You can change the password of the Windows user account freely;
 this does not affect the KeePass database.
diff --git a/Docs/Chm/help/base/placeholders.html b/Docs/Chm/help/base/placeholders.html
index fc9cb47..4b6adbc 100644
--- a/Docs/Chm/help/base/placeholders.html
+++ b/Docs/Chm/help/base/placeholders.html
@@ -106,6 +106,8 @@ you can use the placeholder <code>{S:eMail}</code>.
 <tr><td width="50%"><code>{URL:USERNAME}</code></td><td width="50%">User name of the entry URL.</td></tr>
 <tr><td width="50%"><code>{URL:PASSWORD}</code></td><td width="50%">Password of the entry URL.</td></tr>
 </table>
+<br />
+An example can be found <a href="#url">below</a>.
 
 
 <br /><br />
@@ -135,6 +137,15 @@ on Unix-like systems), if installed.</td></tr>
 <tr><td width="50%"><code>{SAFARI}</code></td><td width="50%">Path of Safari, if installed.</td></tr>
 </table>
 
+<p><b>Microsoft Edge.</b>
+There exists no placeholder for Edge, because Edge is an app
+that cannot be started like a regular Windows application.
+In order to open an URL using Edge, prefix the URL with '<code>microsoft-edge:</code>'.
+For example, in order to open the URL
+<a href="http://keepass.info/" target="_blank">http://keepass.info/</a>
+using Edge, use the URL
+<a href="microsoft-edge:http://keepass.info/" target="_blank">microsoft-edge:http://keepass.info/</a>.</p>
+
 <br />
 
 <table class="tablebox75">
@@ -305,7 +316,8 @@ See <a href="#hmacotp">below</a>.</td></tr>
 <code>{BASE:USERNAME}</code><br />
 <code>{BASE:PASSWORD}</code></td><td width="50%">Within an URL override,
 each of these placeholders is replaced by the specified part of the string that is
-being overridden.</td></tr>
+being overridden.
+See <a href="#url">below</a>.</td></tr>
 </table>
 
 
@@ -504,5 +516,49 @@ are generated: 755224, 287082, 359152, 969429, 338314, ...
 (more generated OTPs can be found in the example in RFC 4226).
 
 
+<br /><br />
+
+<a name="url"></a>
+
+<b><code>{URL:...}</code> and <code>{BASE:...}</code>:</b><br />
+The <code>{URL:...}</code> placeholder is replaced by the specified part
+of the current entry's URL; this typically is useful in an
+entry-specific URL override (defined on the 'Properties' tab of the entry dialog).
+The <code>{BASE:...}</code> placeholder is replaced by the specified part
+of the URL being overridden; this typically is useful in a
+global URL override (defined in 'Tools' -> 'Options' -> tab 'Integration' ->
+button 'URL Overrides'), because there no entry context may be available.<br />
+<br />
+<i>Example.</i> For the entry URL
+<code>http://user:pw@keepass.info:80/path/example.php?q=e&s=t</code>,
+the placeholders return the following values:<br />
+<br />
+<table class="tablebox75">
+<tr><th width="25%">Placeholder</th><th width="75%">Value</th></tr>
+<tr><td width="25%"><code>{URL}</code></td>
+<td width="75%"><code>http://user:pw@keepass.info:80/path/example.php?q=e&s=t</code></td></tr>
+<tr><td width="25%"><code>{URL:RMVSCM}</code></td>
+<td width="75%"><code>user:pw at keepass.info:80/path/example.php?q=e&s=t</code></td></tr>
+<tr><td width="25%"><code>{URL:SCM}</code></td>
+<td width="75%"><code>http</code></td></tr>
+<tr><td width="25%"><code>{URL:HOST}</code></td>
+<td width="75%"><code>keepass.info</code></td></tr>
+<tr><td width="25%"><code>{URL:PORT}</code></td>
+<td width="75%"><code>80</code></td></tr>
+<tr><td width="25%"><code>{URL:PATH}</code></td>
+<td width="75%"><code>/path/example.php</code></td></tr>
+<tr><td width="25%"><code>{URL:QUERY}</code></td>
+<td width="75%"><code>?q=e&s=t</code></td></tr>
+<tr><td width="25%"><code>{URL:USERINFO}</code></td>
+<td width="75%"><code>user:pw</code></td></tr>
+<tr><td width="25%"><code>{URL:USERNAME}</code></td>
+<td width="75%"><code>user</code></td></tr>
+<tr><td width="25%"><code>{URL:PASSWORD}</code></td>
+<td width="75%"><code>pw</code></td></tr>
+</table>
+<br />
+<code>{BASE}</code> supports exactly the same parts as <code>{URL}</code>.
+
+
 </body></html>
 
diff --git a/Docs/Chm/help/base/security.html b/Docs/Chm/help/base/security.html
index 9a5cad2..ad3e044 100644
--- a/Docs/Chm/help/base/security.html
+++ b/Docs/Chm/help/base/security.html
@@ -52,6 +52,7 @@ Detailed information about the security of KeePass.
 <li><a href="#secplugins">Plugins</a></li>
 <li><a href="#secselftests">Self-Tests</a></li>
 <li><a href="#secspecattacks">Specialized Spyware</a></li>
+<li><a href="#secissues">Security Issues</a></li>
 <li><a href="#secref">References</a></li>
 </ul>
 
@@ -410,6 +411,17 @@ in any case it can't be KeePass.</p>
 
 <br />
 
+<a name="secissues"></a>
+<h2 class="sectiontitle">
+<img src="../images/b16x16_message.png" class="singleimg" alt="Message" />  Security
+Issues</h2>
+
+<p>For a list of security issues, their status and clarifications, please see the page
+<a href="http://keepass.info/help/kb/sec_issues.html"
+target="_blank">Security Issues</a>.</p>
+
+<br />
+
 <a name="secref"></a>
 <h2 class="sectiontitle">
 <img src="../images/b16x16_kmultiple.png" class="singleimg" alt="References" />  References
diff --git a/Docs/Chm/help/v2/setup.html b/Docs/Chm/help/v2/setup.html
index fba29ff..400fcde 100644
--- a/Docs/Chm/help/v2/setup.html
+++ b/Docs/Chm/help/v2/setup.html
@@ -194,8 +194,8 @@ your system.</p>
 <img src="../images/b16x16_package_system.png" class="singleimg" alt="Setup" />  Running
 KeePass under Mono (Linux, Mac OS X, BSD, ...)</h2>
 
-<p>In addition to Windows, KeePass 2.x runs fine under Mono, i.e. Linux, Mac OS X,
-BSD, etc.</p>
+<p>In addition to Windows, KeePass 2.x runs under Mono,
+i.e. Linux, Mac OS X, BSD, etc.</p>
 
 <p>Links to all supported packages can be found on the KeePass downloads page:
 <a href="http://keepass.info/download.html"
diff --git a/Docs/Chm/help/v2/xml_replace.html b/Docs/Chm/help/v2/xml_replace.html
index 72380b6..e56c516 100644
--- a/Docs/Chm/help/v2/xml_replace.html
+++ b/Docs/Chm/help/v2/xml_replace.html
@@ -61,6 +61,7 @@ About the XML replacement functionality.
 <li><a href="#atresetifstddelay">Reset default sequences that contain <code>{DELAY=</code></a></li>
 <li><a href="#ataddassoc">Add an auto-type association to all entries</a></li>
 </ul></li>
+<li><a href="#copytitles">Copy entry titles into empty user name fields</a></li>
 </ul></li>
 </ul>
 
@@ -83,6 +84,9 @@ and merges the current database with the modified database.</p>
 style="vertical-align: middle; height: 1em;" />
 This is a feature for experts. Use with caution!</p>
 
+<p>XML Replace can be invoked via 'Tools' -> 'Database Tools' ->
+'XML Replace'.</p>
+
 <p>A few links that might be helpful for working with XPath and
 regular expressions:</p>
 <ul>
@@ -341,5 +345,23 @@ i.e. the option 'Inherit default auto-type sequence from group' is activated.</t
 '<code>* - Notepad</code>' is associated with the sequence '<code>{PASSWORD}</code>'.</td></tr>
 </table>
 
+<br />
+
+<a name="copytitles"></a>
+<table class="tablebox">
+<colgroup><col width="20%" /><col width="80%" /></colgroup>
+<tr><th colspan="2">Copy entry titles into empty user name fields</th></tr>
+<tr><td>Select nodes:</td>
+<td><code>//Entry/String[Key='UserName' and Value='']/..</code></td></tr>
+<tr><td>Action:</td><td>Replace data</td></tr>
+<tr><td>Data:</td><td>Inner XML</td></tr>
+<tr><td>Find what:</td><td><code>(?s)(<Key>Title</Key>\s*?<Value>)(.*?)(</Value>.+?<Key>UserName</Key>\s*?)<Value /></code></td></tr>
+<tr><td>Replace with:</td><td><code>$1$2$3<Value>$2</Value></code></td></tr>
+<tr><td>Case-sensitive:</td><td>Activated</td></tr>
+<tr><td>Regular expressions:</td><td>Activated</td></tr>
+<tr><td colspan="2">Copies the entry title into the user name field of the
+entry, if this field is empty.</td></tr>
+</table>
+
 </body></html>
 
diff --git a/Docs/Chm/help/v2_dev/scr_sc_index.html b/Docs/Chm/help/v2_dev/scr_sc_index.html
index 3499464..45fc2af 100644
--- a/Docs/Chm/help/v2_dev/scr_sc_index.html
+++ b/Docs/Chm/help/v2_dev/scr_sc_index.html
@@ -158,7 +158,10 @@ Usage examples:</p>
 <p>The <code>-GroupName:</code> parameter can be used to specify the group in which the
 entry is created. For searching, KPScript performs a pre-order traversal and uses the
 first matching group (the name is case-sensitive). If no group with the specified name is
-found, it will be created in the root group. If you do not specify a group name,
+found, it will be created in the root group.
+Alternatively, the full path of the group can be specified using the
+<code>-GroupPath:</code> parameter (use '<code>/</code>' as separator).
+If you do not specify a group name or path,
 the entry will be created in the root group. Example:</p>
 
 <p><code>KPScript -c:AddEntry "C:\KeePass\MyDb.kdbx" -pw:MyPw -Title:"My Provider"
@@ -218,10 +221,12 @@ first create backups of entries before modifying them.</p>
 <p>This command moves one or more existing entries. The entry identification
 syntax is exactly the same as in the <code>EditEntry</code> command.</p>
 
-<p>The target group can be specified using the <code>GroupTree</code>
+<p>The target group can be specified using the <code>-GroupPath:</code>
 parameter. '<code>/</code>' must be used as separator
-(e.g. <code>-GroupTree:Internet/eMail</code> moves the specified entries
-to the subgroup 'eMail' of the subgroup 'Internet').</p>
+(e.g. <code>-GroupPath:Internet/eMail</code> moves the specified entries
+to the subgroup 'eMail' of the subgroup 'Internet').
+Alternatively, the <code>-GroupName:</code> parameter can be used
+(see the 'AddEntry' command for details).</p>
 
 <hr />
 <p><b>Command: DeleteEntry</b></p>
@@ -271,6 +276,9 @@ export dialog of KeePass). The file to export to is specified using the
 
 <p><code>KPScript -c:Export "C:\KeePass\MyDb.kdbx" -pw:MyPw -Format:"KeePass XML (2.x)" -OutFile:TargetFile.xml</code></p>
 
+<p>For the XSL transformation export module, the path of the XSL file
+can be passed using the "-XslFile" parameter.</p>
+
 <hr />
 <p><b>Command: Sync</b></p>
 
diff --git a/Docs/History.txt b/Docs/History.txt
index 67e7b92..b210874 100644
--- a/Docs/History.txt
+++ b/Docs/History.txt
@@ -1,3 +1,65 @@
+2015-08-09: 2.30
+- When opening a database via an URL fails, the error message
+  dialog now has a button 'Specify different server
+  credentials' (on Windows Vista and higher)
+- Added support for opening entry URLs with Microsoft Edge via
+  the context menu -> 'URL(s)' -> 'Open with Edge'
+- Added URL override suggestion for Microsoft Edge in the URL
+  override suggestions drop-down list in the entry dialog
+- Added optional built-in global URL overrides for opening
+  HTTP/HTTPS URLs with Microsoft Edge
+- When clicking on a group link in the entry view, KeePass now
+  ensures that the group is visible in the group tree
+- The main window is now moved onto the primary screen when it
+  is restored outside all screens
+- KDBX loader: added support for non-empty protected binary
+  value reference elements
+- Plugins: added two auto-type sequence query events
+- Added workaround for Mono drawing bug when scrolling a rich
+  text box
+- When running under Mono, some automatic locking options are
+  now disabled (because Mono doesn't implement the required
+  events)
+- The installer now prevents running the installer while it is
+  already running
+- KPScript: added '-GroupPath:' parameter (for specifying the
+  full path of a group)
+- KPScript: the 'MoveEntry' command now also supports the
+  '-GroupName:' parameter (as alternative to '-GroupPath:')
+- KPScript: added support for specifying the path of an XSL
+  stylesheet file using the command line parameter '-XslFile:'
+- KPScript: the 'ListGroups' command now also outputs the
+  parent group UUID for each group
+- KPScript: the parameters for specifying new field data (for
+  the 'AddEntry' and the 'EditEntry' command) now support
+  escape sequences (e.g. '\n' is replaced by a new-line
+  character)
+
+- The 'Synchronize' file dialog now shows only KDBX files by
+  default
+- In the 'Attachments (Count)' column, only non-zero counts are
+  shown now
+- Improved MRU item refreshes
+- The entry string dialog now supports changing the case of a
+  string name
+- The entry string dialog now does not allow adding a string
+  whose name differs from another existing string name in this
+  entry only by case
+- The entry view in the main window is now updated immediately
+  after pressing Ctrl+H or Ctrl+J
+- The KDB import module now tries to round any invalid
+  date/time to the nearest valid date/time
+- XML serializers are now loaded/created at KeePass startup in
+  order to avoid a problem when shutting down Windows and
+  KeePass.XmlSerializers.dll not being present
+- Changed tab bar behavior in the options dialog to avoid a tab
+  content cropping issue caused by plugins
+- Improved workaround for Mono splitter bug
+- Upgraded installer
+- Various performance improvements
+- Various code optimizations
+- Minor other improvements
+
 2015-04-10: 2.29
 - Added high resolution icons
 - Added support for high resolution custom icons
diff --git a/Ext/KeePass.exe.config b/Ext/KeePass.exe.config
index d3be430..f68efe8 100644
--- a/Ext/KeePass.exe.config
+++ b/Ext/KeePass.exe.config
@@ -11,8 +11,8 @@
 				<assemblyIdentity name="KeePass"
 					publicKeyToken="fed2ed7716aecf5c"
 					culture="neutral" />
-				<bindingRedirect oldVersion="2.0.9.0-2.29.0.0"
-					newVersion="2.29.0.17893" />
+				<bindingRedirect oldVersion="2.0.9.0-2.30.0.0"
+					newVersion="2.30.0.15916" />
 			</dependentAssembly>
 		</assemblyBinding>
 		<enforceFIPSPolicy enabled="false" />
diff --git a/Ext/KeePass.iss b/Ext/KeePass.iss
index 78ece23..da98219 100644
--- a/Ext/KeePass.iss
+++ b/Ext/KeePass.iss
@@ -8,11 +8,11 @@
 #define MyAppNameEx "KeePass Password Safe 2"
 #define MyAppPublisher "Dominik Reichl"
 
-#define KeeVersionStr "2.29"
-#define KeeVersionStrWithMinor "2.29"
-#define KeeVersionStrWithMinorPath "2.29"
-#define KeeVersionWin "2.29.0.0"
-#define KeeVersionWinShort "2.29"
+#define KeeVersionStr "2.30"
+#define KeeVersionStrWithMinor "2.30"
+#define KeeVersionStrWithMinorPath "2.30"
+#define KeeVersionWin "2.30.0.0"
+#define KeeVersionWinShort "2.30"
 
 #define MyAppURL "http://keepass.info/"
 #define MyAppExeName "KeePass.exe"
@@ -43,6 +43,7 @@ SolidCompression=yes
 InternalCompressLevel=ultra
 UninstallDisplayIcon={app}\{#MyAppExeName}
 AppMutex=KeePassAppMutex,Global\KeePassAppMutexEx
+SetupMutex=KeePassSetupMutex2
 VersionInfoVersion={#KeeVersionWin}
 VersionInfoCompany={#MyAppPublisher}
 VersionInfoDescription={#MyAppName} {#KeeVersionStr} Setup
diff --git a/Ext/KeePassMsi/KeePassMsi.vdproj b/Ext/KeePassMsi/KeePassMsi.vdproj
index 0044d47..c123fe9 100644
--- a/Ext/KeePassMsi/KeePassMsi.vdproj
+++ b/Ext/KeePassMsi/KeePassMsi.vdproj
@@ -382,7 +382,7 @@
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:KeePass, Version=2.29.0.17893, Culture=neutral, PublicKeyToken=fed2ed7716aecf5c, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:KeePass, Version=2.30.0.15916, Culture=neutral, PublicKeyToken=fed2ed7716aecf5c, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
                     "_838987B3C51D42C3C7B9BDA1339A5500"
@@ -413,7 +413,7 @@
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:KeePass.XmlSerializers, Version=2.29.0.17893, Culture=neutral, PublicKeyToken=fed2ed7716aecf5c, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:KeePass.XmlSerializers, Version=2.30.0.15916, Culture=neutral, PublicKeyToken=fed2ed7716aecf5c, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
                     "_8C05ADB649434D7892E36709EBDED4CC"
@@ -564,7 +564,7 @@
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:KeePass, Version=2.29.0.17893, Culture=neutral, PublicKeyToken=fed2ed7716aecf5c, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:KeePass, Version=2.30.0.15916, Culture=neutral, PublicKeyToken=fed2ed7716aecf5c, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
                     "_C4F8814F844C43EE8C9F5B662182B11A"
@@ -711,15 +711,15 @@
         "Product"
         {
         "Name" = "8:Microsoft Visual Studio"
-        "ProductName" = "8:KeePass 2.29"
-        "ProductCode" = "8:{5621BB3B-DFF3-48CA-93FE-4A018FB593B0}"
-        "PackageCode" = "8:{ABBB6B2F-12E6-4CD5-B647-8863A7F0DE3A}"
+        "ProductName" = "8:KeePass 2.30"
+        "ProductCode" = "8:{18169642-7C53-4C93-A027-0AFB862D9DD5}"
+        "PackageCode" = "8:{DB88FEC6-3EE3-4E87-B0CA-00A8E11853D3}"
         "UpgradeCode" = "8:{F2F19898-4F86-4940-9BFA-426574CE03E1}"
         "RestartWWWService" = "11:FALSE"
         "RemovePreviousVersions" = "11:TRUE"
         "DetectNewerInstalledVersion" = "11:TRUE"
         "InstallAllUsers" = "11:TRUE"
-        "ProductVersion" = "8:2.29.0"
+        "ProductVersion" = "8:2.30.0"
         "Manufacturer" = "8:Dominik Reichl"
         "ARPHELPTELEPHONE" = "8:"
         "ARPHELPLINK" = "8:http://keepass.info/"
diff --git a/KeePass/App/Configuration/AceIntegration.cs b/KeePass/App/Configuration/AceIntegration.cs
index 65c1285..06c205f 100644
--- a/KeePass/App/Configuration/AceIntegration.cs
+++ b/KeePass/App/Configuration/AceIntegration.cs
@@ -313,6 +313,10 @@ namespace KeePass.App.Configuration
 			m_lBuiltInOverrides.Add(new AceUrlSchemeOverride(false, "https",
 				"cmd://{INTERNETEXPLORER} \"{BASE}\"", 0x4));
 			m_lBuiltInOverrides.Add(new AceUrlSchemeOverride(false, "http",
+				"microsoft-edge:{BASE}", 0x4000));
+			m_lBuiltInOverrides.Add(new AceUrlSchemeOverride(false, "https",
+				"microsoft-edge:{BASE}", 0x8000));
+			m_lBuiltInOverrides.Add(new AceUrlSchemeOverride(false, "http",
 				"cmd://{FIREFOX} \"{BASE}\"", 0x8));
 			m_lBuiltInOverrides.Add(new AceUrlSchemeOverride(false, "https",
 				"cmd://{FIREFOX} \"{BASE}\"", 0x10));
@@ -334,6 +338,7 @@ namespace KeePass.App.Configuration
 				"cmd://\"{APPDIR}\\KeePass.exe\" \"{BASE:RMVSCM}\" -pw-enc:\"{PASSWORD_ENC}\"", 0x1000));
 			m_lBuiltInOverrides.Add(new AceUrlSchemeOverride(false, "kdbx",
 				"cmd://mono \"{APPDIR}/KeePass.exe\" \"{BASE:RMVSCM}\" -pw-enc:\"{PASSWORD_ENC}\"", 0x2000));
+			// Free: 0x10000
 
 #if DEBUG
 			ulong u = 0;
diff --git a/KeePass/DataExchange/CsvStreamReaderEx.cs b/KeePass/DataExchange/CsvStreamReaderEx.cs
index f736e1a..da6bd85 100644
--- a/KeePass/DataExchange/CsvStreamReaderEx.cs
+++ b/KeePass/DataExchange/CsvStreamReaderEx.cs
@@ -144,8 +144,10 @@ namespace KeePass.DataExchange
 						if(chNum4 != char.MinValue) // Implies the others
 						{
 							StringBuilder sbNum = new StringBuilder();
-							sbNum.Append(chNum3); sbNum.Append(chNum4); // Little
-							sbNum.Append(chNum1); sbNum.Append(chNum2); // Endian
+							sbNum.Append(chNum3); // Little-endian
+							sbNum.Append(chNum4);
+							sbNum.Append(chNum1);
+							sbNum.Append(chNum2);
 
 							byte[] pbNum = MemUtil.HexStringToByteArray(sbNum.ToString());
 							ushort usNum = MemUtil.BytesToUInt16(pbNum);
diff --git a/KeePass/DataExchange/Formats/LastPassCsv2.cs b/KeePass/DataExchange/Formats/LastPassCsv2.cs
index 9d71952..27d65df 100644
--- a/KeePass/DataExchange/Formats/LastPassCsv2.cs
+++ b/KeePass/DataExchange/Formats/LastPassCsv2.cs
@@ -32,7 +32,7 @@ using KeePassLib.Utility;
 
 namespace KeePass.DataExchange.Formats
 {
-	// 2.0.2-2.0.20+
+	// 2.0.2-3.1.95+
 	internal sealed class LastPassCsv2 : FileFormatProvider
 	{
 		public override bool SupportsImport { get { return true; } }
diff --git a/KeePass/DataExchange/Formats/RoboFormHtml69.cs b/KeePass/DataExchange/Formats/RoboFormHtml69.cs
index 796a422..cd17b7b 100644
--- a/KeePass/DataExchange/Formats/RoboFormHtml69.cs
+++ b/KeePass/DataExchange/Formats/RoboFormHtml69.cs
@@ -36,7 +36,7 @@ using KeePassLib.Utility;
 
 namespace KeePass.DataExchange.Formats
 {
-	// 6.9.82-7.9.2.5+
+	// 6.9.82-7.9.13.5+
 	internal sealed class RoboFormHtml69 : FileFormatProvider
 	{
 		public override bool SupportsImport { get { return true; } }
diff --git a/KeePass/DataExchange/Formats/XslTransform2x.cs b/KeePass/DataExchange/Formats/XslTransform2x.cs
index 68f1815..60b9c57 100644
--- a/KeePass/DataExchange/Formats/XslTransform2x.cs
+++ b/KeePass/DataExchange/Formats/XslTransform2x.cs
@@ -40,6 +40,8 @@ namespace KeePass.DataExchange.Formats
 {
 	internal sealed class XslTransform2x : FileFormatProvider
 	{
+		private const string ParamXslFile = "XslFile";
+
 		public override bool SupportsImport { get { return false; } }
 		public override bool SupportsExport { get { return true; } }
 
@@ -54,13 +56,31 @@ namespace KeePass.DataExchange.Formats
 		public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
 			IStatusLogger slLogger)
 		{
+			string strXslFile;
+			pwExportInfo.Parameters.TryGetValue(ParamXslFile, out strXslFile);
+
+			if(string.IsNullOrEmpty(strXslFile))
+				strXslFile = UIGetXslFile();
+			if(string.IsNullOrEmpty(strXslFile))
+				return false;
+
+			return ExportEx(pwExportInfo, sOutput, slLogger, strXslFile);
+		}
+
+		private static string UIGetXslFile()
+		{
 			string strFilter = UIUtil.CreateFileTypeFilter("xsl", KPRes.XslFileType, true);
 			OpenFileDialogEx dlgXsl = UIUtil.CreateOpenFileDialog(KPRes.XslSelectFile,
 				strFilter, 1, "xsl", false, AppDefs.FileDialogContext.Xsl);
 
-			if(dlgXsl.ShowDialog() != DialogResult.OK) return false;
+			if(dlgXsl.ShowDialog() != DialogResult.OK) return null;
+
+			return dlgXsl.FileName;
+		}
 
-			string strXslFile = dlgXsl.FileName;
+		private bool ExportEx(PwExportInfo pwExportInfo, Stream sOutput,
+			IStatusLogger slLogger, string strXslFile)
+		{
 			XslCompiledTransform xsl = new XslCompiledTransform();
 
 			try { xsl.Load(strXslFile); }
diff --git a/KeePass/DataExchange/ImportUtil.cs b/KeePass/DataExchange/ImportUtil.cs
index e8986d1..2223fb0 100644
--- a/KeePass/DataExchange/ImportUtil.cs
+++ b/KeePass/DataExchange/ImportUtil.cs
@@ -317,7 +317,8 @@ namespace KeePass.DataExchange
 			if(bOpenFromUrl == false)
 			{
 				OpenFileDialogEx ofd = UIUtil.CreateOpenFileDialog(KPRes.Synchronize,
-					UIUtil.CreateFileTypeFilter(null, null, true), 1, null, true,
+					UIUtil.CreateFileTypeFilter(AppDefs.FileExtension.FileExt,
+					KPRes.KdbxFiles, true), 1, null, true,
 					AppDefs.FileDialogContext.Sync);
 
 				if(ofd.ShowDialog() != DialogResult.OK) return null;
diff --git a/KeePass/DataExchange/KdbManager.cs b/KeePass/DataExchange/KdbManager.cs
index a65a3c1..c38ce92 100644
--- a/KeePass/DataExchange/KdbManager.cs
+++ b/KeePass/DataExchange/KdbManager.cs
@@ -370,18 +370,42 @@ namespace KeePass.DataExchange
 		/// <summary>
 		/// Convert the current <c>KdbTime</c> object to a <c>DateTime</c> object.
 		/// </summary>
-		/// <returns></returns>
 		public DateTime ToDateTime()
 		{
 			if((this.Year == 0) || (this.Month == 0) || (this.Day == 0))
 				return DateTime.Now;
 
-			return new DateTime((int)this.Year, (int)this.Month, (int)this.Day,
-				(int)this.Hour, (int)this.Minute, (int)this.Second);
+			// https://sourceforge.net/p/keepass/discussion/329221/thread/07599afd/
+			try
+			{
+				int dy = (int)this.Year;
+				if(dy > 2999) { Debug.Assert(false); dy = 2999; }
+
+				int dm = (int)this.Month;
+				if(dm > 12) { Debug.Assert(false); dm = 12; }
+
+				int dd = (int)this.Day;
+				if(dd > 31) { Debug.Assert(false); dd = 28; }
+				// Day might not exist in month
+
+				int th = (int)this.Hour;
+				if(th > 23) { Debug.Assert(false); th = 23; }
+
+				int tm = (int)this.Minute;
+				if(tm > 59) { Debug.Assert(false); tm = 59; }
+
+				int ts = (int)this.Second;
+				if(ts > 59) { Debug.Assert(false); ts = 59; }
+
+				return new DateTime(dy, dm, dd, th, tm, ts);
+			}
+			catch(Exception) { Debug.Assert(false); }
+
+			return DateTime.Now;
 		}
 
 		/// <summary>
-		/// Copy data from a <c>DateTime object</c> to the current <c>KdbTime</c> object.
+		/// Copy data from a <c>DateTime</c> object to the current <c>KdbTime</c> object.
 		/// </summary>
 		/// <param name="dt">Data source.</param>
 		public void Set(DateTime dt)
diff --git a/KeePass/DataExchange/PwExportInfo.cs b/KeePass/DataExchange/PwExportInfo.cs
index 655b0a2..2b81427 100644
--- a/KeePass/DataExchange/PwExportInfo.cs
+++ b/KeePass/DataExchange/PwExportInfo.cs
@@ -56,6 +56,13 @@ namespace KeePass.DataExchange
 			get { return m_bExpDel; }
 		}
 
+		private Dictionary<string, string> m_dictParams =
+			new Dictionary<string, string>();
+		public Dictionary<string, string> Parameters
+		{
+			get { return m_dictParams; }
+		}
+
 		public PwExportInfo(PwGroup pgDataSource, PwDatabase pwContextInfo)
 		{
 			ConstructEx(pgDataSource, pwContextInfo, null);
@@ -71,7 +78,7 @@ namespace KeePass.DataExchange
 			bool? bExportDeleted)
 		{
 			if(pgDataSource == null) throw new ArgumentNullException("pgDataSource");
-			// pwContextInfo may be null.
+			// pwContextInfo may be null
 
 			m_pg = pgDataSource;
 			m_pd = pwContextInfo;
diff --git a/KeePass/Forms/EditStringForm.cs b/KeePass/Forms/EditStringForm.cs
index b6d66ec..2342ad3 100644
--- a/KeePass/Forms/EditStringForm.cs
+++ b/KeePass/Forms/EditStringForm.cs
@@ -23,17 +23,18 @@ using System.ComponentModel;
 using System.Drawing;
 using System.Text;
 using System.Windows.Forms;
-using System.Diagnostics;
 using System.Threading;
+using System.Diagnostics;
 
 using KeePass.App;
 using KeePass.UI;
 using KeePass.Resources;
 
 using KeePassLib;
+using KeePassLib.Collections;
 using KeePassLib.Delegates;
 using KeePassLib.Security;
-using KeePassLib.Collections;
+using KeePassLib.Utility;
 
 namespace KeePass.Forms
 {
@@ -45,7 +46,10 @@ namespace KeePass.Forms
 		private RichTextBoxContextMenu m_ctxValue = new RichTextBoxContextMenu();
 		private PwDatabase m_pwContext = null;
 
-		private volatile List<string> m_vSuggestedNames = new List<string>();
+		private List<string> m_lSuggestedNames = new List<string>();
+
+		private List<string> m_lStdNames = PwDefs.GetStandardFields();
+		private char[] m_vInvalidChars = new char[] { '{', '}' };
 
 		public EditStringForm()
 		{
@@ -105,72 +109,80 @@ namespace KeePass.Forms
 				m_cbProtect.Checked = m_psStringInitialValue.IsProtected;
 			}
 
-			ValidateStringName();
+			ValidateStringNameUI();
 
 			PopulateNamesComboBox();
 			// UIUtil.SetFocus(m_cmbStringName, this); // See PopulateNamesComboBox
 		}
 
-		private bool ValidateStringNameEx(string str)
+		private bool ValidateStringNameUI()
 		{
-			if(str == null) { Debug.Assert(false); return false; }
-
-			if(PwDefs.IsStandardField(str)) return false;
-			if(str.Length <= 0) return false;
+			string strResult;
+			bool bError;
+			bool b = ValidateStringName(m_cmbStringName.Text, out strResult,
+				out bError);
 
-			char[] vInvalidChars = new char[] { '{', '}' };
-			if(str.IndexOfAny(vInvalidChars) >= 0) return false;
+			m_lblValidationInfo.Text = strResult;
+			if(bError) m_cmbStringName.BackColor = AppDefs.ColorEditError;
+			else m_cmbStringName.ResetBackColor();
 
-			string strStart = (m_strStringName != null) ? m_strStringName : string.Empty;
-			if(!strStart.Equals(str) && m_vStringDict.Exists(str)) return false;
-			// See ValidateStringName
+			m_btnOK.Enabled = b;
+			return b;			
+		}
 
-			return true;
+		private bool ValidateStringName(string str)
+		{
+			string strResult;
+			bool bError;
+			return ValidateStringName(str, out strResult, out bError);
 		}
 
-		private bool ValidateStringName()
+		private bool ValidateStringName(string str, out string strResult,
+			out bool bError)
 		{
-			string str = m_cmbStringName.Text;
-			string strStart = (m_strStringName != null) ? m_strStringName : string.Empty;
-			char[] vInvalidChars = new char[]{ '{', '}' };
+			strResult = KPRes.FieldNameInvalid;
+			bError = true;
 
-			if(PwDefs.IsStandardField(str))
+			if(str == null) { Debug.Assert(false); return false; }
+
+			if(str.Length == 0)
 			{
-				m_lblValidationInfo.Text = KPRes.FieldNameInvalid;
-				m_cmbStringName.BackColor = AppDefs.ColorEditError;
-				m_btnOK.Enabled = false;
+				strResult = KPRes.FieldNamePrompt;
+				bError = false; // Name not acceptable, but no error
 				return false;
 			}
-			else if(str.Length <= 0)
-			{
-				m_lblValidationInfo.Text = KPRes.FieldNamePrompt;
-				m_cmbStringName.ResetBackColor();
-				m_btnOK.Enabled = false;
-				return false;
 
-			}
-			else if(str.IndexOfAny(vInvalidChars) >= 0)
+			if(str == m_strStringName) // Case-sensitive
 			{
-				m_lblValidationInfo.Text = KPRes.FieldNameInvalid;
-				m_cmbStringName.BackColor = AppDefs.ColorEditError;
-				m_btnOK.Enabled = false;
-				return false;
+				strResult = string.Empty;
+				bError = false;
+				return true;
 			}
-			else if(!strStart.Equals(str) && m_vStringDict.Exists(str))
+
+			foreach(string strStd in m_lStdNames)
 			{
-				m_lblValidationInfo.Text = KPRes.FieldNameExistsAlready;
-				m_cmbStringName.BackColor = AppDefs.ColorEditError;
-				m_btnOK.Enabled = false;
-				return false;
+				if(str.Equals(strStd, StrUtil.CaseIgnoreCmp))
+					return false;
 			}
+
+			if(str.IndexOfAny(m_vInvalidChars) >= 0) return false;
+
+			if(str.Equals(m_strStringName, StrUtil.CaseIgnoreCmp) &&
+				!m_vStringDict.Exists(str)) { } // Just changing case
 			else
 			{
-				m_lblValidationInfo.Text = string.Empty;
-				m_cmbStringName.ResetBackColor();
-				m_btnOK.Enabled = true;
+				foreach(string strExisting in m_vStringDict.GetKeys())
+				{
+					if(str.Equals(strExisting, StrUtil.CaseIgnoreCmp))
+					{
+						strResult = KPRes.FieldNameExistsAlready;
+						return false;
+					}
+				}
 			}
-			// See ValidateStringNameEx
 
+			strResult = string.Empty;
+			bError = false;
 			return true;
 		}
 
@@ -178,7 +190,7 @@ namespace KeePass.Forms
 		{
 			string strName = m_cmbStringName.Text;
 
-			if(!ValidateStringName())
+			if(!ValidateStringNameUI())
 			{
 				this.DialogResult = DialogResult.None;
 				return;
@@ -217,6 +229,12 @@ namespace KeePass.Forms
 
 		private void PopulateNamesCollectFunc()
 		{
+			try { PopulateNamesCollectFuncPriv(); }
+			catch(Exception) { Debug.Assert(false); }
+		}
+
+		private void PopulateNamesCollectFuncPriv()
+		{
 			if(m_pwContext == null) { Debug.Assert(false); return; }
 
 			EntryHandler eh = delegate(PwEntry pe)
@@ -225,10 +243,14 @@ namespace KeePass.Forms
 
 				foreach(KeyValuePair<string, ProtectedString> kvp in pe.Strings)
 				{
-					if(ValidateStringNameEx(kvp.Key) &&
-						!m_vSuggestedNames.Contains(kvp.Key))
+					if(ValidateStringName(kvp.Key) &&
+						!m_lSuggestedNames.Contains(kvp.Key))
 					{
-						m_vSuggestedNames.Add(kvp.Key);
+						// Do not suggest any case-insensitive variant of the
+						// initial string, otherwise the string case cannot
+						// be changed (due to auto-completion resetting it)
+						if(!kvp.Key.Equals(m_strStringName, StrUtil.CaseIgnoreCmp))
+							m_lSuggestedNames.Add(kvp.Key);
 					}
 				}
 
@@ -237,16 +259,16 @@ namespace KeePass.Forms
 
 			m_pwContext.RootGroup.TraverseTree(TraversalMethod.PreOrder, null, eh);
 
-			m_vSuggestedNames.Sort();
+			m_lSuggestedNames.Sort();
 
 			if(m_cmbStringName.InvokeRequired)
 				m_cmbStringName.Invoke(new VoidDelegate(this.PopulateNamesAddFunc));
-			else this.PopulateNamesAddFunc();
+			else PopulateNamesAddFunc();
 		}
 
 		private void PopulateNamesAddFunc()
 		{
-			foreach(string str in m_vSuggestedNames)
+			foreach(string str in m_lSuggestedNames)
 				m_cmbStringName.Items.Add(str);
 
 			UIUtil.SetFocus(m_cmbStringName, this);
@@ -264,7 +286,7 @@ namespace KeePass.Forms
 
 		private void OnNameTextChanged(object sender, EventArgs e)
 		{
-			ValidateStringName();
+			ValidateStringNameUI();
 		}
 
 		protected override bool ProcessDialogKey(Keys keyData)
diff --git a/KeePass/Forms/MainForm.cs b/KeePass/Forms/MainForm.cs
index af4d158..be2d4c3 100644
--- a/KeePass/Forms/MainForm.cs
+++ b/KeePass/Forms/MainForm.cs
@@ -352,20 +352,12 @@ namespace KeePass.Forms
 			{
 				double dSplitPos = mw.SplitterHorizontalFrac;
 				if(dSplitPos == double.Epsilon) dSplitPos = 0.8333;
-				// m_splitHorizontal.SplitterDistance = (int)Math.Round(dSplitPos *
-				//	(double)m_splitHorizontal.Height);
 				if(MonoWorkarounds.IsRequired(686017))
-				{
-					int iSplitDist = (int)Math.Round(dSplitPos *
-						(double)m_splitHorizontal.Height);
-					m_splitHorizontal.SplitterDistance = Math.Max(35, iSplitDist);
-				}
-				else m_splitHorizontal.SplitterDistanceFrac = dSplitPos;
+					m_splitHorizontal.Panel1MinSize = 35;
+				m_splitHorizontal.SplitterDistanceFrac = dSplitPos;
 
 				dSplitPos = mw.SplitterVerticalFrac;
 				if(dSplitPos == double.Epsilon) dSplitPos = 0.25;
-				// m_splitVertical.SplitterDistance = (int)Math.Round(dSplitPos *
-				//	(double)m_splitVertical.Width);
 				m_splitVertical.SplitterDistanceFrac = dSplitPos;
 			}
 			catch(Exception) { Debug.Assert(false); }
@@ -1922,6 +1914,10 @@ namespace KeePass.Forms
 				(pe.ParentGroup.Name == strLink))
 			{
 				UpdateUI(false, null, true, pe.ParentGroup, true, null, false);
+
+				TreeNode tnSel = m_tvGroups.SelectedNode;
+				if(tnSel != null) tnSel.EnsureVisible();
+
 				EnsureVisibleSelected(false);
 				ResetDefaultFocus(m_lvEntries);
 			}
diff --git a/KeePass/Forms/MainForm_Functions.cs b/KeePass/Forms/MainForm_Functions.cs
index d46fbca..5803dd3 100644
--- a/KeePass/Forms/MainForm_Functions.cs
+++ b/KeePass/Forms/MainForm_Functions.cs
@@ -25,6 +25,7 @@ using System.Collections.Generic;
 using System.Windows.Forms;
 using System.IO;
 using System.Threading;
+using System.Xml.Serialization;
 using System.Diagnostics;
 
 using KeePass.App;
@@ -2032,6 +2033,7 @@ namespace KeePass.Forms
 			if(OpenDatabaseRestoreIfOpened(ioc)) return;
 
 			PwDatabase pwOpenedDb = null;
+			bool bAbort;
 			if(cmpKey == null)
 			{
 				for(int iTry = 0; iTry < 3; ++iTry)
@@ -2079,13 +2081,14 @@ namespace KeePass.Forms
 						return;
 					}
 
-					pwOpenedDb = OpenDatabaseInternal(ioc, kpfResult.Key);
-					if(pwOpenedDb != null) break;
+					pwOpenedDb = OpenDatabaseInternal(ioc, kpfResult.Key,
+						out bAbort);
+					if((pwOpenedDb != null) || bAbort) break;
 				}
 			}
 			else // cmpKey != null
 			{
-				pwOpenedDb = OpenDatabaseInternal(ioc, cmpKey);
+				pwOpenedDb = OpenDatabaseInternal(ioc, cmpKey, out bAbort);
 			}
 
 			if((pwOpenedDb == null) || !pwOpenedDb.IsOpen)
@@ -2180,8 +2183,11 @@ namespace KeePass.Forms
 			ResetDefaultFocus(null);
 		}
 
-		private PwDatabase OpenDatabaseInternal(IOConnectionInfo ioc, CompositeKey cmpKey)
+		private PwDatabase OpenDatabaseInternal(IOConnectionInfo ioc,
+			CompositeKey cmpKey, out bool bAbort)
 		{
+			bAbort = false;
+
 			PerformSelfTest();
 
 			ShowWarningsLogger swLogger = CreateShowWarningsLogger();
@@ -2201,6 +2207,7 @@ namespace KeePass.Forms
 			if(ds == null) pwDb = m_docMgr.CreateNewDocument(true).Database;
 			else pwDb = ds.Database;
 
+			Exception ex = null;
 			try
 			{
 				pwDb.Open(ioc, cmpKey, swLogger);
@@ -2210,10 +2217,9 @@ namespace KeePass.Forms
 				Debug.Assert(MemUtil.ArraysEqual(pbDiskDirect, pwDb.HashOfFileOnDisk));
 #endif
 			}
-			catch(Exception ex)
+			catch(Exception exLoad)
 			{
-				MessageService.ShowLoadWarning(ioc.GetDisplayName(), ex,
-					(Program.CommandLineArgs[AppDefs.CommandLineOptions.Debug] != null));
+				ex = exLoad;
 				pwDb = null;
 			}
 
@@ -2224,6 +2230,52 @@ namespace KeePass.Forms
 				if(ds == null) m_docMgr.CloseDatabase(m_docMgr.ActiveDatabase);
 			}
 
+			if(ex != null)
+			{
+				string strMsg = MessageService.GetLoadWarningMessage(
+					ioc.GetDisplayName(), ex,
+					(Program.CommandLineArgs[AppDefs.CommandLineOptions.Debug] != null));
+
+				bool bShowStd = true;
+				if(!ioc.IsLocalFile())
+				{
+					VistaTaskDialog vtd = new VistaTaskDialog();
+					vtd.CommandLinks = false;
+					vtd.Content = strMsg;
+					vtd.DefaultButtonID = (int)DialogResult.Cancel;
+					// vtd.VerificationText = KPRes.CredSpecifyDifferent;
+					vtd.WindowTitle = PwDefs.ShortProductName;
+
+					vtd.SetIcon(VtdIcon.Warning);
+					vtd.AddButton((int)DialogResult.Cancel, KPRes.Ok, null);
+					vtd.AddButton((int)DialogResult.Retry,
+						KPRes.CredSpecifyDifferent, null);
+
+					if(vtd.ShowDialog(this))
+					{
+						bShowStd = false;
+
+						// if(vtd.ResultVerificationChecked)
+						if(vtd.Result == (int)DialogResult.Retry)
+						{
+							IOConnectionInfo iocNew = ioc.CloneDeep();
+							// iocNew.ClearCredentials(false);
+							iocNew.CredSaveMode = IOCredSaveMode.NoSave;
+							iocNew.IsComplete = false;
+							// iocNew.Password = string.Empty;
+
+							OpenDatabase(iocNew, null, false);
+
+							bAbort = true;
+						}
+					}
+				}
+
+				if(bShowStd) MessageService.ShowWarning(strMsg);
+				// MessageService.ShowLoadWarning(ioc.GetDisplayName(), ex,
+				//	(Program.CommandLineArgs[AppDefs.CommandLineOptions.Debug] != null));
+			}
+
 			return pwDb;
 		}
 
@@ -2753,6 +2805,8 @@ namespace KeePass.Forms
 			if(bRestoreWindow && (this.WindowState == FormWindowState.Minimized))
 				UIUtil.SetWindowState(this, FormWindowState.Normal);
 
+			UIUtil.EnsureInsideScreen(this);
+
 			try
 			{
 				if(this.Visible) // && (this.WindowState != FormWindowState.Minimized)
@@ -4653,7 +4707,8 @@ namespace KeePass.Forms
 					str = pe.History.UCount.ToString();
 					break;
 				case AceColumnType.AttachmentCount:
-					str = pe.Binaries.UCount.ToString();
+					uint uc = pe.Binaries.UCount;
+					str = ((uc > 0) ? uc.ToString() : string.Empty);
 					break;
 				default: Debug.Assert(false); str = string.Empty; break;
 			}
@@ -4710,6 +4765,7 @@ namespace KeePass.Forms
 			}
 
 			RefreshEntriesList();
+			UpdateUIState(false); // Update entry view
 		}
 
 		private void EditSelectedEntry(bool bSwitchToHistoryTab)
@@ -5055,6 +5111,13 @@ namespace KeePass.Forms
 				WinUtil.RemoveZoneIdentifier(WinUtil.GetExecutable());
 				WinUtil.RemoveZoneIdentifier(AppHelp.LocalHelpFile);
 				WinUtil.RemoveZoneIdentifier(strShInstUtil);
+
+				// http://stackoverflow.com/questions/26256917/how-can-i-prevent-my-application-from-causing-a-0xc0000142-error-in-csc-exe
+				XmlSerializer xs = new XmlSerializer(typeof(IpcParamEx));
+				IpcParamEx ipc = new IpcParamEx();
+				MemoryStream ms = new MemoryStream();
+				xs.Serialize(ms, ipc);
+				ms.Close();
 			}
 			catch(Exception) { Debug.Assert(false); }
 		}
diff --git a/KeePass/Forms/OptionsForm.Designer.cs b/KeePass/Forms/OptionsForm.Designer.cs
index 9eae79e..408342b 100644
--- a/KeePass/Forms/OptionsForm.Designer.cs
+++ b/KeePass/Forms/OptionsForm.Designer.cs
@@ -130,7 +130,6 @@
 			this.m_tabMain.Controls.Add(this.m_tabIntegration);
 			this.m_tabMain.Controls.Add(this.m_tabAdvanced);
 			this.m_tabMain.Location = new System.Drawing.Point(12, 66);
-			this.m_tabMain.Multiline = true;
 			this.m_tabMain.Name = "m_tabMain";
 			this.m_tabMain.SelectedIndex = 0;
 			this.m_tabMain.Size = new System.Drawing.Size(562, 337);
diff --git a/KeePass/Forms/OptionsForm.cs b/KeePass/Forms/OptionsForm.cs
index 82d61c7..f2b4d48 100644
--- a/KeePass/Forms/OptionsForm.cs
+++ b/KeePass/Forms/OptionsForm.cs
@@ -109,6 +109,11 @@ namespace KeePass.Forms
 			// Can be invoked by tray command; don't use CenterParent
 			Debug.Assert(this.StartPosition == FormStartPosition.CenterScreen);
 
+			// When multiline is enabled, tabs added by plugins can result
+			// in multiple tab rows, cropping the tab content at the bottom;
+			// https://sourceforge.net/p/keepass/discussion/329220/thread/a17a2734/
+			Debug.Assert(!m_tabMain.Multiline);
+
 			GlobalWindowManager.AddWindow(this);
 
 			this.Icon = Properties.Resources.KeePass;
@@ -257,14 +262,26 @@ namespace KeePass.Forms
 
 			m_cdxSecurityOptions = new CheckedLVItemDXList(m_lvSecurityOptions, true);
 
+			bool? obNoSEv = null; // Allow read-only by enforced config
+			string strSEvSuffix = string.Empty;
+			if(MonoWorkarounds.IsRequired(1378))
+			{
+				aceWL.LockOnSessionSwitch = false;
+				aceWL.LockOnSuspend = false;
+				aceWL.LockOnRemoteControlChange = false;
+
+				obNoSEv = true;
+				strSEvSuffix = " (" + KPRes.UnsupportedByMono + ")";
+			}
+
 			m_cdxSecurityOptions.CreateItem(aceWL, "LockOnWindowMinimize",
 				lvg, KPRes.LockOnMinimize);
 			m_cdxSecurityOptions.CreateItem(aceWL, "LockOnSessionSwitch",
-				lvg, KPRes.LockOnSessionSwitch);
+				lvg, KPRes.LockOnSessionSwitch + strSEvSuffix, obNoSEv);
 			m_cdxSecurityOptions.CreateItem(aceWL, "LockOnSuspend",
-				lvg, KPRes.LockOnSuspend);
+				lvg, KPRes.LockOnSuspend + strSEvSuffix, obNoSEv);
 			m_cdxSecurityOptions.CreateItem(aceWL, "LockOnRemoteControlChange",
-				lvg, KPRes.LockOnRemoteControlChange);
+				lvg, KPRes.LockOnRemoteControlChange + strSEvSuffix, obNoSEv);
 			m_cdxSecurityOptions.CreateItem(aceWL, "ExitInsteadOfLockingAfterTime",
 				lvg, KPRes.ExitInsteadOfLockingAfterTime);
 			m_cdxSecurityOptions.CreateItem(aceWL, "AlwaysExitInsteadOfLocking",
@@ -279,8 +296,16 @@ namespace KeePass.Forms
 				m_cdxSecurityOptions.CreateItem(Program.Config.Native, "NativeKeyTransformations",
 					lvg, KPRes.NativeLibUse);
 
+			bool? obNoWin = null; // Allow read-only by enforced config
+			if(NativeLib.IsUnix())
+			{
+				Program.Config.Security.MasterKeyOnSecureDesktop = false;
+
+				obNoWin = true;
+			}
+
 			m_cdxSecurityOptions.CreateItem(Program.Config.Security, "MasterKeyOnSecureDesktop",
-				lvg, KPRes.MasterKeyOnSecureDesktop);
+				lvg, KPRes.MasterKeyOnSecureDesktop, obNoWin);
 			m_cdxSecurityOptions.CreateItem(Program.Config.Security, "ClearKeyCommandLineParams",
 				lvg, KPRes.ClearKeyCmdLineParams);
 
diff --git a/KeePass/Forms/PwEntryForm.cs b/KeePass/Forms/PwEntryForm.cs
index 0a7cdeb..268cc0e 100644
--- a/KeePass/Forms/PwEntryForm.cs
+++ b/KeePass/Forms/PwEntryForm.cs
@@ -1689,8 +1689,8 @@ namespace KeePass.Forms
 			if(strFilter != null) strFlt += strFilter;
 			strFlt += KPRes.AllFiles + @" (*.*)|*.*";
 
-			OpenFileDialogEx dlg = UIUtil.CreateOpenFileDialog(null, strFlt, 1, null,
-				false, AppDefs.FileDialogContext.Attachments);
+			OpenFileDialogEx dlg = UIUtil.CreateOpenFileDialog(null, strFlt, 1,
+				null, false, AppDefs.FileDialogContext.Attachments);
 
 			if(dlg.ShowDialog() == DialogResult.OK)
 				m_tbUrl.Text = "cmd://\"" + dlg.FileName + "\"";
@@ -1981,6 +1981,8 @@ namespace KeePass.Forms
 
 			AddOverrideUrlItem(l, "cmd://{INTERNETEXPLORER} \"{URL}\"",
 				AppLocator.InternetExplorerPath);
+			AddOverrideUrlItem(l, "microsoft-edge:{URL}",
+				AppLocator.EdgePath);
 			AddOverrideUrlItem(l, "cmd://{FIREFOX} \"{URL}\"",
 				AppLocator.FirefoxPath);
 			AddOverrideUrlItem(l, "cmd://{OPERA} \"{URL}\"",
diff --git a/KeePass/Plugins/IPluginHost.cs b/KeePass/Plugins/IPluginHost.cs
index cd535f5..d3983cd 100644
--- a/KeePass/Plugins/IPluginHost.cs
+++ b/KeePass/Plugins/IPluginHost.cs
@@ -51,7 +51,7 @@ namespace KeePass.Plugins
 		PwDatabase Database { get; }
 
 		/// <summary>
-		/// Reference to the command-line arguments.
+		/// Reference to the command line arguments.
 		/// </summary>
 		CommandLineArgs CommandLineArgs { get; }
 
diff --git a/KeePass/Properties/AssemblyInfo.cs b/KeePass/Properties/AssemblyInfo.cs
index 2fea0d8..a61374c 100644
--- a/KeePass/Properties/AssemblyInfo.cs
+++ b/KeePass/Properties/AssemblyInfo.cs
@@ -38,5 +38,5 @@ using System.Runtime.InteropServices;
 [assembly: Guid("02020c52-c0da-47c0-9f3f-a6fe76cee400")]
 
 // Assembly version information
-[assembly: AssemblyVersion("2.29.0.*")]
-[assembly: AssemblyFileVersion("2.29.0.0")]
+[assembly: AssemblyVersion("2.30.0.*")]
+[assembly: AssemblyFileVersion("2.30.0.0")]
diff --git a/KeePass/Resources/KPRes.Generated.cs b/KeePass/Resources/KPRes.Generated.cs
index 7d9d689..453d8f1 100644
--- a/KeePass/Resources/KPRes.Generated.cs
+++ b/KeePass/Resources/KPRes.Generated.cs
@@ -172,6 +172,7 @@ namespace KeePass.Resources
 			m_strCredSaveAll = TryGetEx(dictNew, "CredSaveAll", m_strCredSaveAll);
 			m_strCredSaveNone = TryGetEx(dictNew, "CredSaveNone", m_strCredSaveNone);
 			m_strCredSaveUserOnly = TryGetEx(dictNew, "CredSaveUserOnly", m_strCredSaveUserOnly);
+			m_strCredSpecifyDifferent = TryGetEx(dictNew, "CredSpecifyDifferent", m_strCredSpecifyDifferent);
 			m_strCsprojCountError = TryGetEx(dictNew, "CsprojCountError", m_strCsprojCountError);
 			m_strCsvTextFile = TryGetEx(dictNew, "CsvTextFile", m_strCsvTextFile);
 			m_strCurrentStyle = TryGetEx(dictNew, "CurrentStyle", m_strCurrentStyle);
@@ -686,6 +687,7 @@ namespace KeePass.Resources
 			m_strUnhideSourceCharactersToo = TryGetEx(dictNew, "UnhideSourceCharactersToo", m_strUnhideSourceCharactersToo);
 			m_strUnknown = TryGetEx(dictNew, "Unknown", m_strUnknown);
 			m_strUnknownError = TryGetEx(dictNew, "UnknownError", m_strUnknownError);
+			m_strUnsupportedByMono = TryGetEx(dictNew, "UnsupportedByMono", m_strUnsupportedByMono);
 			m_strUpdateCheck = TryGetEx(dictNew, "UpdateCheck", m_strUpdateCheck);
 			m_strUpdateCheckEnableQ = TryGetEx(dictNew, "UpdateCheckEnableQ", m_strUpdateCheckEnableQ);
 			m_strUpdateCheckFailedNoDl = TryGetEx(dictNew, "UpdateCheckFailedNoDl", m_strUpdateCheckFailedNoDl);
@@ -889,6 +891,7 @@ namespace KeePass.Resources
 			"CredSaveAll",
 			"CredSaveNone",
 			"CredSaveUserOnly",
+			"CredSpecifyDifferent",
 			"CsprojCountError",
 			"CsvTextFile",
 			"CurrentStyle",
@@ -1403,6 +1406,7 @@ namespace KeePass.Resources
 			"UnhideSourceCharactersToo",
 			"Unknown",
 			"UnknownError",
+			"UnsupportedByMono",
 			"UpdateCheck",
 			"UpdateCheckEnableQ",
 			"UpdateCheckFailedNoDl",
@@ -3070,6 +3074,17 @@ namespace KeePass.Resources
 			get { return m_strCredSaveUserOnly; }
 		}
 
+		private static string m_strCredSpecifyDifferent =
+			@"&Specify different server credentials";
+		/// <summary>
+		/// Look up a localized string similar to
+		/// '&Specify different server credentials'.
+		/// </summary>
+		public static string CredSpecifyDifferent
+		{
+			get { return m_strCredSpecifyDifferent; }
+		}
+
 		private static string m_strCsprojCountError =
 			@"There must be exactly one .csproj or .vbproj file.";
 		/// <summary>
@@ -8724,6 +8739,17 @@ namespace KeePass.Resources
 			get { return m_strUnknownError; }
 		}
 
+		private static string m_strUnsupportedByMono =
+			@"unsupported by Mono";
+		/// <summary>
+		/// Look up a localized string similar to
+		/// 'unsupported by Mono'.
+		/// </summary>
+		public static string UnsupportedByMono
+		{
+			get { return m_strUnsupportedByMono; }
+		}
+
 		private static string m_strUpdateCheck =
 			@"Update Check";
 		/// <summary>
diff --git a/KeePass/UI/CustomRichTextBoxEx.cs b/KeePass/UI/CustomRichTextBoxEx.cs
index cef64e2..7429b31 100644
--- a/KeePass/UI/CustomRichTextBoxEx.cs
+++ b/KeePass/UI/CustomRichTextBoxEx.cs
@@ -27,10 +27,14 @@ using System.Diagnostics;
 
 using KeePass.Util;
 
+using KeePassLib.Utility;
+
 namespace KeePass.UI
 {
 	public sealed class CustomRichTextBoxEx : RichTextBox
 	{
+		private static bool? m_bForceRedrawOnScroll = null;
+
 		private bool m_bSimpleTextOnly = false;
 		[Browsable(false)]
 		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
@@ -421,5 +425,27 @@ namespace KeePass.UI
 
 			return true;
 		} */
+
+		protected override void OnHScroll(EventArgs e)
+		{
+			base.OnHScroll(e);
+
+			MonoRedrawOnScroll();
+		}
+
+		protected override void OnVScroll(EventArgs e)
+		{
+			base.OnVScroll(e);
+
+			MonoRedrawOnScroll();
+		}
+
+		private void MonoRedrawOnScroll()
+		{
+			if(!m_bForceRedrawOnScroll.HasValue)
+				m_bForceRedrawOnScroll = MonoWorkarounds.IsRequired(1366);
+
+			if(m_bForceRedrawOnScroll.Value) Invalidate();
+		}
 	}
 }
diff --git a/KeePass/UI/MruList.cs b/KeePass/UI/MruList.cs
index 0992023..7444a87 100644
--- a/KeePass/UI/MruList.cs
+++ b/KeePass/UI/MruList.cs
@@ -181,10 +181,11 @@ namespace KeePass.UI
 				}
 			}
 
-			if(bExists) MoveItemToTop(strDisplayName);
+			if(bExists) MoveItemToTop(strDisplayName, oTag);
 			else
 			{
-				m_vItems.Insert(0, new KeyValuePair<string, object>(strDisplayName, oTag));
+				m_vItems.Insert(0, new KeyValuePair<string, object>(
+					strDisplayName, oTag));
 
 				if(m_vItems.Count > m_uMaxItemCount)
 					m_vItems.RemoveAt(m_vItems.Count - 1);
@@ -193,16 +194,17 @@ namespace KeePass.UI
 			// if(bUpdateMenu) UpdateMenu();
 		}
 
-		private void MoveItemToTop(string strName)
+		private void MoveItemToTop(string strName, object oNewTag)
 		{
 			for(int i = 0; i < m_vItems.Count; ++i)
 			{
 				if(m_vItems[i].Key.Equals(strName, StrUtil.CaseIgnoreCmp))
 				{
-					KeyValuePair<string, object> t = m_vItems[i];
+					KeyValuePair<string, object> t =
+						new KeyValuePair<string, object>(strName, oNewTag);
+
 					m_vItems.RemoveAt(i);
 					m_vItems.Insert(0, t);
-
 					return;
 				}
 			}
diff --git a/KeePass/UI/OpenWithMenu.cs b/KeePass/UI/OpenWithMenu.cs
index 60c100e..9ab08a4 100644
--- a/KeePass/UI/OpenWithMenu.cs
+++ b/KeePass/UI/OpenWithMenu.cs
@@ -38,11 +38,29 @@ using KeePassLib.Utility;
 
 namespace KeePass.UI
 {
+	internal enum OwFilePathType
+	{
+		/// <summary>
+		/// Path to an executable file that is invoked with
+		/// the target URI as command line parameter.
+		/// </summary>
+		Executable = 0,
+
+		/// <summary>
+		/// Shell path (e.g. URI) in which a placeholder is
+		/// replaced by the target URI.
+		/// </summary>
+		ShellExpand
+	}
+
 	internal sealed class OpenWithItem
 	{
 		private string m_strPath;
 		public string FilePath { get { return m_strPath; } }
 
+		private OwFilePathType m_tPath;
+		public OwFilePathType FilePathType { get { return m_tPath; } }
+
 		private string m_strMenuText;
 		// public string MenuText { get { return m_strMenuText; } }
 
@@ -52,10 +70,11 @@ namespace KeePass.UI
 		private ToolStripMenuItem m_tsmi;
 		public ToolStripMenuItem MenuItem { get { return m_tsmi; } }
 
-		private OpenWithItem(string strFilePath, string strMenuText,
-			Image imgIcon, DynamicMenu dynMenu)
+		public OpenWithItem(string strFilePath, OwFilePathType tPath,
+			string strMenuText, Image imgIcon, DynamicMenu dynMenu)
 		{
 			m_strPath = strFilePath;
+			m_tPath = tPath;
 			m_strMenuText = strMenuText;
 			m_imgIcon = imgIcon;
 
@@ -64,12 +83,6 @@ namespace KeePass.UI
 			try { m_tsmi.ToolTipText = m_strPath; }
 			catch(Exception) { } // Too long?
 		}
-
-		public static OpenWithItem Create(string strFilePath, string strMenuText,
-			Image imgIcon, DynamicMenu dynMenu)
-		{
-			return new OpenWithItem(strFilePath, strMenuText, imgIcon, dynMenu);
-		}
 	}
 
 	public sealed class OpenWithMenu
@@ -79,6 +92,8 @@ namespace KeePass.UI
 
 		private List<OpenWithItem> m_lOpenWith = null;
 
+		private const string PlhTargetUri = @"{OW_URI}";
+
 		public OpenWithMenu(ToolStripDropDownItem tsmiHost)
 		{
 			if(tsmiHost == null) { Debug.Assert(false); return; }
@@ -169,6 +184,8 @@ namespace KeePass.UI
 			OpenWithItem it = (e.Tag as OpenWithItem);
 			if(it == null) { Debug.Assert(false); return; }
 
+			string strApp = it.FilePath;
+
 			PwEntry[] v = Program.MainForm.GetSelectedEntries();
 			if(v == null) { Debug.Assert(false); return; }
 
@@ -177,7 +194,14 @@ namespace KeePass.UI
 				string strUrl = pe.Strings.ReadSafe(PwDefs.UrlField);
 				if(string.IsNullOrEmpty(strUrl)) continue;
 
-				WinUtil.OpenUrlWithApp(strUrl, pe, it.FilePath);
+				if(it.FilePathType == OwFilePathType.Executable)
+					WinUtil.OpenUrlWithApp(strUrl, pe, strApp);
+				else if(it.FilePathType == OwFilePathType.ShellExpand)
+				{
+					string str = strApp.Replace(PlhTargetUri, strUrl);
+					WinUtil.OpenUrl(str, pe, false);
+				}
+				else { Debug.Assert(false); }
 			}
 		}
 
@@ -206,14 +230,38 @@ namespace KeePass.UI
 				DpiUtil.ScaleIntY(16));
 
 			string strMenuText = KPRes.OpenWith.Replace(@"{PARAM}", strName);
-			OpenWithItem owi = OpenWithItem.Create(strPath, strMenuText,
-				img, m_dynMenu);
+			OpenWithItem owi = new OpenWithItem(strPath, OwFilePathType.Executable,
+				strMenuText, img, m_dynMenu);
+			m_lOpenWith.Add(owi);
+		}
+
+		private void AddAppByShellExpand(string strShell, string strName,
+			string strIconExe)
+		{
+			if(string.IsNullOrEmpty(strShell)) return;
+
+			if(string.IsNullOrEmpty(strName))
+				strName = strShell;
+
+			Image img = null;
+			if(!string.IsNullOrEmpty(strIconExe))
+				img = UIUtil.GetFileIcon(strIconExe, DpiUtil.ScaleIntX(16),
+					DpiUtil.ScaleIntY(16));
+
+			string strMenuText = KPRes.OpenWith.Replace(@"{PARAM}", strName);
+			OpenWithItem owi = new OpenWithItem(strShell, OwFilePathType.ShellExpand,
+				strMenuText, img, m_dynMenu);
 			m_lOpenWith.Add(owi);
 		}
 
 		private void FindAppsByKnown()
 		{
 			AddAppByFile(AppLocator.InternetExplorerPath, @"&Internet Explorer");
+
+			if(AppLocator.EdgeProtocolSupported)
+				AddAppByShellExpand("microsoft-edge:" + PlhTargetUri, @"&Edge",
+					AppLocator.EdgePath);
+
 			AddAppByFile(AppLocator.FirefoxPath, @"&Firefox");
 			AddAppByFile(AppLocator.OperaPath, @"O&pera");
 			AddAppByFile(AppLocator.ChromePath, @"&Google Chrome");
diff --git a/KeePass/UI/UIUtil.cs b/KeePass/UI/UIUtil.cs
index fedd857..ecc3319 100644
--- a/KeePass/UI/UIUtil.cs
+++ b/KeePass/UI/UIUtil.cs
@@ -2033,6 +2033,49 @@ namespace KeePass.UI
 			return false;
 		}
 
+		public static void EnsureInsideScreen(Form f)
+		{
+			if(f == null) { Debug.Assert(false); return; }
+
+			try
+			{
+				if(!f.Visible) return; // No assert
+				if(f.WindowState != FormWindowState.Normal) return;
+
+				int x = f.Location.X;
+				int y = f.Location.Y;
+				int w = f.Size.Width;
+				int h = f.Size.Height;
+
+				Debug.Assert((x != -32000) && (x != -64000));
+				Debug.Assert(x != AppDefs.InvalidWindowValue);
+				Debug.Assert((y != -32000) && (y != -64000));
+				Debug.Assert(y != AppDefs.InvalidWindowValue);
+				Debug.Assert(w != AppDefs.InvalidWindowValue);
+				Debug.Assert(h != AppDefs.InvalidWindowValue);
+
+				Rectangle rect = new Rectangle(x, y, w, h);
+				if(IsScreenAreaVisible(rect)) return;
+
+				Screen scr = Screen.PrimaryScreen;
+				Rectangle rectScr = scr.Bounds;
+				BoundsSpecified bs = BoundsSpecified.Location;
+
+				if((w > rectScr.Width) || (h > rectScr.Height))
+				{
+					w = Math.Min(w, rectScr.Width);
+					h = Math.Min(h, rectScr.Height);
+					bs |= BoundsSpecified.Size;
+				}
+
+				x = rectScr.X + ((rectScr.Width - w) / 2);
+				y = rectScr.Y + ((rectScr.Height - h) / 2);
+
+				f.SetBounds(x, y, w, h, bs);				
+			}
+			catch(Exception) { Debug.Assert(false); }
+		}
+
 		public static string GetWindowScreenRect(Form f)
 		{
 			if(f == null) { Debug.Assert(false); return string.Empty; }
diff --git a/KeePass/Util/AppLocator.cs b/KeePass/Util/AppLocator.cs
index fda4150..bf8ffdb 100644
--- a/KeePass/Util/AppLocator.cs
+++ b/KeePass/Util/AppLocator.cs
@@ -21,6 +21,7 @@ using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Text;
+using System.IO;
 using System.Diagnostics;
 
 using Microsoft.Win32;
@@ -40,6 +41,7 @@ namespace KeePass.Util
 		private const int BrwOpera = 2;
 		private const int BrwChrome = 3;
 		private const int BrwSafari = 4;
+		private const int BrwEdge = 5;
 
 		private static Dictionary<int, string> m_dictPaths =
 			new Dictionary<int, string>();
@@ -69,6 +71,39 @@ namespace KeePass.Util
 			get { return GetPath(BrwSafari, FindSafari); }
 		}
 
+		/// <summary>
+		/// Edge executable cannot be run normally.
+		/// </summary>
+		public static string EdgePath
+		{
+			get { return GetPath(BrwEdge, FindEdge); }
+		}
+
+		private static bool? m_obEdgeProtocol = null;
+		public static bool EdgeProtocolSupported
+		{
+			get
+			{
+				if(m_obEdgeProtocol.HasValue)
+					return m_obEdgeProtocol.Value;
+
+				bool b = false;
+				RegistryKey rk = null;
+				try
+				{
+					rk = Registry.ClassesRoot.OpenSubKey(
+						"microsoft-edge", false);
+					if(rk != null)
+						b = (rk.GetValue("URL Protocol") != null);
+				}
+				catch(Exception) { Debug.Assert(false); }
+				finally { if(rk != null) rk.Close(); }
+
+				m_obEdgeProtocol = b;
+				return b;
+			}
+		}
+
 		private delegate string FindAppDelegate();
 
 		private static string GetPath(int iBrwID, FindAppDelegate f)
@@ -101,6 +136,7 @@ namespace KeePass.Util
 				AppLocator.ChromePath, ctx);
 			str = AppLocator.ReplacePath(str, @"{SAFARI}",
 				AppLocator.SafariPath, ctx);
+			// Edge executable cannot be run normally
 
 			return str;
 		}
@@ -346,6 +382,30 @@ namespace KeePass.Util
 			return strPath;
 		}
 
+		private static string FindEdge()
+		{
+			string strSys = Environment.SystemDirectory.TrimEnd(
+				UrlUtil.LocalDirSepChar);
+			if(strSys.EndsWith("32"))
+				strSys = strSys.Substring(0, strSys.Length - 2);
+			strSys += "Apps";
+
+			if(!Directory.Exists(strSys)) return null;
+
+			string[] vEdgeDirs = Directory.GetDirectories(strSys,
+				"Microsoft.MicrosoftEdge*", SearchOption.TopDirectoryOnly);
+			if(vEdgeDirs == null) { Debug.Assert(false); return null; }
+
+			foreach(string strEdgeDir in vEdgeDirs)
+			{
+				string strExe = UrlUtil.EnsureTerminatingSeparator(
+					strEdgeDir, false) + "MicrosoftEdge.exe";
+				if(File.Exists(strExe)) return strExe;
+			}
+
+			return null;
+		}
+
 		public static string FindAppUnix(string strApp)
 		{
 			string strArgPrefix = "-b ";
diff --git a/KeePass/Util/AutoType.cs b/KeePass/Util/AutoType.cs
index f9873d3..473fca8 100644
--- a/KeePass/Util/AutoType.cs
+++ b/KeePass/Util/AutoType.cs
@@ -77,7 +77,9 @@ namespace KeePass.Util
 		public static event EventHandler<AutoTypeEventArgs> FilterSendPre;
 		public static event EventHandler<AutoTypeEventArgs> FilterSend;
 
+		public static event EventHandler<SequenceQueryEventArgs> SequenceQueryPre;
 		public static event EventHandler<SequenceQueryEventArgs> SequenceQuery;
+		public static event EventHandler<SequenceQueryEventArgs> SequenceQueryPost;
 
 		public static event EventHandler<SequenceQueriesEventArgs> SequenceQueriesBegin;
 		public static event EventHandler<SequenceQueriesEventArgs> SequenceQueriesEnd;
@@ -246,7 +248,7 @@ namespace KeePass.Util
 				AutoType.SequenceQueriesEnd(null, e);
 		}
 
-		// Multiple calls of this method should be wrapped in
+		// Multiple calls of this method are wrapped in
 		// GetSequencesForWindowBegin and GetSequencesForWindowEnd
 		private static List<string> GetSequencesForWindow(PwEntry pwe,
 			IntPtr hWnd, string strWindow, PwDatabase pdContext, int iEventID)
@@ -261,6 +263,9 @@ namespace KeePass.Util
 			SprContext sprCtx = new SprContext(pwe, pdContext,
 				SprCompileFlags.NonActive);
 
+			RaiseSequenceQueryEvent(AutoType.SequenceQueryPre, iEventID,
+				hWnd, strWindow, pwe, pdContext, l);
+
 			// Specifically defined sequences must match before the title,
 			// in order to allow selecting the first item as default one
 			foreach(AutoTypeAssociation a in pwe.AutoType.Associations)
@@ -279,6 +284,9 @@ namespace KeePass.Util
 				}
 			}
 
+			RaiseSequenceQueryEvent(AutoType.SequenceQuery, iEventID,
+				hWnd, strWindow, pwe, pdContext, l);
+
 			if(Program.Config.Integration.AutoTypeMatchByTitle)
 			{
 				string strTitle = SprEngine.Compile(pwe.Strings.ReadSafe(
@@ -331,21 +339,31 @@ namespace KeePass.Util
 				}
 			}
 
-			if(AutoType.SequenceQuery != null)
-			{
-				SequenceQueryEventArgs e = new SequenceQueryEventArgs(iEventID,
-					hWnd, strWindow, pwe, pdContext);
-				AutoType.SequenceQuery(null, e);
-
-				foreach(string strSeq in e.Sequences)
-					AddSequence(l, strSeq);
-			}
+			RaiseSequenceQueryEvent(AutoType.SequenceQueryPost, iEventID,
+				hWnd, strWindow, pwe, pdContext, l);
 
 			return l;
 		}
 
+		private static void RaiseSequenceQueryEvent(
+			EventHandler<SequenceQueryEventArgs> f, int iEventID, IntPtr hWnd,
+			string strWindow, PwEntry pwe, PwDatabase pdContext,
+			List<string> lSeq)
+		{
+			if(f == null) return;
+
+			SequenceQueryEventArgs e = new SequenceQueryEventArgs(iEventID,
+				hWnd, strWindow, pwe, pdContext);
+			f(null, e);
+
+			foreach(string strSeq in e.Sequences)
+				AddSequence(lSeq, strSeq);
+		}
+
 		private static void AddSequence(List<string> lSeq, string strSeq)
 		{
+			if(strSeq == null) { Debug.Assert(false); return; }
+
 			string strCanSeq = CanonicalizeSeq(strSeq);
 
 			for(int i = 0; i < lSeq.Count; ++i)
diff --git a/KeePass/Util/CommandLineArgs.cs b/KeePass/Util/CommandLineArgs.cs
index bbfb81f..857494b 100644
--- a/KeePass/Util/CommandLineArgs.cs
+++ b/KeePass/Util/CommandLineArgs.cs
@@ -75,21 +75,18 @@ namespace KeePass.Util
 		}
 
 		/// <summary>
-		/// Get the value of a command-line parameter. Returns <c>null</c>
+		/// Get the value of a command line parameter. Returns <c>null</c>
 		/// if no key-value pair with the specified key exists.
 		/// </summary>
-		/// <param name="strParam">Key name.</param>
-		/// <returns>Value of the specified key or <c>null</c>.</returns>
 		public string this[string strKey]
 		{
 			get
 			{
-				if((strKey == null) || (strKey.Length == 0))
+				if(string.IsNullOrEmpty(strKey))
 					return this.FileName;
 				else
 				{
 					string strValue;
-
 					if(m_vParams.TryGetValue(strKey.ToLower(), out strValue))
 						return strValue;
 				}
diff --git a/KeePassLib/Collections/ProtectedStringDictionary.cs b/KeePassLib/Collections/ProtectedStringDictionary.cs
index 0a7ff68..1f862ea 100644
--- a/KeePassLib/Collections/ProtectedStringDictionary.cs
+++ b/KeePassLib/Collections/ProtectedStringDictionary.cs
@@ -283,11 +283,7 @@ namespace KeePassLib.Collections
 
 		public List<string> GetKeys()
 		{
-			List<string> v = new List<string>();
-
-			foreach(string strKey in m_vStrings.Keys) v.Add(strKey);
-
-			return v;
+			return new List<string>(m_vStrings.Keys);
 		}
 
 		public void EnableProtection(string strField, bool bProtect)
@@ -299,7 +295,8 @@ namespace KeePassLib.Collections
 			{
 				byte[] pbData = ps.ReadUtf8();
 				Set(strField, new ProtectedString(bProtect, pbData));
-				MemUtil.ZeroByteArray(pbData);
+
+				if(bProtect) MemUtil.ZeroByteArray(pbData);
 			}
 		}
 	}
diff --git a/KeePassLib/Cryptography/CryptoRandom.cs b/KeePassLib/Cryptography/CryptoRandom.cs
index c6a2a5f..892e1ad 100644
--- a/KeePassLib/Cryptography/CryptoRandom.cs
+++ b/KeePassLib/Cryptography/CryptoRandom.cs
@@ -31,8 +31,8 @@ using KeePassLib.Utility;
 namespace KeePassLib.Cryptography
 {
 	/// <summary>
-	/// Cryptographically strong random number generator. The returned values
-	/// are unpredictable and cannot be reproduced.
+	/// Cryptographically strong random number generator. The returned
+	/// values are unpredictable and cannot be reproduced.
 	/// <c>CryptoRandom</c> is a singleton class.
 	/// </summary>
 	public sealed class CryptoRandom
@@ -42,6 +42,7 @@ namespace KeePassLib.Cryptography
 		private RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider();
 		private ulong m_uGeneratedBytesCount = 0;
 
+		private static object g_oSyncRoot = new object();
 		private object m_oSyncRoot = new object();
 
 		private static CryptoRandom m_pInstance = null;
@@ -49,10 +50,18 @@ namespace KeePassLib.Cryptography
 		{
 			get
 			{
-				if(m_pInstance != null) return m_pInstance;
-
-				m_pInstance = new CryptoRandom();
-				return m_pInstance;
+				CryptoRandom cr;
+				lock(g_oSyncRoot)
+				{
+					cr = m_pInstance;
+					if(cr == null)
+					{
+						cr = new CryptoRandom();
+						m_pInstance = cr;
+					}
+				}
+
+				return cr;
 			}
 		}
 
diff --git a/KeePassLib/Cryptography/HmacOtp.cs b/KeePassLib/Cryptography/HmacOtp.cs
index 18223cf..2225f0a 100644
--- a/KeePassLib/Cryptography/HmacOtp.cs
+++ b/KeePassLib/Cryptography/HmacOtp.cs
@@ -40,7 +40,7 @@ namespace KeePassLib.Cryptography
 			uint uCodeDigits, bool bAddChecksum, int iTruncationOffset)
 		{
 			byte[] pbText = MemUtil.UInt64ToBytes(uFactor);
-			Array.Reverse(pbText); // Big-Endian
+			Array.Reverse(pbText); // To big-endian
 
 			HMACSHA1 hsha1 = new HMACSHA1(pbSecret);
 			byte[] pbHash = hsha1.ComputeHash(pbText);
diff --git a/KeePassLib/Keys/CompositeKey.cs b/KeePassLib/Keys/CompositeKey.cs
index 027b284..74a6284 100644
--- a/KeePassLib/Keys/CompositeKey.cs
+++ b/KeePassLib/Keys/CompositeKey.cs
@@ -161,21 +161,32 @@ namespace KeePassLib.Keys
 			ValidateUserKeys();
 
 			// Concatenate user key data
-			MemoryStream ms = new MemoryStream();
+			List<byte[]> lData = new List<byte[]>();
+			int cbData = 0;
 			foreach(IUserKey pKey in m_vUserKeys)
 			{
 				ProtectedBinary b = pKey.KeyData;
 				if(b != null)
 				{
 					byte[] pbKeyData = b.ReadData();
-					ms.Write(pbKeyData, 0, pbKeyData.Length);
-					MemUtil.ZeroByteArray(pbKeyData);
+					lData.Add(pbKeyData);
+					cbData += pbKeyData.Length;
 				}
 			}
 
+			byte[] pbAllData = new byte[cbData];
+			int p = 0;
+			foreach(byte[] pbData in lData)
+			{
+				Array.Copy(pbData, 0, pbAllData, p, pbData.Length);
+				p += pbData.Length;
+				MemUtil.ZeroByteArray(pbData);
+			}
+			Debug.Assert(p == cbData);
+
 			SHA256Managed sha256 = new SHA256Managed();
-			byte[] pbHash = sha256.ComputeHash(ms.ToArray());
-			ms.Close();
+			byte[] pbHash = sha256.ComputeHash(pbAllData);
+			MemUtil.ZeroByteArray(pbAllData);
 			return pbHash;
 		}
 
@@ -186,8 +197,8 @@ namespace KeePassLib.Keys
 			byte[] pbThis = CreateRawCompositeKey32();
 			byte[] pbOther = ckOther.CreateRawCompositeKey32();
 			bool bResult = MemUtil.ArraysEqual(pbThis, pbOther);
-			Array.Clear(pbOther, 0, pbOther.Length);
-			Array.Clear(pbThis, 0, pbThis.Length);
+			MemUtil.ZeroByteArray(pbOther);
+			MemUtil.ZeroByteArray(pbThis);
 
 			return bResult;
 		}
@@ -263,15 +274,18 @@ namespace KeePassLib.Keys
 			byte[] pbNewKey = new byte[32];
 			Array.Copy(pbOriginalKey32, pbNewKey, pbNewKey.Length);
 
-			// Try to use the native library first
-			if(NativeLib.TransformKey256(pbNewKey, pbKeySeed32, uNumRounds))
-				return (new SHA256Managed()).ComputeHash(pbNewKey);
+			try
+			{
+				// Try to use the native library first
+				if(NativeLib.TransformKey256(pbNewKey, pbKeySeed32, uNumRounds))
+					return (new SHA256Managed()).ComputeHash(pbNewKey);
 
-			if(TransformKeyManaged(pbNewKey, pbKeySeed32, uNumRounds) == false)
-				return null;
+				if(!TransformKeyManaged(pbNewKey, pbKeySeed32, uNumRounds))
+					return null;
 
-			SHA256Managed sha256 = new SHA256Managed();
-			return sha256.ComputeHash(pbNewKey);
+				return (new SHA256Managed()).ComputeHash(pbNewKey);
+			}
+			finally { MemUtil.ZeroByteArray(pbNewKey); }
 		}
 
 		public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
diff --git a/KeePassLib/Native/NativeLib.cs b/KeePassLib/Native/NativeLib.cs
index 72ae30a..c067d78 100644
--- a/KeePassLib/Native/NativeLib.cs
+++ b/KeePassLib/Native/NativeLib.cs
@@ -192,8 +192,6 @@ namespace KeePassLib.Native
 
 					if(strStdInput != null)
 					{
-						// Workaround for Mono Process StdIn BOM bug;
-						// https://sourceforge.net/p/keepass/bugs/1219/
 						EnsureNoBom(p.StandardInput);
 
 						p.StandardInput.Write(strStdInput);
@@ -258,7 +256,7 @@ namespace KeePassLib.Native
 		private static void EnsureNoBom(StreamWriter sw)
 		{
 			if(sw == null) { Debug.Assert(false); return; }
-			if(!NativeLib.IsUnix()) return;
+			if(!MonoWorkarounds.IsRequired(1219)) return;
 
 			try
 			{
@@ -267,9 +265,24 @@ namespace KeePassLib.Native
 				byte[] pbBom = enc.GetPreamble();
 				if((pbBom == null) || (pbBom.Length == 0)) return;
 
-				FieldInfo fi = typeof(StreamWriter).GetField("preamble_done",
+				// For Mono >= 4.0 (using Microsoft's reference source)
+				try
+				{
+					FieldInfo fi = typeof(StreamWriter).GetField("haveWrittenPreamble",
+						BindingFlags.Instance | BindingFlags.NonPublic);
+					if(fi != null)
+					{
+						fi.SetValue(sw, true);
+						return;
+					}
+				}
+				catch(Exception) { Debug.Assert(false); }
+
+				// For Mono < 4.0
+				FieldInfo fiPD = typeof(StreamWriter).GetField("preamble_done",
 					BindingFlags.Instance | BindingFlags.NonPublic);
-				if(fi != null) fi.SetValue(sw, true);
+				if(fiPD != null) fiPD.SetValue(sw, true);
+				else { Debug.Assert(false); }
 			}
 			catch(Exception) { Debug.Assert(false); }
 		}
diff --git a/KeePassLib/Properties/AssemblyInfo.cs b/KeePassLib/Properties/AssemblyInfo.cs
index a1bd327..b473b34 100644
--- a/KeePassLib/Properties/AssemblyInfo.cs
+++ b/KeePassLib/Properties/AssemblyInfo.cs
@@ -38,5 +38,5 @@ using System.Runtime.InteropServices;
 [assembly: Guid("395f6eec-a1e0-4438-aa82-b75099348134")]
 
 // Assembly version information
-[assembly: AssemblyVersion("2.29.0.*")]
-[assembly: AssemblyFileVersion("2.29.0.0")]
+[assembly: AssemblyVersion("2.30.0.*")]
+[assembly: AssemblyFileVersion("2.30.0.0")]
diff --git a/KeePassLib/PwDefs.cs b/KeePassLib/PwDefs.cs
index 11df805..09278e9 100644
--- a/KeePassLib/PwDefs.cs
+++ b/KeePassLib/PwDefs.cs
@@ -55,18 +55,18 @@ namespace KeePassLib
 		/// e.g. 2.19 = 0x02130000.
 		/// It is highly recommended to use <c>FileVersion64</c> instead.
 		/// </summary>
-		public const uint Version32 = 0x021D0000;
+		public const uint Version32 = 0x021E0000;
 
 		/// <summary>
 		/// Version, encoded as 64-bit unsigned integer
 		/// (component-wise, 16 bits per component).
 		/// </summary>
-		public const ulong FileVersion64 = 0x0002001D00000000UL;
+		public const ulong FileVersion64 = 0x0002001E00000000UL;
 
 		/// <summary>
 		/// Version, encoded as string.
 		/// </summary>
-		public const string VersionString = "2.29";
+		public const string VersionString = "2.30";
 
 		public const string Copyright = @"Copyright © 2003-2015 Dominik Reichl";
 
diff --git a/KeePassLib/Security/ProtectedBinary.cs b/KeePassLib/Security/ProtectedBinary.cs
index 4a8e481..2a1d85c 100644
--- a/KeePassLib/Security/ProtectedBinary.cs
+++ b/KeePassLib/Security/ProtectedBinary.cs
@@ -195,7 +195,8 @@ namespace KeePassLib.Security
 
 			byte[] pb = xbProtected.ReadPlainText();
 			Init(bEnableProtection, pb);
-			MemUtil.ZeroByteArray(pb);
+
+			if(bEnableProtection) MemUtil.ZeroByteArray(pb);
 		}
 
 		private void Init(bool bEnableProtection, byte[] pbData)
diff --git a/KeePassLib/Security/ProtectedString.cs b/KeePassLib/Security/ProtectedString.cs
index 0dcabb0..edb061e 100644
--- a/KeePassLib/Security/ProtectedString.cs
+++ b/KeePassLib/Security/ProtectedString.cs
@@ -150,7 +150,8 @@ namespace KeePassLib.Security
 
 			byte[] pb = xbProtected.ReadPlainText();
 			Init(bEnableProtection, pb);
-			MemUtil.ZeroByteArray(pb);
+
+			if(bEnableProtection) MemUtil.ZeroByteArray(pb);
 		}
 
 		private void Init(bool bEnableProtection, string str)
@@ -242,7 +243,8 @@ namespace KeePassLib.Security
 
 			byte[] pb = ReadUtf8();
 			ProtectedString ps = new ProtectedString(bProtect, pb);
-			MemUtil.ZeroByteArray(pb);
+
+			if(bProtect) MemUtil.ZeroByteArray(pb);
 			return ps;
 		}
 
diff --git a/KeePassLib/Serialization/KdbxFile.Read.Streamed.cs b/KeePassLib/Serialization/KdbxFile.Read.Streamed.cs
index c34f62b..9899e6c 100644
--- a/KeePassLib/Serialization/KdbxFile.Read.Streamed.cs
+++ b/KeePassLib/Serialization/KdbxFile.Read.Streamed.cs
@@ -807,7 +807,19 @@ namespace KeePassLib.Serialization
 				if(strRef != null)
 				{
 					ProtectedBinary pb = BinPoolGet(strRef);
-					if(pb != null) return pb;
+					if(pb != null)
+					{
+						// https://sourceforge.net/p/keepass/feature-requests/2023/
+						xr.MoveToElement();
+#if DEBUG
+						string strInner = ReadStringRaw(xr);
+						Debug.Assert(string.IsNullOrEmpty(strInner));
+#else
+						ReadStringRaw(xr);
+#endif
+
+						return pb;
+					}
 					else { Debug.Assert(false); }
 				}
 				else { Debug.Assert(false); }
diff --git a/KeePassLib/Utility/GfxUtil.cs b/KeePassLib/Utility/GfxUtil.cs
index 5a66c1e..7ed37c5 100644
--- a/KeePassLib/Utility/GfxUtil.cs
+++ b/KeePassLib/Utility/GfxUtil.cs
@@ -212,7 +212,7 @@ namespace KeePassLib.Utility
 			const int SizeICONDIRENTRY = 16;
 
 			Debug.Assert(BitConverter.ToInt32(new byte[] { 1, 2, 3, 4 },
-				0) == 0x04030201); // Little-Endian
+				0) == 0x04030201); // Little-endian
 
 			if(pb.Length < SizeICONDIR) return null;
 			if(BitConverter.ToUInt16(pb, 0) != 0) return null; // Reserved, 0
diff --git a/KeePassLib/Utility/MemUtil.cs b/KeePassLib/Utility/MemUtil.cs
index 08d5259..222ef20 100644
--- a/KeePassLib/Utility/MemUtil.cs
+++ b/KeePassLib/Utility/MemUtil.cs
@@ -21,8 +21,9 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Security.Cryptography;
-using System.Diagnostics;
 using System.IO;
+using System.Runtime.CompilerServices;
+using System.Diagnostics;
 
 #if !KeePassLibSD
 using System.IO.Compression;
@@ -247,25 +248,24 @@ namespace KeePassLib.Utility
 		/// <summary>
 		/// Set all bytes in a byte array to zero.
 		/// </summary>
-		/// <param name="pbArray">Input array. All bytes of this array will be set
-		/// to zero.</param>
+		/// <param name="pbArray">Input array. All bytes of this array
+		/// will be set to zero.</param>
+#if KeePassLibSD
+		[MethodImpl(MethodImplOptions.NoInlining)]
+#else
+		[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
+#endif
 		public static void ZeroByteArray(byte[] pbArray)
 		{
 			Debug.Assert(pbArray != null);
 			if(pbArray == null) throw new ArgumentNullException("pbArray");
 
-			// for(int i = 0; i < pbArray.Length; ++i)
-			//	pbArray[i] = 0;
-
 			Array.Clear(pbArray, 0, pbArray.Length);
 		}
 
 		/// <summary>
-		/// Convert 2 bytes to a 16-bit unsigned integer using Little-Endian
-		/// encoding.
+		/// Convert 2 bytes to a 16-bit unsigned integer (little-endian).
 		/// </summary>
-		/// <param name="pb">Input bytes. Array must contain at least 2 bytes.</param>
-		/// <returns>16-bit unsigned integer.</returns>
 		public static ushort BytesToUInt16(byte[] pb)
 		{
 			Debug.Assert((pb != null) && (pb.Length == 2));
@@ -276,44 +276,35 @@ namespace KeePassLib.Utility
 		}
 
 		/// <summary>
-		/// Convert 4 bytes to a 32-bit unsigned integer using Little-Endian
-		/// encoding.
+		/// Convert 4 bytes to a 32-bit unsigned integer (little-endian).
 		/// </summary>
-		/// <param name="pb">Input bytes.</param>
-		/// <returns>32-bit unsigned integer.</returns>
 		public static uint BytesToUInt32(byte[] pb)
 		{
 			Debug.Assert((pb != null) && (pb.Length == 4));
 			if(pb == null) throw new ArgumentNullException("pb");
-			if(pb.Length != 4) throw new ArgumentException("Input array must contain 4 bytes!");
+			if(pb.Length != 4) throw new ArgumentException();
 
-			return (uint)pb[0] | ((uint)pb[1] << 8) | ((uint)pb[2] << 16) |
-				((uint)pb[3] << 24);
+			return ((uint)pb[0] | ((uint)pb[1] << 8) | ((uint)pb[2] << 16) |
+				((uint)pb[3] << 24));
 		}
 
 		/// <summary>
-		/// Convert 8 bytes to a 64-bit unsigned integer using Little-Endian
-		/// encoding.
+		/// Convert 8 bytes to a 64-bit unsigned integer (little-endian).
 		/// </summary>
-		/// <param name="pb">Input bytes.</param>
-		/// <returns>64-bit unsigned integer.</returns>
 		public static ulong BytesToUInt64(byte[] pb)
 		{
 			Debug.Assert((pb != null) && (pb.Length == 8));
 			if(pb == null) throw new ArgumentNullException("pb");
 			if(pb.Length != 8) throw new ArgumentException();
 
-			return (ulong)pb[0] | ((ulong)pb[1] << 8) | ((ulong)pb[2] << 16) |
+			return ((ulong)pb[0] | ((ulong)pb[1] << 8) | ((ulong)pb[2] << 16) |
 				((ulong)pb[3] << 24) | ((ulong)pb[4] << 32) | ((ulong)pb[5] << 40) |
-				((ulong)pb[6] << 48) | ((ulong)pb[7] << 56);
+				((ulong)pb[6] << 48) | ((ulong)pb[7] << 56));
 		}
 
 		/// <summary>
-		/// Convert a 16-bit unsigned integer to 2 bytes using Little-Endian
-		/// encoding.
+		/// Convert a 16-bit unsigned integer to 2 bytes (little-endian).
 		/// </summary>
-		/// <param name="uValue">16-bit input word.</param>
-		/// <returns>Two bytes representing the 16-bit value.</returns>
 		public static byte[] UInt16ToBytes(ushort uValue)
 		{
 			byte[] pb = new byte[2];
@@ -328,11 +319,8 @@ namespace KeePassLib.Utility
 		}
 
 		/// <summary>
-		/// Convert a 32-bit unsigned integer to 4 bytes using Little-Endian
-		/// encoding.
+		/// Convert a 32-bit unsigned integer to 4 bytes (little-endian).
 		/// </summary>
-		/// <param name="uValue">32-bit input word.</param>
-		/// <returns>Four bytes representing the 32-bit value.</returns>
 		public static byte[] UInt32ToBytes(uint uValue)
 		{
 			byte[] pb = new byte[4];
@@ -349,11 +337,8 @@ namespace KeePassLib.Utility
 		}
 
 		/// <summary>
-		/// Convert a 64-bit unsigned integer to 8 bytes using Little-Endian
-		/// encoding.
+		/// Convert a 64-bit unsigned integer to 8 bytes (little-endian).
 		/// </summary>
-		/// <param name="uValue">64-bit input word.</param>
-		/// <returns>Eight bytes representing the 64-bit value.</returns>
 		public static byte[] UInt64ToBytes(ulong uValue)
 		{
 			byte[] pb = new byte[8];
diff --git a/KeePassLib/Utility/MessageService.cs b/KeePassLib/Utility/MessageService.cs
index 70f323f..8950114 100644
--- a/KeePassLib/Utility/MessageService.cs
+++ b/KeePassLib/Utility/MessageService.cs
@@ -356,29 +356,35 @@ namespace KeePassLib.Utility
 			return AskYesNo(strText, null, true, m_mbiQuestion);
 		}
 
-		public static void ShowLoadWarning(string strFilePath, Exception ex)
-		{
-			ShowLoadWarning(strFilePath, ex, false);
-		}
-
-		public static void ShowLoadWarning(string strFilePath, Exception ex,
-			bool bFullException)
+		internal static string GetLoadWarningMessage(string strFilePath,
+			Exception ex, bool bFullException)
 		{
 			string str = string.Empty;
 
-			if((strFilePath != null) && (strFilePath.Length > 0))
+			if(!string.IsNullOrEmpty(strFilePath))
 				str += strFilePath + MessageService.NewParagraph;
 
 			str += KLRes.FileLoadFailed;
 
-			if((ex != null) && (ex.Message != null) && (ex.Message.Length > 0))
+			if((ex != null) && !string.IsNullOrEmpty(ex.Message))
 			{
 				str += MessageService.NewParagraph;
 				if(!bFullException) str += ex.Message;
 				else str += ObjectsToMessage(new object[] { ex }, true);
 			}
 
-			ShowWarning(str);
+			return str;
+		}
+
+		public static void ShowLoadWarning(string strFilePath, Exception ex)
+		{
+			ShowLoadWarning(strFilePath, ex, false);
+		}
+
+		public static void ShowLoadWarning(string strFilePath, Exception ex,
+			bool bFullException)
+		{
+			ShowWarning(GetLoadWarningMessage(strFilePath, ex, bFullException));
 		}
 
 		public static void ShowLoadWarning(IOConnectionInfo ioConnection, Exception ex)
diff --git a/KeePassLib/Utility/MonoWorkarounds.cs b/KeePassLib/Utility/MonoWorkarounds.cs
index 87a8769..13a401d 100644
--- a/KeePassLib/Utility/MonoWorkarounds.cs
+++ b/KeePassLib/Utility/MonoWorkarounds.cs
@@ -38,12 +38,22 @@ namespace KeePassLib.Utility
 			return m_bReq.Value;
 		}
 
+		// 1219:
+		//   Mono prepends byte order mark (BOM) to StdIn.
+		//   https://sourceforge.net/p/keepass/bugs/1219/
 		// 1245:
 		//   Key events not raised while Alt is down, and nav keys out of order.
 		//   https://sourceforge.net/p/keepass/bugs/1245/
 		// 1254:
 		//   NumericUpDown bug: text is drawn below up/down buttons.
 		//   https://sourceforge.net/p/keepass/bugs/1254/
+		// 1366:
+		//   Drawing bug when scrolling a RichTextBox.
+		//   https://sourceforge.net/p/keepass/bugs/1366/
+		// 1378:
+		//   Mono doesn't implement Microsoft.Win32.SystemEvents events.
+		//   https://sourceforge.net/p/keepass/bugs/1378/
+		//   https://github.com/mono/mono/blob/master/mcs/class/System/Microsoft.Win32/SystemEvents.cs
 		// 5795:
 		//   Text in input field is incomplete.
 		//   https://bugzilla.xamarin.com/show_bug.cgi?id=5795
diff --git a/KeePassLib/Utility/StrUtil.cs b/KeePassLib/Utility/StrUtil.cs
index 9ef9671..6bbd435 100644
--- a/KeePassLib/Utility/StrUtil.cs
+++ b/KeePassLib/Utility/StrUtil.cs
@@ -356,9 +356,9 @@ namespace KeePassLib.Utility
 		}
 
 		/// <summary>
-		/// Split up a command-line into application and argument.
+		/// Split up a command line into application and argument.
 		/// </summary>
-		/// <param name="strCmdLine">Command-line to split.</param>
+		/// <param name="strCmdLine">Command line to split.</param>
 		/// <param name="strApp">Application path.</param>
 		/// <param name="strArgs">Arguments.</param>
 		public static void SplitCommandLine(string strCmdLine, out string strApp, out string strArgs)
diff --git a/KeePassLibSD/Properties/AssemblyInfo.cs b/KeePassLibSD/Properties/AssemblyInfo.cs
index ec88c91..4018825 100644
--- a/KeePassLibSD/Properties/AssemblyInfo.cs
+++ b/KeePassLibSD/Properties/AssemblyInfo.cs
@@ -38,4 +38,4 @@ using System.Runtime.InteropServices;
 [assembly: Guid("1d3c6f10-e10b-47be-a2f1-af2562d7d470")]
 
 // Assembly version information
-[assembly: AssemblyVersion("2.29.0.*")]
+[assembly: AssemblyVersion("2.30.0.*")]
diff --git a/ShInstUtil/ShInstUtil.rc b/ShInstUtil/ShInstUtil.rc
index 787d16d..9e84173 100644
--- a/ShInstUtil/ShInstUtil.rc
+++ b/ShInstUtil/ShInstUtil.rc
@@ -65,8 +65,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,29,0,0
- PRODUCTVERSION 2,29,0,0
+ FILEVERSION 2,30,0,0
+ PRODUCTVERSION 2,30,0,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -83,12 +83,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "Dominik Reichl"
             VALUE "FileDescription", "ShInstUtil - KeePass Helper Utility"
-            VALUE "FileVersion", "2.29.0.0"
+            VALUE "FileVersion", "2.30.0.0"
             VALUE "InternalName", "ShInstUtil"
             VALUE "LegalCopyright", "Copyright (c) 2007-2015 Dominik Reichl"
             VALUE "OriginalFilename", "ShInstUtil.exe"
             VALUE "ProductName", "ShInstUtil - KeePass Helper Utility"
-            VALUE "ProductVersion", "2.29.0.0"
+            VALUE "ProductVersion", "2.30.0.0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/Translation/DefaultText.xml b/Translation/DefaultText.xml
index 9b136be..413ed09 100644
--- a/Translation/DefaultText.xml
+++ b/Translation/DefaultText.xml
@@ -439,6 +439,9 @@
 		<Data Name="CredSaveUserOnly">
 			<Value>Remember user name only</Value>
 		</Data>
+		<Data Name="CredSpecifyDifferent">
+			<Value>&Specify different server credentials</Value>
+		</Data>
 		<Data Name="CsprojCountError">
 			<Value>There must be exactly one .csproj or .vbproj file.</Value>
 		</Data>
@@ -1981,6 +1984,9 @@
 		<Data Name="UnknownError">
 			<Value>An unknown error occurred.</Value>
 		</Data>
+		<Data Name="UnsupportedByMono">
+			<Value>unsupported by Mono</Value>
+		</Data>
 		<Data Name="UpdateCheck">
 			<Value>Update Check</Value>
 		</Data>
diff --git a/Translation/TrlUtil/Properties/AssemblyInfo.cs b/Translation/TrlUtil/Properties/AssemblyInfo.cs
index f669bb5..d1a303e 100644
--- a/Translation/TrlUtil/Properties/AssemblyInfo.cs
+++ b/Translation/TrlUtil/Properties/AssemblyInfo.cs
@@ -38,5 +38,5 @@ using System.Runtime.InteropServices;
 [assembly: Guid("39aa6f93-a1c9-497f-bad2-cc42a61d5710")]
 
 // Assembly version information
-[assembly: AssemblyVersion("2.29.0.*")]
-[assembly: AssemblyFileVersion("2.29.0.0")]
+[assembly: AssemblyVersion("2.30.0.*")]
+[assembly: AssemblyFileVersion("2.30.0.0")]

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-cli-apps/packages/keepass2.git



More information about the Pkg-cli-apps-commits mailing list