From f324f0dd45e5b4ac8ee3164af254c2690c7aff1f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 19 Mar 2026 22:38:52 +0000
Subject: [PATCH 1/5] Initial plan
From deacb4c0a5d9008a120b64601540947e1b539a0a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 19 Mar 2026 22:54:16 +0000
Subject: [PATCH 2/5] Add IEncryptionProvider interface and TLS/Legacy
encryption support
- Create IEncryptionProvider interface abstracting the security layer
- Create TlsEncryptionProvider wrapping existing OpenSSL/TLS behavior (default)
- Create LegacyEncryptionProvider using HarpoS7 for older firmware
- Add HarpoS7 as git submodule for legacy encryption support
- Add new Connect() overload accepting IEncryptionProvider parameter
- Update S7CommPlusConnection to use provider for InitSSL, channel activation, security overhead, and legitimation secrets
- Backward compatible: existing Connect(address, password, ...) uses TLS by default
Co-authored-by: jogibear9988 <364896+jogibear9988@users.noreply.github.com>
---
.gitmodules | 3 +
libs/HarpoS7 | 1 +
.../Encryption/IEncryptionProvider.cs | 65 +++++
.../Encryption/LegacyEncryptionProvider.cs | 235 ++++++++++++++++++
.../Encryption/TlsEncryptionProvider.cs | 59 +++++
.../Legitimation/Legitimation.cs | 7 +-
src/S7CommPlusDriver/S7CommPlusConnection.cs | 85 +++++--
src/S7CommPlusDriver/S7CommPlusDriver.csproj | 5 +
8 files changed, 430 insertions(+), 30 deletions(-)
create mode 100644 .gitmodules
create mode 160000 libs/HarpoS7
create mode 100644 src/S7CommPlusDriver/Encryption/IEncryptionProvider.cs
create mode 100644 src/S7CommPlusDriver/Encryption/LegacyEncryptionProvider.cs
create mode 100644 src/S7CommPlusDriver/Encryption/TlsEncryptionProvider.cs
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..186ecea
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "libs/HarpoS7"]
+ path = libs/HarpoS7
+ url = https://github.com/bonk-dev/HarpoS7.git
diff --git a/libs/HarpoS7 b/libs/HarpoS7
new file mode 160000
index 0000000..af9e165
--- /dev/null
+++ b/libs/HarpoS7
@@ -0,0 +1 @@
+Subproject commit af9e165a25a1c74b725971ac8c7ec7427732c891
diff --git a/src/S7CommPlusDriver/Encryption/IEncryptionProvider.cs b/src/S7CommPlusDriver/Encryption/IEncryptionProvider.cs
new file mode 100644
index 0000000..6803954
--- /dev/null
+++ b/src/S7CommPlusDriver/Encryption/IEncryptionProvider.cs
@@ -0,0 +1,65 @@
+#region License
+/******************************************************************************
+ * S7CommPlusDriver
+ *
+ * Copyright (C) 2023 Thomas Wiens, th.wiens@gmx.de
+ *
+ * This file is part of S7CommPlusDriver.
+ *
+ * S7CommPlusDriver is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ /****************************************************************************/
+#endregion
+
+namespace S7CommPlusDriver.Encryption
+{
+ ///
+ /// Abstraction for the security/encryption layer used during S7CommPlus communication.
+ /// Two implementations exist:
+ /// - TlsEncryptionProvider: For newer PLC firmware using TLS 1.3 (OpenSSL)
+ /// - LegacyEncryptionProvider: For older PLC firmware using Siemens proprietary encryption (HarpoS7)
+ ///
+ public interface IEncryptionProvider
+ {
+ ///
+ /// Whether the InitSSL request/response protocol step is needed before activation.
+ /// TLS requires the InitSSL handshake; legacy encryption does not.
+ ///
+ bool RequiresInitSsl { get; }
+
+ ///
+ /// Activate the security channel on the given S7Client.
+ /// For TLS: Initializes OpenSSL and performs the TLS 1.3 handshake.
+ /// For Legacy: No-op at this stage (authentication happens later during CreateObject processing).
+ ///
+ /// The S7Client to activate encryption on
+ /// 0 on success, error code on failure
+ int ActivateChannel(S7Client client);
+
+ ///
+ /// Deactivate the security channel and release resources.
+ /// For TLS: Deactivates TLS on the S7Client.
+ /// For Legacy: Clears session key material.
+ ///
+ /// The S7Client to deactivate encryption on
+ void DeactivateChannel(S7Client client);
+
+ ///
+ /// Get the secret used for password legitimation.
+ /// For TLS: Returns the OMS exporter secret from SSL_export_keying_material.
+ /// For Legacy: Returns null (legacy legitimation uses a different mechanism).
+ ///
+ /// The S7Client to get the secret from
+ /// The secret bytes, or null if not applicable
+ byte[] GetSecretForLegitimation(S7Client client);
+
+ ///
+ /// Additional overhead per PDU from the security layer, used for fragmentation calculation.
+ /// For TLS: 22 bytes (5 byte TLS header + 17 byte GCM authentication tag).
+ /// For Legacy: 0 bytes (no TLS encryption overhead).
+ ///
+ int SecurityOverheadPerPdu { get; }
+ }
+}
diff --git a/src/S7CommPlusDriver/Encryption/LegacyEncryptionProvider.cs b/src/S7CommPlusDriver/Encryption/LegacyEncryptionProvider.cs
new file mode 100644
index 0000000..5e84cfe
--- /dev/null
+++ b/src/S7CommPlusDriver/Encryption/LegacyEncryptionProvider.cs
@@ -0,0 +1,235 @@
+#region License
+/******************************************************************************
+ * S7CommPlusDriver
+ *
+ * Copyright (C) 2023 Thomas Wiens, th.wiens@gmx.de
+ *
+ * This file is part of S7CommPlusDriver.
+ *
+ * S7CommPlusDriver is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ /****************************************************************************/
+#endregion
+
+#if !NET6_0
+
+using System;
+using System.Text;
+using HarpoS7;
+using HarpoS7.Auth;
+using HarpoS7.Keys;
+using HarpoS7.PublicKeys.Impl;
+using HarpoS7.Utilities.Auth;
+using HarpoS7.Utilities.Extensions;
+using HarpoS7.Extensions;
+
+namespace S7CommPlusDriver.Encryption
+{
+ ///
+ /// Legacy encryption provider for older PLC firmware that uses Siemens proprietary
+ /// challenge-based authentication (pre-TLS, implemented by HarpoS7).
+ ///
+ /// With legacy encryption:
+ /// - No TLS/SSL is used for data encryption
+ /// - Authentication is done via challenge-response using HarpoS7
+ /// - Each packet includes an HMAC-SHA256 integrity digest
+ /// - The session key is derived from the authentication handshake
+ ///
+ public class LegacyEncryptionProvider : IEncryptionProvider
+ {
+ private byte[] m_sessionKey;
+ private byte[] m_publicKey;
+ private EPublicKeyFamily m_publicKeyFamily;
+ private bool m_authenticated;
+
+ ///
+ /// Legacy encryption does not use the InitSSL protocol step.
+ ///
+ public bool RequiresInitSsl => false;
+
+ ///
+ /// No TLS overhead with legacy encryption. Data is sent unencrypted with integrity digests.
+ ///
+ public int SecurityOverheadPerPdu => 0;
+
+ ///
+ /// The session key derived from the HarpoS7 authentication handshake.
+ /// Available after completes successfully.
+ ///
+ public byte[] SessionKey => m_sessionKey;
+
+ ///
+ /// Whether legacy authentication has been completed successfully.
+ ///
+ public bool IsAuthenticated => m_authenticated;
+
+ ///
+ /// The public key family determined from the PLC fingerprint.
+ ///
+ public EPublicKeyFamily PublicKeyFamily => m_publicKeyFamily;
+
+ ///
+ /// No-op for legacy encryption. The security channel is established
+ /// during the CreateObject response processing via .
+ ///
+ public int ActivateChannel(S7Client client)
+ {
+ // Legacy encryption doesn't activate TLS - authentication happens later
+ return 0;
+ }
+
+ ///
+ /// Clears session key material.
+ ///
+ public void DeactivateChannel(S7Client client)
+ {
+ if (m_sessionKey != null)
+ {
+ Array.Clear(m_sessionKey, 0, m_sessionKey.Length);
+ m_sessionKey = null;
+ }
+ m_authenticated = false;
+ }
+
+ ///
+ /// Returns null for legacy encryption. Legacy legitimation uses the HarpoS7
+ /// directly with the session key.
+ ///
+ public byte[] GetSecretForLegitimation(S7Client client)
+ {
+ return null;
+ }
+
+ ///
+ /// Processes the challenge received from the PLC during the CreateObject response.
+ /// Performs the HarpoS7 authentication and produces the encrypted key blob
+ /// and session key.
+ ///
+ /// The 20-byte challenge received from the PLC
+ /// The public key fingerprint string from the PLC (e.g., "00:181B7B0847D11694")
+ /// Output: The encrypted key blob to send back to the PLC
+ /// 0 on success, error code on failure
+ public int ProcessChallengeResponse(byte[] challenge, string fingerprint, out byte[] keyBlob)
+ {
+ keyBlob = null;
+
+ try
+ {
+ // Determine public key family from fingerprint
+ m_publicKeyFamily = fingerprint.ToPublicKeyFamily();
+
+ // Look up the public key from the default key store
+ var store = new DefaultPublicKeyStore();
+ m_publicKey = new byte[store.GetPublicKeyLength(fingerprint)];
+ store.ReadPublicKey(m_publicKey.AsSpan(), fingerprint);
+
+ // Determine blob length based on family
+ int blobLength = (m_publicKeyFamily == EPublicKeyFamily.PlcSim)
+ ? CommonConstants.EncryptedBlobLengthPlcSim
+ : CommonConstants.EncryptedBlobLengthRealPlc;
+
+ keyBlob = new byte[blobLength];
+ m_sessionKey = new byte[Constants.SessionKeyLength];
+
+ // Perform HarpoS7 authentication
+ LegacyAuthenticationScheme.Authenticate(
+ keyBlob.AsSpan(),
+ m_sessionKey.AsSpan(),
+ challenge.AsSpan(),
+ m_publicKey.AsSpan(),
+ m_publicKeyFamily);
+
+ m_authenticated = true;
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("LegacyEncryptionProvider - ProcessChallengeResponse: Error: " + ex.Message);
+ return S7Consts.errCliAccessDenied;
+ }
+ }
+
+ ///
+ /// Derives the key ID from the public key for the SetMultiVariables authentication request.
+ ///
+ /// 8-byte public key ID
+ public byte[] GetPublicKeyId()
+ {
+ if (m_publicKey == null) return null;
+ var pubKeyId = new byte[Constants.KeyIdLength];
+ m_publicKey.DeriveKeyId(pubKeyId);
+ return pubKeyId;
+ }
+
+ ///
+ /// Derives the key ID from the session key for the SetMultiVariables authentication request.
+ ///
+ /// 8-byte session key ID
+ public byte[] GetSessionKeyId()
+ {
+ if (m_sessionKey == null) return null;
+ var sessionKeyId = new byte[Constants.KeyIdLength];
+ m_sessionKey.DeriveKeyId(sessionKeyId);
+ return sessionKeyId;
+ }
+
+ ///
+ /// Calculates the HMAC-SHA256 packet integrity digest for a given packet payload.
+ /// This must be included with every packet in legacy authentication mode.
+ ///
+ /// The S7CommPlus packet data (without header/trailer)
+ /// 32-byte HMAC-SHA256 digest
+ public byte[] CalculatePacketDigest(byte[] packetData)
+ {
+ if (m_sessionKey == null)
+ throw new InvalidOperationException("Session key not available. Authenticate first.");
+
+ var digest = new byte[HarpoS7.Integrity.HarpoPacketDigest.DigestLength];
+ HarpoS7.Integrity.HarpoPacketDigest.CalculateDigest(
+ digest.AsSpan(),
+ packetData.AsSpan(),
+ m_sessionKey.AsSpan());
+ return digest;
+ }
+
+ ///
+ /// Solves the legitimation challenge for password-protected PLCs in legacy mode.
+ ///
+ /// The legitimation challenge from the PLC (20 bytes)
+ /// The access password
+ /// The solved legitimation blob to send back to the PLC
+ public byte[] SolveLegitimationChallenge(byte[] challenge, string password)
+ {
+ if (m_sessionKey == null || m_publicKey == null)
+ throw new InvalidOperationException("Session not authenticated. Call ProcessChallengeResponse first.");
+
+ if (m_publicKeyFamily == EPublicKeyFamily.PlcSim)
+ {
+ var blobData = new byte[CommonConstants.EncryptedLegitimationBlobLengthPlcSim];
+ LegitimateScheme.SolveLegitimateChallengePlcSim(
+ blobData.AsSpan(),
+ challenge.AsSpan(),
+ m_publicKey.AsSpan(),
+ m_sessionKey.AsSpan(),
+ password);
+ return blobData;
+ }
+ else
+ {
+ var blobData = new byte[CommonConstants.EncryptedLegitimationBlobLengthRealPlc];
+ LegitimateScheme.SolveLegitimateChallengeRealPlc(
+ blobData.AsSpan(),
+ challenge.AsSpan(),
+ m_publicKey.AsSpan(),
+ m_publicKeyFamily,
+ m_sessionKey.AsSpan(),
+ password);
+ return blobData;
+ }
+ }
+ }
+}
+
+#endif
diff --git a/src/S7CommPlusDriver/Encryption/TlsEncryptionProvider.cs b/src/S7CommPlusDriver/Encryption/TlsEncryptionProvider.cs
new file mode 100644
index 0000000..9dfb057
--- /dev/null
+++ b/src/S7CommPlusDriver/Encryption/TlsEncryptionProvider.cs
@@ -0,0 +1,59 @@
+#region License
+/******************************************************************************
+ * S7CommPlusDriver
+ *
+ * Copyright (C) 2023 Thomas Wiens, th.wiens@gmx.de
+ *
+ * This file is part of S7CommPlusDriver.
+ *
+ * S7CommPlusDriver is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ /****************************************************************************/
+#endregion
+
+namespace S7CommPlusDriver.Encryption
+{
+ ///
+ /// TLS 1.3 encryption provider for newer PLC firmware.
+ /// This wraps the existing OpenSSL/TLS behavior and is the default provider.
+ ///
+ public class TlsEncryptionProvider : IEncryptionProvider
+ {
+ ///
+ /// TLS requires the InitSSL request/response handshake step.
+ ///
+ public bool RequiresInitSsl => true;
+
+ ///
+ /// TLS overhead per PDU: 5 byte TLS header + 17 byte GCM authentication tag.
+ ///
+ public int SecurityOverheadPerPdu => 5 + 17;
+
+ ///
+ /// Activates TLS 1.3 on the S7Client via OpenSSL.
+ ///
+ public int ActivateChannel(S7Client client)
+ {
+ return client.SslActivate();
+ }
+
+ ///
+ /// Deactivates TLS on the S7Client.
+ ///
+ public void DeactivateChannel(S7Client client)
+ {
+ client.SslDeactivate();
+ }
+
+ ///
+ /// Returns the OMS exporter secret derived from TLS key material export.
+ /// This is used for password legitimation on newer firmware.
+ ///
+ public byte[] GetSecretForLegitimation(S7Client client)
+ {
+ return client.getOMSExporterSecret();
+ }
+ }
+}
diff --git a/src/S7CommPlusDriver/Legitimation/Legitimation.cs b/src/S7CommPlusDriver/Legitimation/Legitimation.cs
index 41e97c7..b02869b 100644
--- a/src/S7CommPlusDriver/Legitimation/Legitimation.cs
+++ b/src/S7CommPlusDriver/Legitimation/Legitimation.cs
@@ -1,4 +1,5 @@
-using S7CommPlusDriver.Legitimation;
+using S7CommPlusDriver.Encryption;
+using S7CommPlusDriver.Legitimation;
using System;
using System.Collections.Generic;
using System.IO;
@@ -160,8 +161,8 @@ private int legitimateNew(string password, string username = "")
byte[] challengeResponse;
if (omsSecret == null || omsSecret.Length != 32)
{
- // Create oms exporter secret
- omsSecret = m_client.getOMSExporterSecret();
+ // Get secret from encryption provider
+ omsSecret = m_encryptionProvider.GetSecretForLegitimation(m_client);
}
// Roll key
byte[] key = LegitimationCrypto.sha256(omsSecret);
diff --git a/src/S7CommPlusDriver/S7CommPlusConnection.cs b/src/S7CommPlusDriver/S7CommPlusConnection.cs
index 25737f8..015c7f2 100644
--- a/src/S7CommPlusDriver/S7CommPlusConnection.cs
+++ b/src/S7CommPlusDriver/S7CommPlusConnection.cs
@@ -21,6 +21,7 @@
using System.Linq;
using System.Diagnostics;
using S7CommPlusDriver.ClientApi;
+using S7CommPlusDriver.Encryption;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
@@ -30,6 +31,7 @@ public partial class S7CommPlusConnection
{
#region Private Members
private S7Client m_client;
+ private IEncryptionProvider m_encryptionProvider;
private MemoryStream m_ReceivedPDU;
private MemoryStream m_ReceivedTempPDU;
private Queue m_ReceivedPDUs = new Queue();
@@ -58,6 +60,12 @@ public UInt32 SessionId2
#region Public Members
public int m_LastError = 0;
+ ///
+ /// Gets the current encryption provider used by this connection.
+ /// Can be used to access provider-specific functionality (e.g., LegacyEncryptionProvider's session key).
+ ///
+ public IEncryptionProvider EncryptionProvider => m_encryptionProvider;
+
#endregion
#region Private Methods
@@ -183,10 +191,11 @@ private int SendS7plusPDUdata(byte[] sendPduData, int bytesToSend, byte protoVer
// 4 Byte TPKT Header
// 3 Byte ISO-Header
- // 5 Byte TLS Header + 17 Bytes addition from TLS
+ // Security overhead from encryption provider (TLS: 5+17, Legacy: 0)
// 4 Byte S7CommPlus Header
// 4 Byte S7CommPlus Trailer (must fit into last PDU)
- int MaxSize = NegotiatedIsoPduSize - 4 - 3 - 5 - 17 - 4 - 4;
+ int securityOverhead = m_encryptionProvider != null ? m_encryptionProvider.SecurityOverheadPerPdu : 5 + 17;
+ int MaxSize = NegotiatedIsoPduSize - 4 - 3 - securityOverhead - 4 - 4;
byte[] packet = new byte[MaxSize + 4]; //max packet size is always MaxSize + PDU Header
while (bytesToSend > 0)
@@ -384,18 +393,36 @@ private int checkResponseWithIntegrity(IS7pRequest request, IS7pResponse respons
#region Public Methods
///
- /// Establishes a connection to the PLC.
+ /// Establishes a connection to the PLC using TLS encryption (default, for newer firmware).
///
/// PLC IP address
/// PLC password (if set)
+ /// PLC username (leave empty for legacy login)
/// read timeout in milliseconds (default: 5000 ms)
- ///
+ /// 0 on success, error code on failure
public int Connect(string address, string password = "", string username = "", int timeoutMs = 5000)
+ {
+ return Connect(address, new TlsEncryptionProvider(), password, username, timeoutMs);
+ }
+
+ ///
+ /// Establishes a connection to the PLC using the specified encryption provider.
+ /// Use for newer firmware (TLS 1.3) or
+ /// (net8.0+) for older firmware (HarpoS7 challenge-based auth).
+ ///
+ /// PLC IP address
+ /// The encryption provider to use
+ /// PLC password (if set)
+ /// PLC username (leave empty for legacy login)
+ /// read timeout in milliseconds (default: 5000 ms)
+ /// 0 on success, error code on failure
+ public int Connect(string address, IEncryptionProvider encryptionProvider, string password = "", string username = "", int timeoutMs = 5000)
{
if (timeoutMs > 0) {
m_ReadTimeout = timeoutMs;
}
+ m_encryptionProvider = encryptionProvider;
m_LastError = 0;
int res;
int Elapsed = Environment.TickCount;
@@ -407,35 +434,38 @@ public int Connect(string address, string password = "", string username = "", i
if (res != 0)
return res;
- #region Step 1: Unencrypted InitSSL Request / Response
+ #region Step 1: InitSSL Request / Response (only for TLS)
- InitSslRequest sslReq = new InitSslRequest(ProtocolVersion.V1, 0 , 0);
- res = SendS7plusFunctionObject(sslReq);
- if (res != 0)
- {
- m_client.Disconnect();
- return res;
- }
- m_LastError = 0;
- WaitForNewS7plusReceived(m_ReadTimeout);
- if (m_LastError != 0)
- {
- m_client.Disconnect();
- return m_LastError;
- }
- InitSslResponse sslRes;
- sslRes = InitSslResponse.DeserializeFromPdu(m_ReceivedPDU);
- if (sslRes == null)
+ if (m_encryptionProvider.RequiresInitSsl)
{
- m_client.Disconnect();
- return S7Consts.errInitSslResponse;
+ InitSslRequest sslReq = new InitSslRequest(ProtocolVersion.V1, 0 , 0);
+ res = SendS7plusFunctionObject(sslReq);
+ if (res != 0)
+ {
+ m_client.Disconnect();
+ return res;
+ }
+ m_LastError = 0;
+ WaitForNewS7plusReceived(m_ReadTimeout);
+ if (m_LastError != 0)
+ {
+ m_client.Disconnect();
+ return m_LastError;
+ }
+ InitSslResponse sslRes;
+ sslRes = InitSslResponse.DeserializeFromPdu(m_ReceivedPDU);
+ if (sslRes == null)
+ {
+ m_client.Disconnect();
+ return S7Consts.errInitSslResponse;
+ }
}
#endregion
- #region Step 2: Activate TLS. Everything from here onwards is TLS encrypted.
+ #region Step 2: Activate encryption channel
- res = m_client.SslActivate();
+ res = m_encryptionProvider.ActivateChannel(m_client);
if (res != 0)
{
m_client.Disconnect();
@@ -444,7 +474,7 @@ public int Connect(string address, string password = "", string username = "", i
#endregion
- #region Step 3: CreateObjectRequest / Response (with TLS)
+ #region Step 3: CreateObjectRequest / Response
var createObjReq = new CreateObjectRequest(ProtocolVersion.V1, 0, false);
createObjReq.SetNullServerSessionData();
@@ -534,6 +564,7 @@ public int Connect(string address, string password = "", string username = "", i
public void Disconnect()
{
DeleteObject(m_SessionId);
+ m_encryptionProvider?.DeactivateChannel(m_client);
m_client.Disconnect();
}
diff --git a/src/S7CommPlusDriver/S7CommPlusDriver.csproj b/src/S7CommPlusDriver/S7CommPlusDriver.csproj
index 64a7c26..cf043ff 100644
--- a/src/S7CommPlusDriver/S7CommPlusDriver.csproj
+++ b/src/S7CommPlusDriver/S7CommPlusDriver.csproj
@@ -11,6 +11,11 @@
+
+
+
+
+
PreserveNewest
From 91eaceefa83e802191facb8d072d7743106d9a68 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 19 Mar 2026 22:56:11 +0000
Subject: [PATCH 3/5] Address code review feedback: clarify param docs
Co-authored-by: jogibear9988 <364896+jogibear9988@users.noreply.github.com>
---
src/S7CommPlusDriver/S7CommPlusConnection.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/S7CommPlusDriver/S7CommPlusConnection.cs b/src/S7CommPlusDriver/S7CommPlusConnection.cs
index 015c7f2..84114d0 100644
--- a/src/S7CommPlusDriver/S7CommPlusConnection.cs
+++ b/src/S7CommPlusDriver/S7CommPlusConnection.cs
@@ -397,7 +397,7 @@ private int checkResponseWithIntegrity(IS7pRequest request, IS7pResponse respons
///
/// PLC IP address
/// PLC password (if set)
- /// PLC username (leave empty for legacy login)
+ /// PLC username (leave empty for password-only authentication)
/// read timeout in milliseconds (default: 5000 ms)
/// 0 on success, error code on failure
public int Connect(string address, string password = "", string username = "", int timeoutMs = 5000)
@@ -413,7 +413,7 @@ public int Connect(string address, string password = "", string username = "", i
/// PLC IP address
/// The encryption provider to use
/// PLC password (if set)
- /// PLC username (leave empty for legacy login)
+ /// PLC username (leave empty for password-only authentication)
/// read timeout in milliseconds (default: 5000 ms)
/// 0 on success, error code on failure
public int Connect(string address, IEncryptionProvider encryptionProvider, string password = "", string username = "", int timeoutMs = 5000)
From 2a69c47cec078956b505557348831c20a6900136 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 19 Mar 2026 23:02:01 +0000
Subject: [PATCH 4/5] Update DriverTest and GUIBrowser to support both TLS and
Legacy encryption
- DriverTest: Add 4th command-line arg for encryption mode ("tls" or "legacy")
- GUIBrowser: Add Encryption dropdown to Connection group box
- Both projects use IEncryptionProvider to select TLS or Legacy mode
Co-authored-by: jogibear9988 <364896+jogibear9988@users.noreply.github.com>
---
src/DriverTest/Program.cs | 25 +++++++++++++++++-
src/S7CommPlusGUIBrowser/Form1.Designer.cs | 30 +++++++++++++++++++---
src/S7CommPlusGUIBrowser/Form1.cs | 26 ++++++++++++++++++-
3 files changed, 76 insertions(+), 5 deletions(-)
diff --git a/src/DriverTest/Program.cs b/src/DriverTest/Program.cs
index aea7ba1..79f5ac3 100644
--- a/src/DriverTest/Program.cs
+++ b/src/DriverTest/Program.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using S7CommPlusDriver;
+using S7CommPlusDriver.Encryption;
using S7CommPlusDriver.ClientApi;
@@ -17,6 +18,7 @@ static void Main(string[] args)
string HostIp = "10.0.98.100";
string Password = "";
string Username = "";
+ string EncryptionMode = "tls";
int res;
List readlist = new List();
Console.WriteLine("Main - START");
@@ -35,10 +37,31 @@ static void Main(string[] args)
{
Username = args[2];
}
+ // Als Parameter lässt sich der Verschlüsselungsmodus übergeben: "tls" (default) oder "legacy"
+ if (args.Length >= 4)
+ {
+ EncryptionMode = args[3].ToLowerInvariant();
+ }
Console.WriteLine("Main - Versuche Verbindungsaufbau zu: " + HostIp);
+ Console.WriteLine("Main - Encryption mode: " + EncryptionMode);
+
+ IEncryptionProvider encryptionProvider;
+ if (EncryptionMode == "legacy")
+ {
+#if NET6_0
+ Console.WriteLine("Main - ERROR: Legacy encryption is not supported on net6.0. Use net8.0 or newer.");
+ return;
+#else
+ encryptionProvider = new LegacyEncryptionProvider();
+#endif
+ }
+ else
+ {
+ encryptionProvider = new TlsEncryptionProvider();
+ }
S7CommPlusConnection conn = new S7CommPlusConnection();
- res = conn.Connect(HostIp, Password, Username);
+ res = conn.Connect(HostIp, encryptionProvider, Password, Username);
if (res == 0)
{
Console.WriteLine("Main - Connect fertig");
diff --git a/src/S7CommPlusGUIBrowser/Form1.Designer.cs b/src/S7CommPlusGUIBrowser/Form1.Designer.cs
index 9cb52ab..0f8fa9f 100644
--- a/src/S7CommPlusGUIBrowser/Form1.Designer.cs
+++ b/src/S7CommPlusGUIBrowser/Form1.Designer.cs
@@ -26,6 +26,8 @@ private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.cbEncryption = new System.Windows.Forms.ComboBox();
+ this.labelEncryption = new System.Windows.Forms.Label();
this.tbUser = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.lbStatus = new System.Windows.Forms.Label();
@@ -52,6 +54,8 @@ private void InitializeComponent() {
//
// groupBox1
//
+ this.groupBox1.Controls.Add(this.cbEncryption);
+ this.groupBox1.Controls.Add(this.labelEncryption);
this.groupBox1.Controls.Add(this.tbUser);
this.groupBox1.Controls.Add(this.label7);
this.groupBox1.Controls.Add(this.btnDisconnect);
@@ -62,11 +66,29 @@ private void InitializeComponent() {
this.groupBox1.Controls.Add(this.tbIpAddress);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
- this.groupBox1.Size = new System.Drawing.Size(171, 165);
+ this.groupBox1.Size = new System.Drawing.Size(171, 205);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Connection";
//
+ // cbEncryption
+ //
+ this.cbEncryption.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cbEncryption.FormattingEnabled = true;
+ this.cbEncryption.Location = new System.Drawing.Point(9, 149);
+ this.cbEncryption.Name = "cbEncryption";
+ this.cbEncryption.Size = new System.Drawing.Size(151, 21);
+ this.cbEncryption.TabIndex = 10;
+ //
+ // labelEncryption
+ //
+ this.labelEncryption.AutoSize = true;
+ this.labelEncryption.Location = new System.Drawing.Point(6, 133);
+ this.labelEncryption.Name = "labelEncryption";
+ this.labelEncryption.Size = new System.Drawing.Size(60, 13);
+ this.labelEncryption.TabIndex = 9;
+ this.labelEncryption.Text = "Encryption:";
+ //
// tbUser
//
this.tbUser.Location = new System.Drawing.Point(9, 71);
@@ -103,7 +125,7 @@ private void InitializeComponent() {
//
// btnDisconnect
//
- this.btnDisconnect.Location = new System.Drawing.Point(85, 136);
+ this.btnDisconnect.Location = new System.Drawing.Point(85, 176);
this.btnDisconnect.Name = "btnDisconnect";
this.btnDisconnect.Size = new System.Drawing.Size(75, 23);
this.btnDisconnect.TabIndex = 4;
@@ -113,7 +135,7 @@ private void InitializeComponent() {
//
// btnConnect
//
- this.btnConnect.Location = new System.Drawing.Point(9, 136);
+ this.btnConnect.Location = new System.Drawing.Point(9, 176);
this.btnConnect.Name = "btnConnect";
this.btnConnect.Size = new System.Drawing.Size(75, 23);
this.btnConnect.TabIndex = 3;
@@ -340,6 +362,8 @@ private void InitializeComponent() {
private System.Windows.Forms.ImageList imageListTreeIcons;
private System.Windows.Forms.TextBox tbUser;
private System.Windows.Forms.Label label7;
+ private System.Windows.Forms.ComboBox cbEncryption;
+ private System.Windows.Forms.Label labelEncryption;
}
}
diff --git a/src/S7CommPlusGUIBrowser/Form1.cs b/src/S7CommPlusGUIBrowser/Form1.cs
index 42e5539..a1b3e6e 100644
--- a/src/S7CommPlusGUIBrowser/Form1.cs
+++ b/src/S7CommPlusGUIBrowser/Form1.cs
@@ -1,5 +1,6 @@
using S7CommPlusDriver;
using S7CommPlusDriver.ClientApi;
+using S7CommPlusDriver.Encryption;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -17,6 +18,11 @@ public Form1()
{
InitializeComponent();
+ // Initialize encryption mode combo box
+ cbEncryption.Items.Add("TLS (new firmware)");
+ cbEncryption.Items.Add("Legacy (old firmware)");
+ cbEncryption.SelectedIndex = 0;
+
string[] args = Environment.GetCommandLineArgs();
// 1st argument can be the plc ip-address, otherwise use default
if (args.Length >= 2)
@@ -33,6 +39,14 @@ public Form1()
{
tbUser.Text = args[3];
}
+ // 4th argument can be the encryption mode: "tls" (default) or "legacy"
+ if (args.Length >= 5)
+ {
+ if (args[4].ToLowerInvariant() == "legacy")
+ {
+ cbEncryption.SelectedIndex = 1;
+ }
+ }
}
private void setStatus(string status)
@@ -45,9 +59,19 @@ private void btnConnect_Click(object sender, EventArgs e)
{
setStatus("connecting...");
+ IEncryptionProvider encryptionProvider;
+ if (cbEncryption.SelectedIndex == 1)
+ {
+ encryptionProvider = new LegacyEncryptionProvider();
+ }
+ else
+ {
+ encryptionProvider = new TlsEncryptionProvider();
+ }
+
if (conn != null) conn.Disconnect();
conn = new S7CommPlusConnection();
- int res = conn.Connect(tbIpAddress.Text, tbPassword.Text, tbUser.Text);
+ int res = conn.Connect(tbIpAddress.Text, encryptionProvider, tbPassword.Text, tbUser.Text);
if (res != 0)
{
setStatus("error: " + S7Client.ErrorText(res));
From dbecda1a66a87c8697283f0c142363a9f4fb51ea Mon Sep 17 00:00:00 2001
From: jkuehner
Date: Fri, 20 Mar 2026 00:31:32 +0100
Subject: [PATCH 5/5] fix test tool and solution
---
src/S7CommPlusDriver.slnx | 5 +
src/S7CommPlusGUIBrowser/Form1.Designer.cs | 648 +++++++++++----------
src/S7CommPlusGUIBrowser/Form1.resx | 624 ++++++++++----------
3 files changed, 651 insertions(+), 626 deletions(-)
diff --git a/src/S7CommPlusDriver.slnx b/src/S7CommPlusDriver.slnx
index afa1056..aeb2d33 100644
--- a/src/S7CommPlusDriver.slnx
+++ b/src/S7CommPlusDriver.slnx
@@ -5,6 +5,11 @@
+
+
+
+
+
diff --git a/src/S7CommPlusGUIBrowser/Form1.Designer.cs b/src/S7CommPlusGUIBrowser/Form1.Designer.cs
index 0f8fa9f..341d7e4 100644
--- a/src/S7CommPlusGUIBrowser/Form1.Designer.cs
+++ b/src/S7CommPlusGUIBrowser/Form1.Designer.cs
@@ -22,320 +22,340 @@ protected override void Dispose(bool disposing) {
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
///
- private void InitializeComponent() {
- this.components = new System.ComponentModel.Container();
- System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
- this.groupBox1 = new System.Windows.Forms.GroupBox();
- this.cbEncryption = new System.Windows.Forms.ComboBox();
- this.labelEncryption = new System.Windows.Forms.Label();
- this.tbUser = new System.Windows.Forms.TextBox();
- this.label7 = new System.Windows.Forms.Label();
- this.lbStatus = new System.Windows.Forms.Label();
- this.label6 = new System.Windows.Forms.Label();
- this.btnDisconnect = new System.Windows.Forms.Button();
- this.btnConnect = new System.Windows.Forms.Button();
- this.label2 = new System.Windows.Forms.Label();
- this.tbPassword = new System.Windows.Forms.TextBox();
- this.label1 = new System.Windows.Forms.Label();
- this.tbIpAddress = new System.Windows.Forms.TextBox();
- this.treeView1 = new System.Windows.Forms.TreeView();
- this.imageListTreeIcons = new System.Windows.Forms.ImageList(this.components);
- this.groupBox2 = new System.Windows.Forms.GroupBox();
- this.btnRead = new System.Windows.Forms.Button();
- this.tbValue = new System.Windows.Forms.TextBox();
- this.label5 = new System.Windows.Forms.Label();
- this.tbSymbolicAddress = new System.Windows.Forms.TextBox();
- this.label4 = new System.Windows.Forms.Label();
- this.tbSymbol = new System.Windows.Forms.TextBox();
- this.label3 = new System.Windows.Forms.Label();
- this.groupBox1.SuspendLayout();
- this.groupBox2.SuspendLayout();
- this.SuspendLayout();
- //
- // groupBox1
- //
- this.groupBox1.Controls.Add(this.cbEncryption);
- this.groupBox1.Controls.Add(this.labelEncryption);
- this.groupBox1.Controls.Add(this.tbUser);
- this.groupBox1.Controls.Add(this.label7);
- this.groupBox1.Controls.Add(this.btnDisconnect);
- this.groupBox1.Controls.Add(this.btnConnect);
- this.groupBox1.Controls.Add(this.label2);
- this.groupBox1.Controls.Add(this.tbPassword);
- this.groupBox1.Controls.Add(this.label1);
- this.groupBox1.Controls.Add(this.tbIpAddress);
- this.groupBox1.Location = new System.Drawing.Point(12, 12);
- this.groupBox1.Name = "groupBox1";
- this.groupBox1.Size = new System.Drawing.Size(171, 205);
- this.groupBox1.TabIndex = 0;
- this.groupBox1.TabStop = false;
- this.groupBox1.Text = "Connection";
- //
- // cbEncryption
- //
- this.cbEncryption.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.cbEncryption.FormattingEnabled = true;
- this.cbEncryption.Location = new System.Drawing.Point(9, 149);
- this.cbEncryption.Name = "cbEncryption";
- this.cbEncryption.Size = new System.Drawing.Size(151, 21);
- this.cbEncryption.TabIndex = 10;
- //
- // labelEncryption
- //
- this.labelEncryption.AutoSize = true;
- this.labelEncryption.Location = new System.Drawing.Point(6, 133);
- this.labelEncryption.Name = "labelEncryption";
- this.labelEncryption.Size = new System.Drawing.Size(60, 13);
- this.labelEncryption.TabIndex = 9;
- this.labelEncryption.Text = "Encryption:";
- //
- // tbUser
- //
- this.tbUser.Location = new System.Drawing.Point(9, 71);
- this.tbUser.Name = "tbUser";
- this.tbUser.Size = new System.Drawing.Size(151, 20);
- this.tbUser.TabIndex = 1;
- //
- // label7
- //
- this.label7.AutoSize = true;
- this.label7.Location = new System.Drawing.Point(6, 94);
- this.label7.Name = "label7";
- this.label7.Size = new System.Drawing.Size(102, 13);
- this.label7.TabIndex = 8;
- this.label7.Text = "Password (optional):";
- //
- // lbStatus
- //
- this.lbStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.lbStatus.Location = new System.Drawing.Point(233, 158);
- this.lbStatus.Name = "lbStatus";
- this.lbStatus.Size = new System.Drawing.Size(555, 16);
- this.lbStatus.TabIndex = 7;
- //
- // label6
- //
- this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(195, 158);
- this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(40, 13);
- this.label6.TabIndex = 6;
- this.label6.Text = "Status:";
- //
- // btnDisconnect
- //
- this.btnDisconnect.Location = new System.Drawing.Point(85, 176);
- this.btnDisconnect.Name = "btnDisconnect";
- this.btnDisconnect.Size = new System.Drawing.Size(75, 23);
- this.btnDisconnect.TabIndex = 4;
- this.btnDisconnect.Text = "Disconnect";
- this.btnDisconnect.UseVisualStyleBackColor = true;
- this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click);
- //
- // btnConnect
- //
- this.btnConnect.Location = new System.Drawing.Point(9, 176);
- this.btnConnect.Name = "btnConnect";
- this.btnConnect.Size = new System.Drawing.Size(75, 23);
- this.btnConnect.TabIndex = 3;
- this.btnConnect.Text = "Connect";
- this.btnConnect.UseVisualStyleBackColor = true;
- this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
- //
- // label2
- //
- this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(6, 55);
- this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(104, 13);
- this.label2.TabIndex = 3;
- this.label2.Text = "Username (optional):";
- //
- // tbPassword
- //
- this.tbPassword.Location = new System.Drawing.Point(9, 110);
- this.tbPassword.Name = "tbPassword";
- this.tbPassword.PasswordChar = '*';
- this.tbPassword.Size = new System.Drawing.Size(151, 20);
- this.tbPassword.TabIndex = 2;
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(6, 16);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(61, 13);
- this.label1.TabIndex = 1;
- this.label1.Text = "IP-Address:";
- //
- // tbIpAddress
- //
- this.tbIpAddress.Location = new System.Drawing.Point(9, 32);
- this.tbIpAddress.Name = "tbIpAddress";
- this.tbIpAddress.Size = new System.Drawing.Size(151, 20);
- this.tbIpAddress.TabIndex = 0;
- //
- // treeView1
- //
- this.treeView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
- | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.treeView1.ImageIndex = 0;
- this.treeView1.ImageList = this.imageListTreeIcons;
- this.treeView1.Location = new System.Drawing.Point(12, 183);
- this.treeView1.Name = "treeView1";
- this.treeView1.SelectedImageIndex = 0;
- this.treeView1.Size = new System.Drawing.Size(776, 255);
- this.treeView1.TabIndex = 9;
- this.treeView1.AfterExpand += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterExpand);
- this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
- //
- // imageListTreeIcons
- //
- this.imageListTreeIcons.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListTreeIcons.ImageStream")));
- this.imageListTreeIcons.TransparentColor = System.Drawing.Color.Transparent;
- this.imageListTreeIcons.Images.SetKeyName(0, "Default");
- this.imageListTreeIcons.Images.SetKeyName(1, "Datablock");
- this.imageListTreeIcons.Images.SetKeyName(2, "Tag");
- this.imageListTreeIcons.Images.SetKeyName(3, "Boolean");
- this.imageListTreeIcons.Images.SetKeyName(4, "Boolean1");
- this.imageListTreeIcons.Images.SetKeyName(5, "Boolean2");
- this.imageListTreeIcons.Images.SetKeyName(6, "Any");
- this.imageListTreeIcons.Images.SetKeyName(7, "Binary");
- this.imageListTreeIcons.Images.SetKeyName(8, "Binary2");
- this.imageListTreeIcons.Images.SetKeyName(9, "Date");
- this.imageListTreeIcons.Images.SetKeyName(10, "Integer");
- this.imageListTreeIcons.Images.SetKeyName(11, "Integer2");
- this.imageListTreeIcons.Images.SetKeyName(12, "Number");
- this.imageListTreeIcons.Images.SetKeyName(13, "Number2");
- this.imageListTreeIcons.Images.SetKeyName(14, "Time");
- this.imageListTreeIcons.Images.SetKeyName(15, "Datetime");
- this.imageListTreeIcons.Images.SetKeyName(16, "Datetimezone");
- this.imageListTreeIcons.Images.SetKeyName(17, "Duration");
- this.imageListTreeIcons.Images.SetKeyName(18, "Timer");
- this.imageListTreeIcons.Images.SetKeyName(19, "Char");
- this.imageListTreeIcons.Images.SetKeyName(20, "Text");
- this.imageListTreeIcons.Images.SetKeyName(21, "Text2");
- this.imageListTreeIcons.Images.SetKeyName(22, "Text3");
- this.imageListTreeIcons.Images.SetKeyName(23, "Structure");
- this.imageListTreeIcons.Images.SetKeyName(24, "Currency");
- this.imageListTreeIcons.Images.SetKeyName(25, "Percentage");
- this.imageListTreeIcons.Images.SetKeyName(26, "UserDataType");
- this.imageListTreeIcons.Images.SetKeyName(27, "UserDefinedDataType");
- this.imageListTreeIcons.Images.SetKeyName(28, "CountCollection");
- this.imageListTreeIcons.Images.SetKeyName(29, "FolderOpened");
- this.imageListTreeIcons.Images.SetKeyName(30, "FolderClosed");
- this.imageListTreeIcons.Images.SetKeyName(31, "FolderTopPanel");
- this.imageListTreeIcons.Images.SetKeyName(32, "Indexer");
- this.imageListTreeIcons.Images.SetKeyName(33, "Library");
- this.imageListTreeIcons.Images.SetKeyName(34, "NamedSet");
- this.imageListTreeIcons.Images.SetKeyName(35, "TypeDefinition");
- //
- // groupBox2
- //
- this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.groupBox2.Controls.Add(this.btnRead);
- this.groupBox2.Controls.Add(this.tbValue);
- this.groupBox2.Controls.Add(this.label5);
- this.groupBox2.Controls.Add(this.tbSymbolicAddress);
- this.groupBox2.Controls.Add(this.label4);
- this.groupBox2.Controls.Add(this.tbSymbol);
- this.groupBox2.Controls.Add(this.label3);
- this.groupBox2.Location = new System.Drawing.Point(189, 12);
- this.groupBox2.Name = "groupBox2";
- this.groupBox2.Size = new System.Drawing.Size(599, 139);
- this.groupBox2.TabIndex = 2;
- this.groupBox2.TabStop = false;
- this.groupBox2.Text = "Data";
- //
- // btnRead
- //
- this.btnRead.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
- this.btnRead.Location = new System.Drawing.Point(518, 30);
- this.btnRead.Name = "btnRead";
- this.btnRead.Size = new System.Drawing.Size(75, 23);
- this.btnRead.TabIndex = 6;
- this.btnRead.Text = "Read";
- this.btnRead.UseVisualStyleBackColor = true;
- this.btnRead.Click += new System.EventHandler(this.btnRead_Click);
- //
- // tbValue
- //
- this.tbValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.tbValue.Location = new System.Drawing.Point(6, 110);
- this.tbValue.Name = "tbValue";
- this.tbValue.ReadOnly = true;
- this.tbValue.Size = new System.Drawing.Size(587, 20);
- this.tbValue.TabIndex = 8;
- //
- // label5
- //
- this.label5.AutoSize = true;
- this.label5.Location = new System.Drawing.Point(6, 94);
- this.label5.Name = "label5";
- this.label5.Size = new System.Drawing.Size(37, 13);
- this.label5.TabIndex = 9;
- this.label5.Text = "Value:";
- //
- // tbSymbolicAddress
- //
- this.tbSymbolicAddress.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.tbSymbolicAddress.Location = new System.Drawing.Point(6, 71);
- this.tbSymbolicAddress.Name = "tbSymbolicAddress";
- this.tbSymbolicAddress.ReadOnly = true;
- this.tbSymbolicAddress.Size = new System.Drawing.Size(587, 20);
- this.tbSymbolicAddress.TabIndex = 7;
- //
- // label4
- //
- this.label4.AutoSize = true;
- this.label4.Location = new System.Drawing.Point(6, 55);
- this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(92, 13);
- this.label4.TabIndex = 7;
- this.label4.Text = "Symbolic address:";
- //
- // tbSymbol
- //
- this.tbSymbol.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.tbSymbol.Location = new System.Drawing.Point(6, 32);
- this.tbSymbol.Name = "tbSymbol";
- this.tbSymbol.Size = new System.Drawing.Size(506, 20);
- this.tbSymbol.TabIndex = 5;
- //
- // label3
- //
- this.label3.AutoSize = true;
- this.label3.Location = new System.Drawing.Point(6, 16);
- this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(44, 13);
- this.label3.TabIndex = 0;
- this.label3.Text = "Symbol:";
- //
- // Form1
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Controls.Add(this.groupBox2);
- this.Controls.Add(this.treeView1);
- this.Controls.Add(this.lbStatus);
- this.Controls.Add(this.groupBox1);
- this.Controls.Add(this.label6);
- this.Name = "Form1";
- this.Text = "S7CommPlusGUIBrowser";
- this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Form1_FormClosed);
- this.groupBox1.ResumeLayout(false);
- this.groupBox1.PerformLayout();
- this.groupBox2.ResumeLayout(false);
- this.groupBox2.PerformLayout();
- this.ResumeLayout(false);
- this.PerformLayout();
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
+ groupBox1 = new System.Windows.Forms.GroupBox();
+ cbEncryption = new System.Windows.Forms.ComboBox();
+ labelEncryption = new System.Windows.Forms.Label();
+ tbUser = new System.Windows.Forms.TextBox();
+ label7 = new System.Windows.Forms.Label();
+ btnDisconnect = new System.Windows.Forms.Button();
+ btnConnect = new System.Windows.Forms.Button();
+ label2 = new System.Windows.Forms.Label();
+ tbPassword = new System.Windows.Forms.TextBox();
+ label1 = new System.Windows.Forms.Label();
+ tbIpAddress = new System.Windows.Forms.TextBox();
+ lbStatus = new System.Windows.Forms.Label();
+ label6 = new System.Windows.Forms.Label();
+ treeView1 = new System.Windows.Forms.TreeView();
+ imageListTreeIcons = new System.Windows.Forms.ImageList(components);
+ groupBox2 = new System.Windows.Forms.GroupBox();
+ btnRead = new System.Windows.Forms.Button();
+ tbValue = new System.Windows.Forms.TextBox();
+ label5 = new System.Windows.Forms.Label();
+ tbSymbolicAddress = new System.Windows.Forms.TextBox();
+ label4 = new System.Windows.Forms.Label();
+ tbSymbol = new System.Windows.Forms.TextBox();
+ label3 = new System.Windows.Forms.Label();
+ groupBox1.SuspendLayout();
+ groupBox2.SuspendLayout();
+ SuspendLayout();
+ //
+ // groupBox1
+ //
+ groupBox1.Controls.Add(cbEncryption);
+ groupBox1.Controls.Add(labelEncryption);
+ groupBox1.Controls.Add(tbUser);
+ groupBox1.Controls.Add(label7);
+ groupBox1.Controls.Add(btnDisconnect);
+ groupBox1.Controls.Add(btnConnect);
+ groupBox1.Controls.Add(label2);
+ groupBox1.Controls.Add(tbPassword);
+ groupBox1.Controls.Add(label1);
+ groupBox1.Controls.Add(tbIpAddress);
+ groupBox1.Location = new System.Drawing.Point(14, 14);
+ groupBox1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ groupBox1.Name = "groupBox1";
+ groupBox1.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ groupBox1.Size = new System.Drawing.Size(200, 237);
+ groupBox1.TabIndex = 0;
+ groupBox1.TabStop = false;
+ groupBox1.Text = "Connection";
+ //
+ // cbEncryption
+ //
+ cbEncryption.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ cbEncryption.FormattingEnabled = true;
+ cbEncryption.Location = new System.Drawing.Point(10, 172);
+ cbEncryption.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ cbEncryption.Name = "cbEncryption";
+ cbEncryption.Size = new System.Drawing.Size(176, 23);
+ cbEncryption.TabIndex = 10;
+ //
+ // labelEncryption
+ //
+ labelEncryption.AutoSize = true;
+ labelEncryption.Location = new System.Drawing.Point(7, 153);
+ labelEncryption.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ labelEncryption.Name = "labelEncryption";
+ labelEncryption.Size = new System.Drawing.Size(67, 15);
+ labelEncryption.TabIndex = 9;
+ labelEncryption.Text = "Encryption:";
+ //
+ // tbUser
+ //
+ tbUser.Location = new System.Drawing.Point(10, 82);
+ tbUser.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ tbUser.Name = "tbUser";
+ tbUser.Size = new System.Drawing.Size(176, 23);
+ tbUser.TabIndex = 1;
+ //
+ // label7
+ //
+ label7.AutoSize = true;
+ label7.Location = new System.Drawing.Point(7, 108);
+ label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ label7.Name = "label7";
+ label7.Size = new System.Drawing.Size(115, 15);
+ label7.TabIndex = 8;
+ label7.Text = "Password (optional):";
+ //
+ // btnDisconnect
+ //
+ btnDisconnect.Location = new System.Drawing.Point(99, 203);
+ btnDisconnect.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ btnDisconnect.Name = "btnDisconnect";
+ btnDisconnect.Size = new System.Drawing.Size(88, 27);
+ btnDisconnect.TabIndex = 4;
+ btnDisconnect.Text = "Disconnect";
+ btnDisconnect.UseVisualStyleBackColor = true;
+ btnDisconnect.Click += btnDisconnect_Click;
+ //
+ // btnConnect
+ //
+ btnConnect.Location = new System.Drawing.Point(10, 203);
+ btnConnect.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ btnConnect.Name = "btnConnect";
+ btnConnect.Size = new System.Drawing.Size(88, 27);
+ btnConnect.TabIndex = 3;
+ btnConnect.Text = "Connect";
+ btnConnect.UseVisualStyleBackColor = true;
+ btnConnect.Click += btnConnect_Click;
+ //
+ // label2
+ //
+ label2.AutoSize = true;
+ label2.Location = new System.Drawing.Point(7, 63);
+ label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ label2.Name = "label2";
+ label2.Size = new System.Drawing.Size(118, 15);
+ label2.TabIndex = 3;
+ label2.Text = "Username (optional):";
+ //
+ // tbPassword
+ //
+ tbPassword.Location = new System.Drawing.Point(10, 127);
+ tbPassword.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ tbPassword.Name = "tbPassword";
+ tbPassword.PasswordChar = '*';
+ tbPassword.Size = new System.Drawing.Size(176, 23);
+ tbPassword.TabIndex = 2;
+ //
+ // label1
+ //
+ label1.AutoSize = true;
+ label1.Location = new System.Drawing.Point(7, 18);
+ label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ label1.Name = "label1";
+ label1.Size = new System.Drawing.Size(67, 15);
+ label1.TabIndex = 1;
+ label1.Text = "IP-Address:";
+ //
+ // tbIpAddress
+ //
+ tbIpAddress.Location = new System.Drawing.Point(10, 37);
+ tbIpAddress.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ tbIpAddress.Name = "tbIpAddress";
+ tbIpAddress.Size = new System.Drawing.Size(176, 23);
+ tbIpAddress.TabIndex = 0;
+ //
+ // lbStatus
+ //
+ lbStatus.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ lbStatus.Location = new System.Drawing.Point(272, 182);
+ lbStatus.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ lbStatus.Name = "lbStatus";
+ lbStatus.Size = new System.Drawing.Size(648, 18);
+ lbStatus.TabIndex = 7;
+ //
+ // label6
+ //
+ label6.AutoSize = true;
+ label6.Location = new System.Drawing.Point(227, 182);
+ label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ label6.Name = "label6";
+ label6.Size = new System.Drawing.Size(42, 15);
+ label6.TabIndex = 6;
+ label6.Text = "Status:";
+ //
+ // treeView1
+ //
+ treeView1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ treeView1.ImageIndex = 0;
+ treeView1.ImageList = imageListTreeIcons;
+ treeView1.Location = new System.Drawing.Point(14, 257);
+ treeView1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ treeView1.Name = "treeView1";
+ treeView1.SelectedImageIndex = 0;
+ treeView1.Size = new System.Drawing.Size(905, 248);
+ treeView1.TabIndex = 9;
+ treeView1.AfterExpand += treeView1_AfterExpand;
+ treeView1.AfterSelect += treeView1_AfterSelect;
+ //
+ // imageListTreeIcons
+ //
+ imageListTreeIcons.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
+ imageListTreeIcons.ImageStream = (System.Windows.Forms.ImageListStreamer)resources.GetObject("imageListTreeIcons.ImageStream");
+ imageListTreeIcons.TransparentColor = System.Drawing.Color.Transparent;
+ imageListTreeIcons.Images.SetKeyName(0, "Default");
+ imageListTreeIcons.Images.SetKeyName(1, "Datablock");
+ imageListTreeIcons.Images.SetKeyName(2, "Tag");
+ imageListTreeIcons.Images.SetKeyName(3, "Boolean");
+ imageListTreeIcons.Images.SetKeyName(4, "Boolean1");
+ imageListTreeIcons.Images.SetKeyName(5, "Boolean2");
+ imageListTreeIcons.Images.SetKeyName(6, "Any");
+ imageListTreeIcons.Images.SetKeyName(7, "Binary");
+ imageListTreeIcons.Images.SetKeyName(8, "Binary2");
+ imageListTreeIcons.Images.SetKeyName(9, "Date");
+ imageListTreeIcons.Images.SetKeyName(10, "Integer");
+ imageListTreeIcons.Images.SetKeyName(11, "Integer2");
+ imageListTreeIcons.Images.SetKeyName(12, "Number");
+ imageListTreeIcons.Images.SetKeyName(13, "Number2");
+ imageListTreeIcons.Images.SetKeyName(14, "Time");
+ imageListTreeIcons.Images.SetKeyName(15, "Datetime");
+ imageListTreeIcons.Images.SetKeyName(16, "Datetimezone");
+ imageListTreeIcons.Images.SetKeyName(17, "Duration");
+ imageListTreeIcons.Images.SetKeyName(18, "Timer");
+ imageListTreeIcons.Images.SetKeyName(19, "Char");
+ imageListTreeIcons.Images.SetKeyName(20, "Text");
+ imageListTreeIcons.Images.SetKeyName(21, "Text2");
+ imageListTreeIcons.Images.SetKeyName(22, "Text3");
+ imageListTreeIcons.Images.SetKeyName(23, "Structure");
+ imageListTreeIcons.Images.SetKeyName(24, "Currency");
+ imageListTreeIcons.Images.SetKeyName(25, "Percentage");
+ imageListTreeIcons.Images.SetKeyName(26, "UserDataType");
+ imageListTreeIcons.Images.SetKeyName(27, "UserDefinedDataType");
+ imageListTreeIcons.Images.SetKeyName(28, "CountCollection");
+ imageListTreeIcons.Images.SetKeyName(29, "FolderOpened");
+ imageListTreeIcons.Images.SetKeyName(30, "FolderClosed");
+ imageListTreeIcons.Images.SetKeyName(31, "FolderTopPanel");
+ imageListTreeIcons.Images.SetKeyName(32, "Indexer");
+ imageListTreeIcons.Images.SetKeyName(33, "Library");
+ imageListTreeIcons.Images.SetKeyName(34, "NamedSet");
+ imageListTreeIcons.Images.SetKeyName(35, "TypeDefinition");
+ //
+ // groupBox2
+ //
+ groupBox2.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ groupBox2.Controls.Add(btnRead);
+ groupBox2.Controls.Add(tbValue);
+ groupBox2.Controls.Add(label5);
+ groupBox2.Controls.Add(tbSymbolicAddress);
+ groupBox2.Controls.Add(label4);
+ groupBox2.Controls.Add(tbSymbol);
+ groupBox2.Controls.Add(label3);
+ groupBox2.Location = new System.Drawing.Point(220, 14);
+ groupBox2.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ groupBox2.Name = "groupBox2";
+ groupBox2.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ groupBox2.Size = new System.Drawing.Size(699, 160);
+ groupBox2.TabIndex = 2;
+ groupBox2.TabStop = false;
+ groupBox2.Text = "Data";
+ //
+ // btnRead
+ //
+ btnRead.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
+ btnRead.Location = new System.Drawing.Point(604, 35);
+ btnRead.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ btnRead.Name = "btnRead";
+ btnRead.Size = new System.Drawing.Size(88, 27);
+ btnRead.TabIndex = 6;
+ btnRead.Text = "Read";
+ btnRead.UseVisualStyleBackColor = true;
+ btnRead.Click += btnRead_Click;
+ //
+ // tbValue
+ //
+ tbValue.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ tbValue.Location = new System.Drawing.Point(7, 127);
+ tbValue.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ tbValue.Name = "tbValue";
+ tbValue.ReadOnly = true;
+ tbValue.Size = new System.Drawing.Size(684, 23);
+ tbValue.TabIndex = 8;
+ //
+ // label5
+ //
+ label5.AutoSize = true;
+ label5.Location = new System.Drawing.Point(7, 108);
+ label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ label5.Name = "label5";
+ label5.Size = new System.Drawing.Size(38, 15);
+ label5.TabIndex = 9;
+ label5.Text = "Value:";
+ //
+ // tbSymbolicAddress
+ //
+ tbSymbolicAddress.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ tbSymbolicAddress.Location = new System.Drawing.Point(7, 82);
+ tbSymbolicAddress.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ tbSymbolicAddress.Name = "tbSymbolicAddress";
+ tbSymbolicAddress.ReadOnly = true;
+ tbSymbolicAddress.Size = new System.Drawing.Size(684, 23);
+ tbSymbolicAddress.TabIndex = 7;
+ //
+ // label4
+ //
+ label4.AutoSize = true;
+ label4.Location = new System.Drawing.Point(7, 63);
+ label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ label4.Name = "label4";
+ label4.Size = new System.Drawing.Size(102, 15);
+ label4.TabIndex = 7;
+ label4.Text = "Symbolic address:";
+ //
+ // tbSymbol
+ //
+ tbSymbol.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+ tbSymbol.Location = new System.Drawing.Point(7, 37);
+ tbSymbol.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ tbSymbol.Name = "tbSymbol";
+ tbSymbol.Size = new System.Drawing.Size(590, 23);
+ tbSymbol.TabIndex = 5;
+ //
+ // label3
+ //
+ label3.AutoSize = true;
+ label3.Location = new System.Drawing.Point(7, 18);
+ label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ label3.Name = "label3";
+ label3.Size = new System.Drawing.Size(50, 15);
+ label3.TabIndex = 0;
+ label3.Text = "Symbol:";
+ //
+ // Form1
+ //
+ AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ ClientSize = new System.Drawing.Size(933, 519);
+ Controls.Add(groupBox2);
+ Controls.Add(treeView1);
+ Controls.Add(lbStatus);
+ Controls.Add(groupBox1);
+ Controls.Add(label6);
+ Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ Name = "Form1";
+ Text = "S7CommPlusGUIBrowser";
+ FormClosed += Form1_FormClosed;
+ groupBox1.ResumeLayout(false);
+ groupBox1.PerformLayout();
+ groupBox2.ResumeLayout(false);
+ groupBox2.PerformLayout();
+ ResumeLayout(false);
+ PerformLayout();
}
diff --git a/src/S7CommPlusGUIBrowser/Form1.resx b/src/S7CommPlusGUIBrowser/Form1.resx
index 9fe5485..604d6e5 100644
--- a/src/S7CommPlusGUIBrowser/Form1.resx
+++ b/src/S7CommPlusGUIBrowser/Form1.resx
@@ -1,313 +1,313 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 17, 17
-
-
-
- AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
- LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
- ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAC4
- KgAAAk1TRnQBSQFMAgEBJAEAAZgBAAGYAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
- AwABQAMAAaADAAEBAQABCAYAASgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
- AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
- AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
- AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm
- AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM
- AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA
- ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz
- AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ
- AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM
- AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA
- AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA
- AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ
- AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/
- AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA
- AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm
- ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ
- Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz
- AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA
- AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM
- AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM
- ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM
- Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA
- AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM
- AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ
- AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz
- AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm
- AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw
- AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD//8A/wD/AP8ANQAJ9AcA
- BfQGABX0EAAB9AcUCfQDFAH0BgAB9AMUAvQEFAH0BBQB9AQUAfQBAAH/A/QGAAP0Af8BAAH0ARQF9AEU
- AfQGFAL0ARQD9AYAA/QBFAL0ARQC9AEUAfQBFAL0ARQB9AEUAvQBFAH0AQAB9AFtARQB8wYAAfQBFAFt
- AfQBAAH0ARQF9AEUBvQBFAL0ARQB9AoAAfQBFAL0BBQB9AQUAfQEFAH0AQAB8wEUAZIB9AYAAfQBkgEU
- AfMB/wH0ARQF9AEUBvQBFAL0ARQB9AoAAfQBFAL0ARQC9AEUAfQBFAL0ARQB9AEUAvQBFAH0AQAB8wEU
- CfQB8wEUAfQBAAH0ARQF9AEUAfQEFAH0ARQC9AEUAfQKAAH0ARQC9AQUAfQEFAH0BBQC9AGSARQC9AIU
- AvQCFAH0AfMBFAGSAvQBFAX0ARQG9AEUAvQBFAH0CgAB9AEUAvQEFAH0BBQB9AQUAvQBFAFtAvQCFAL0
- AhQC9AFtARQC9AcUBvQBFAL0ARQB9AoAAfQBFAL0BBQB9AQUAfQEFAH0AfMBFAFtCvQBbQEUCvQEFAH0
- ARQC9AEUAfQKAAH0ARQC9AQUAfQEFAH0BBQB9AHzAZIBFAH0Af8HAAH0ARQBkgH0BAAB9AEUCPQBFAL0
- ARQB9AoAAfQBFAL0ARQC9AEUAfQEFAH0ARQC9AEUAfQBAAHzARQB9AgAAfMBFAH0BQAB9AEUCPQBFAL0
- ARQB9AoAAfQBFAL0ARQC9AEUAfQEFAH0ARQC9AEUAfQBAAHzARQBkgH0BgAB9AGSARQB8wUAAfQBFAH0
- BhQB9AEUAvQBFAP0BgAD9AEUAvQEFAH0ARQC9AEUAfQEFAH0AQAB9AFtARQB9AYAAfQBFAFtAfQFAAH0
- ARQI9AEUAvQDFAH0BgAB9AMUB/QEFAb0AQAB/wP0BgAD9AH/BQAB9AEUCPQBFAb0BgAF9AUABvQZAAH0
- ChQB9DQADPQBAAv0NQAB9AEUAfQDFAH0AxQB9CUADfQDAAH0ARQB9AEUBfQBFAH0BAAO9AH/AQAP9AEA
- D/QCAAH0ARQB9AMUAvQCFAb0ApkKeQEaAfQBAAH0AZkLeQGZAfQBAAH0DJkBeQH0AQAC9AEUA/QBFAP0
- ARQB9AMUAvQBeQEaCnkBmQH0AQAB9A15AfQBAAH0AZkL9AF5AfQBAAH0AhQB9AMUAfQDFAP0ARQC9AF5
- AfMLeQEbAvQNeQH0AQAB9AGZC/QBeQH0AQAO9AEUAvQBeQH0AZkKeQEaAvQNeQH0AQAB9AGZC/QBeQH0
- BAAB9AEUBPQBFAT0ARQC9AF5AfQBGgp5AZkC9A15AfQBAAH0AZkL9AF5AfQEAAH0BhQE9AEUAvQBeQv0
- AXkD9A15AfQBAAH0DXkB9AQAC/QBFAL0AXkL9AF5A/QNeQH0AQAB9A15AfQFAAH0ARQD9AEUBPQBFAL0
- AXkL9AF5AfQBAAH0DXkB9AEAAfQNeQH0BQAB9AEUA/QGFAL0AXkG9AEaBHkBmQH0AQAB9Ax5AZkB9AEA
- AfQNeQH0BQAB9AEUC/QBeQb0AZkBGgX0AQAB9AF5BvQBGgGZBfQBAAH0CHkBmQX0BQAB9AEUBPQBFAH0
- BAAB8wGZBnkBmQT0Af8CAAH0AZkHeQEbAfQFAAH0CHkBGgH0CQAB9AYUAfQEAAr0BgAK9AH/BQAK9AH/
- CQAI9AUAAf8H9AH/LQAB7AHzCQABBwHqAfIEAAH/AewD6gHsAfQB/wX0Af8MAA30AwAB9AEHBOoBBwH0
- BwAB/wHsAW0B/wMAAe8B6gHvAfIB7wHqAewB9AHbA7MB2wH0DAAB9AsUAfQDAAHwBuoB6wH0BwAB8gHq
- Ae8DAAHqAW0DAAGSAeoB9AWzAfQMAAH0ARQJ9AEUAfQDAALwAfQBAAHsAfIB7wHqAfcIAAHvAeoB8wIA
- AeoBkgMAAbwB6gH0BbMB9AwAAfQBFAn0ARQB9AcAAewB8wH0AuoIAAH/AW0B7AH/AQAB6gHsAwABBwHq
- AfQBswHbAdwB2wGzCvQDAAH0ARQJ9AEUAfQHAAHsAfMB8gHqAesJAAHwAeoBBwEAAewB6gHzAQAB/wHs
- AeoB9AGzA/QBswf0ApIB9AMAAfQBFAn0ARQB9AcAAewB7wLqAfAKAAGSAeoB9AHyAuoB7AFtAeoBBwH0
- AdwDswHcBvQB8gHqAfAP9AEUAfQFAAH0AQcD6gEHBgAB/wHxAbwB8gEAAf8B6gHsAQAB8wHvApIBvAEA
- Af8F9AFtAewB8gL0AfEBbQHsAfQBAAH0BxQG9AEUAfQEAAHyA+oB9wH0BgAB9AFtA+oB7QH/AbwB6gG8
- CwAB9AHzAW0BEwJtARQB7QH0Af8BAAH0ARQB7QH0Ae0BFAH0ARQG9AEUAfQDAAH0AuoB7wHrAfMHAAHs
- AeoBvAH0AQcB6gEHAQAB7AFtAf8KAAH0AfIBEwHvAfQB8gGSAW0B9AH/AQAB9AEUAfQBFAH0ARQB9AEU
- BvQBFAH0AwABBwHqAQcBAAHsAfMHAAHqAewDAAHsAeoBAAHzAeoBkgoAAfQB7QHsBPQBbQEHAfQBAAH0
- ARQB9AETAfQBFAH0ARQC9AUUAfQDAAEHAeoB8AEAAewB8wcAAeoBvAMAAe8B6gH0AQABBwHqAfEJAAH0
- AW0BBwT0ApIB9AEAAfQBFAHtAfQB7QHqAfQBFAL0ARQC9AHxARQB9AMAAfEB6gHsAfQB7AHzAfQBBwH0
- BAAB6gHvAwAB7AHqAf8BAAH/AewBbQH/CAAB9AHsAfcE9AHsAe8B9AEAAfQHFAL0ARQB9AHxARQB8wH0
- BAAB9wbqAfQEAAFtAeoB9AEAAfMB6gHsAwAB8gHqAe8IAAH0AfABEwEHAvQB9wHqAfMB/wEACvQBFAHx
- ARQB8wH0BgAB8AHrA+oBBwH/BAAB8QLqAewC6gHxBAAB7wHqAfMIAAH0AQcB6gIUAW0B8AH0BQAB9AgU
- AfMB9AkAAewB8wgAAfMB7wGSAe8B8gUAAf8BvAHxCQAG9AYACvQOAAH/AvQB/zsAAbwBbQISAW0B8jkA
- AfIBEgH3AfMB9AHyAfQhAAb0AgAG9AEAAv8EAAH0Af8BAAGSAW0B/yUAAfQEigH0AgAB9ASKAfQBAALs
- AwAB8wESAfEBAAHrAfcFAAH/D/QB/w/0AQAB9ASKAfQCAAH0BIoB9AEAAbwBEgHzAvQB9wFtAf8BAAHr
- AZIFAAH0AZIDFAH0ARQB7AEUAewC8QHsAhQC9AGSAxQB9AEUAewBFAHsAvEB7AIUAfQBAAH0BIoB9AIA
- AfQEigH0AQAB/wFtBBIB7wIAAQcBbQH0BAAB9AEUAu8BFAH0AhQB8AEUAfcB7QEUAfEBBwL0ARQC7wEU
- AfQCFAHwARQB9wHtARQB8QEHAfQBAAH0BIoB9AIAAfQEigH0AgABkgHsAfQB8QESAfED9ALrAbwB8QG8
- AvQB8wFtAhQB9AEUAe8B9AFtAewBbQHsBPQB8wFtAhQB9AEUAe8B9AFtAewBbQHsA/QBAAb0AgAG9AIA
- AfIBEgH0AfcB6wMSAW0BBwGSAW0BEgFtAfEB9AEHAe8B7AEUAfQCFAEHARQB9wHvARMB7wH3AvQBBwHv
- AewBFAH0AhQBBwEUAfcB7wETAe8B9wH0AQAO9AIAAf8BbQEHAW0BBwESAbwB9AHvARIB8wP/AQAB9AG8
- AhQB7QH0ARQBkgEUAewC8wH3AhQC9AG8AhQB7QH0ARQBkgEUAewC8wH3AhQB9AEAAfQMigH0AwABBwFt
- ARIB8gESAfABAAH0ARIB8QQAAf8F9AEUAbwC9AH/BfQB/wX0ARQBvAL0Af8F9AEAAfQMigH0AwAB8wES
- AZIB/wESAe0B7wLrAfQJAAH0ARQBvAH0DAAB9AEUAbwB9AgAAfQMigH0BAAB9AH/AfQBEgHtAZIBbQHy
- CgAE9AwABPQIAAH0DIoB9AYAAfQBEgHxAQAB7wFtAf8lAA70BgAB9AESAQcB8QGSAW0B/zkAAfQCEgFt
- AewB8zgAAfEB7AHvAewC8wG7ArQBtQHzBgAB8wHvAewB6wHsAe8B9BUABvQBAAn0AgABBwHtAfMBkgHz
- AbwBtAHwAv8B8AG0AbwDAAH/AQcB7AHvAfEB8wHxAe8B7AEHAf8IAAf0BAAB9AGSAhQBbQH0AQAB9AGS
- BRQBvAH0AQAB8QHsAQcB8QH3AfIBtAH0Bf8BtAHzAgABBwHsAfQF/wH0AewBBwYAAf8B9AEHAW0DFAFt
- AQcB9AH/AgAB9AHyAewBEwHzAfQBAAH0AfMBbQIUAeoBBwL0Af8B7AHxAe8C7AGuAbwG/wHwAbUBAAHz
- AewB9Af/AfQB7AHzBQAB9AGSAeoBBwP0AQcB6gGSAfQDAAH0AfIBFAHwAfQBAAH/AfQBEwIUAe8B9AIA
- AfAB7wL/Ae0B/wG0AfQC/wPrAv8BtAEAAu8J/wLvBAAB9AEHAeoB8gX0AfIB6gEHAfQDAAH0AW0B7AP0
- Ae8CFAETAfMB/wIAAZIB8gL/AewB/wG0A/8B6wT/AbQBAAHsAfEJ/wHxAewEAAH0AW0BBwf0AQcBbQH0
- AwAB9AHvBxQB7AH0AwAB7AP/Ae0B/wG1AfAC/wHrA/8B8AG1AQAB6wHzBP8E6wH/AfMB6wQAAfQBFAP0
- AZIBEwGSA/QBFAH0AwAB/wH0ARMB7wH0AfIDFAHwAfQDAAHsBusBtAL/AesD/wG0AfABAAHsAfEE/wHr
- BP8B8QHsBAAB8gEUA/QDFAP0ARQB9AQAAfQB7QFtAfQB7QIUAW0B9AQAAewD/wHtAv8BvAG0AfAC/wHw
- AbQBBwH0AQAC7wT/AesE/wLvBAAB9AEUA/QB7AEUAewD9AEUAfQEAAH0AfIBFAHwARMCFAHvAfQEAAH3
- AfEC/wHsA/8B8gG1AbMBrQGRAfEB/wHxAQAB8gHsAfQD/wHrA/8B9AHsAfMEAAH0AW0BBwL0AQcBFAEH
- AvQBBwFtAfQFAAH0AW0B6gIUARMB8wH/BAAB8AHvAv8B7Qb/AfAB7wL/Ae8CAAHvAewB8wL/AesC/wHz
- AewB7wUAAfQBBwHqAfIC9AEUAvQB8gHqAQcB9AUAAfQB7wMUAewB9AUAAf8B7AHxAQcD7APrA+wB7wHw
- AewCAAH/Ae8B7AHvAfEB8wHxAe8B7AHvAf8GAAH0AZIB6gEHAfQBFAH0AQcB6gGSAfQGAAH/AfQBEwIU
- AfAB9AYAAfIB7AEHAfAB9wX/AewB8wG8AewB8wQAAfMB7wHsAesB7AHvAfMIAAH/AfQBBwFtAxQBbQEH
- AfQB/wcAAfQB7QEUAW0B9AgAAfAB7QHzAZIB8wP/AgcB8gHsAfEHAAPrDAAC9AMUAvQJAAH0AfIBFAHv
- AfQJAAHyAewB9wHsAfIB/wHwAewB7wHsAfMIAAPrDAAB9AUUAfQKAAP0Af8KAAH/AfEB9wLrAewB7wHx
- Af8IAAXrCwAH9DgAAfQBCQS0AbwB9A0AAfQBuwK0AbsB9CMAAf8BvAG0AbUBCQLwAQkBtQG0AbwB/wIA
- COsBrgG0AQkC9AHwAbQBvARtAeoB9AHsAe0B/wHtAm0B6gJtAfIGAAH/AfQJAAH/AbsBtAHwBv8B8AG0
- AbsB/wEAAesD/wHvAv8B8wG0Bv8BtAGSAe8BbQLsAf8B7AHtAf8B7wHqAuwC7wH0AwAE9AHwB/QCAAG8
- AbQB8wj/AfMBtAG8AQAB6wP/Ae8C/wG1AQkG/wHdAQAB9AFtAe8FAAH/AuwB8wYAAfQBFAGSAewBFAH3
- BBQBvAH0AQAB9AG0AfEK/wHxAbQB/wHrBv8BtAP/A+sC/wEAAfQBbQHvAf8FAAH0AewB6wYAAfQBFAGS
- AfMB9wHzAhMBBwG8AfMB9AEAAbwBtQz/AbUBvAHrAu8B/wNMAa4D/wHrBP8BAAH0AW0B7wH/BgAB/wFt
- AfMEAAL0ARQBkgP0Ae8BFAHqAfAB9AH/AQABtAEJBf8DbQHrAe0C/wEJAbQB6wP/AUwC/wG1AQkC/wHr
- A/8B3QEAAfQBbQHvAf8HAAHtAewB9AIAA/QBFAGSAfQBAAL0AfACEwHzAf8BAAG0AfEF/wFtBv8B8QG0
- AesD/wFMAv8B9AG0Av8B6wP/AbQBAAH0AW0B7wH/BwAB9AHrAe0B/wEAAfQB7wHsARQBkgH0AQAB9AG8
- AfQBkgEUAbwB9AEAAbQB8QX/AW0G/wHxAbQB6wP/AUwD/wGNAbQB8AL0AfABtAGuAQAB9AFtAe8B/wgA
- AQcB6gH0AQAB9AH3AhQBkgH0AQAB9AQUAfAB/wEAAbQBCQX/AW0G/wEJAbQB6wLvAf8FTAHzBLQB9wHr
- AfQB/wFtAe8B/wMAAv8DAAG8AeoB8gEAAvQB8AHsAe8B9AEAAfQBvAHtAewBBwH0AgABvAG1Bf8BbQb/
- AbUBvAHrC/8B7wL/AusBkgFtAe8B/wMAAf8B8gEHAf8B9AHsAeoB9AMABPQCAAT0AwAB9AG0AfEE/wFt
- Bf8B8QG0Af8B6wP/Ae8D/wHvA/8B7wL/AesBkgHrAeoB7wH/BAAB8gFtAesBbQHqAQcB/xEAAbwBtAHz
- A/8B8AT/AfMBtAG8AQAB6wP/Ae8D/wHvA/8B7wL/AesC/wHzAfIB/wQAAv8B8QHtAfMB/xIAAf8BuwG0
- AfAG/wHwAbQBuwH/AQAQ6yIAAf8BvAG0AbUBCQLwAQkBtQG0AbwB/wIAEOskAAH0AbwBtQK0AbUBvAH/
- BAAQ6xAAEOsLAAH0AfIB8yIAAesD/wHvA/8B7wP/Ae8D/wMAAf8GAAG8AxIB7AH0IAAB6wP/Ae8D/wHv
- A/8B7wP/AgABBwESAf8FAAHxAfQB/wHyAesBkhAAEPQB6wP/Ae8L/wIAAQcBEgH/CQABBwESAQAB/wj0
- A/8DAAH0DhQB9AHrBu8B/wVMAf8C7wIAAQcBEgH/CAAB/wGSAesBAAH0CPMB9ALzAvQBAAH0ARQM9AEU
- AfQB6wP/Ae8D/wFMA/8BTAP/AgABBwESBv8BAAG8AewBbQHsAfQBAAH0AbwBFAHwAfQDFAFtAfQCFAHq
- AfEB/wH0BBQB9AEUAfQDFAH0ARQB9AEUAfQB6wP/Ae8D/wFMA/8BTAP/AgABBwESAQcFEgEAAfIBBwGS
- AewB9AEAAfQBvAEUAfAB9AETAW0BBwHwAfQB8AG8ARQB9wL0AhQB9AEUAfQBFAH0ARQB9AEUAfQBFAH0
- ARQB9AHrA/8B7wP/AUwD/wFMA/8CAAEHARIBvAESAfED8gQAAewB9wL0AbwBFAHwAfQBBwETAW0B8wH0
- Ae0C6gHwAvQCFAH0ARQB9AEUAfQBFAH0ARQB9AEUAfQBFAH0AesG7wH/BUwB/wLvAfQBAAEHARIB/wLs
- Af8GAAHrAewB9AHxAe8BFAHwAvQB8AEUAZIB9ALwAW0B9AH/AfQEFAH0ARQB9AMUAfQBFAH0ARQB9AHr
- A/8B7wv/AQcB6wGSARIC/wHsAesB9AIAAW0B7AHrARIB8QH0AZICFAHwAfQB6gGSARQB7QH0AewBbQEU
- AbwC9AEUDPQBFAH0AesD/wHvA/8B7wP/Ae8E/wG8AesBEgH/AQAB/wHvAW0B9AEAAfECBwHzAQAB9AHz
- AfcBFAHwAfQBkgEUAewB8QH0AewBbQHtAfQBAAH0DhQB9AHrA/8B7wP/Ae8D/wHvA/8CAAH/AbwEAAH3
- AW0HAAH/DPQB/wEAEPQQ6wgAAfIBEgHyJQAQ6wQAAfMB8gIAAbwBEgHzJQAQ6wQAAfMBEgLsARIBkiYA
- EOsFAAH0AbwBBwG8RwAQ6wcAAvQXAAHvBBIB7wQSAe8B7ANtAfMB6w7/AesGAAH0AvAB9AYAEPQB/wH0
- ARIBvAL0AesBBwL0Af8B8wL/AZIC6w7/AesFAAH0AfACEwHwAfQFAAH0DhQB9AEAAfQBEgHxAgAB9AHr
- AbwFAAHvAW0B6wL/CusC/wHrBAAB9AHwBBMB8AH0BAAB9AQUAW0CFAb0ARQB9AEAAfQBEgHxAwAB9AHr
- AbwBAAH/Ae8BkgFtAbwB6w7/AesDAAH/AfQB6gETAvACEwHwAfQDAAH0AhQBEwEHAfQBEwEUAvQBFAFt
- AvQBFAH0AQAB9AESAfEEAAHzARIB8wH/Ae8B9wHsAfQB6w7/AesCAAH/AvQC8AL0AfACEwHwAfQCAAH0
- ARQBEwG8AfQBbQIUA/QBFAFtAfQBFAH0AQAB9AESAfEFAAHrAe8DAAHrAfcB6w7/AesBAAH/AvMC9ALz
- AvQB8AITAfAB9AEAAfQBFAG8BfQFFAHvARQB9AEHAewBEgHxAQAB9AGSAfEBvAESArwC8QFtAfcB6wL/
- CusC/wHrAf8B9AJtAvMCbQP0AfACEwH0AQAB9AEUAe8F9AUUAe8BFAL0AbwBkgHyAgAB7wLrAe8BAAHx
- AusBkgH0AesO/wHrAQAB9AHvARQCbQEUAe8B9AH/AQAB9AHwAQcB9AEAAfQCFAHvAfQBbQIUA/QBFAFt
- AfQBFAH0ARIB8QIAAf8DEgHqAZIB9AH/AQcB6wESAZIB6w7/AesCAAH0AfcCFAH3AfQB/wMAAvQCAAH0
- AxQB7wH0ARMBFAL0ARQBbQL0ARQB9AHvAewCAAHzAhICAAHtAe8BBwHsAfMB/wHzAesO/wHrAQAB9AHz
- AfcCFAH3AfMB9AcAAfQEFAFtAhQG9AEUAfQBAAQSAbwBEgEAAf8B9wEHAeoB9AMAAesC/wrrAv8B6wH/
- AfQBbQEUAu8BFAFtAvQGAAH0DhQB9AEAARIB8gH/ARIB9AMSAfcB/wESAf8DAAHrDv8B6wEAAfQB8AHv
- AvQC7wH0BwAQ9AEAAfIBEgHzARIBAAESAQAB/wHsAf8BbQHzAwAB6w7/AesCAAL0Af8BAAL0GQAB/wFt
- ARIB7wEAARIBAAH/AeoB9AG8AewB8wEAAfQB6w7/AesiAAG8ARIB/wEAAxIB7QH/AQAB8AHrARIB7BDr
- EwAB/wj0Af8JAAH/EAAB8gH0GQAC9AEJAdsEswHbAQkC9AcAA/QOAAH0ArQB/wYAD/QDAAH0AboIswG6
- AfQGAAH0AfEB6wHyAfQMAAH/AbQCrQG1Af8FAAH0AZkLeQGZAfQDAAH0CrMB9AUAAfQB8QHqAesBbQHy
- BfQGAAH/AbQBrQG0AbMBrQEHBQAB9A15AfQDAAH0CrMB9AQAAfQB8QHqAe8B9AGSAW0B8gHsARMB7AHx
- AfQEAAH/AbUCrQHyAfACrQHyBAAB9A15AfQDAAH0CrMB9AMAAfQB8QHqAe8D9AGSAW0C8gH3ARIB8QH0
- AwAB8QKtAfABAAH/AbsBrQG0AfQDAAH0DXkB9AMAAfQKswH0AgAB9AHxAeoB7wX0AZIBbQHyAfQB9wHr
- AfQB8wFMARoB8wGtAQkDAAHzAbQBrQG0Af8CAAH0DXkB9AMAAfQKswH0AgAB9ALrB/QBkgFtAvIBEwH0
- ARoCTAHyAfQB/wIAAfQBTAHxAbQBrQG7Af8BAAH0DXkB9AMAAfQKswH0AgAB9AHyAW0Bkgf0AZIB6wHy
- ARMB9AH/A0wB9AIAAfQBTAGTAQAB8QKtAbwBAAH0DXkB9AMAAfQKswH0AwAB9AHyAW0Bkgf0AQcB9wHr
- AfQBAAH0A0wC9AJMAf8BAAH/AbsCrQHzAfQNeQH0AwAB9AqzAfQEAAH0AfIBbQGSBfQB8gH3ARIB8QH0
- AgAB9AVMAfMDAAH/AbQBrQG1AfQMeQGZAfQDAAH0A7ME2wOzAfQFAAH0AfIBbQGSA/QB7wETAewB8QH0
- BAAB/wNMAZMFAAH0AbsB/wH0AXkG9AEaAZkF9AMAAfQBswEJBvQBCQGzAfQGAAH0AfIBbQGSBPQBBwH0
- BAAB9gGTBEwBkwH/BgAB9AGZB3kBGwH0BwAB9AG6AbkBCQEZAvMBGQEJAbkBugH0BwAB9AHyAW0FFAH0
- AwABGwNMARoB/wGTAUwBbwH0BQAK9AH/BwAC9AEJAdsEswHbAQkC9AgACPQDAAFvAkwB8gMAAfQBGgH/
- GAAB/wj0Af8UAAH0ARoB/wwAAUIBTQE+BwABPgMAASgDAAFAAwABoAMAAQEBAAEBBgABBRYAA/+BAAb/
- AQABfwEHAeACAAL/AgABBwHgAgABhwHhAgABBwHgAgABhwHhAgABHwH4AgABhwHgAgABHwH4AgABgAEB
- AgABHwH4BgABHwH4BgABHwH4BgABHwH4AgABBwLwAQABHwH4AgABjwHxAfABAAEfAfgCAAGHAeEB8AEA
- AQcB4AIAAYcB4QHwAQABBwHgAgABhwHhAfABAAEHAeAB+AEfAv8B8AEABv8B8AEAAYABDwb/AYABDwT/
- AYABAwGAAQ8BAAEBAQABAQEAAQEBgAIAAQEBAAEBAQABAQMAAQEBAAEBAQABAQUAAQEBAAEBBQABAQEA
- AQEB4AQAAQEBAAEBAeAEAAEBAQABAQHgBAABAQEAAQEB8AIAAQEBAAEBAQABAQHwAgABAQEAAQEBAAEB
- AfACAAEBAQABAQEAAQEB8AEPAQABAwEAAR8BAAEfAfABDwEAAT8BAAEfAQABHwHwAQ8BgAE/BP8B/gF/
- AccBgAEBAf8B4AEAAeABHwHDAYABAQH/AeABAAHgAQ8B4wGcAQEB/wHgAQAB4gEPAfEBnAEBAf8B4AEA
- Af4BDwHwAZwCAAHgAQAB/gEPAfgBiAIAAeABAAH+AQ8B/AUAAfgBHwGEAUEBAAEBAgAB8AE/AQABPwH4
- AQECAAHgAX8BAQEfAfgBAQIAAeIBfwE5AR8B+AEBAgAB4gF/ATgBjwH4AQECAAHgAQ8BOAGHAfgBAQIA
- AfABDwERAccB+AEBAQABAQH4AQ8BAQHjAfwBAwHgAQMB/gF/AYMB4wH+AQcB4AEHAf8B4Qf/AcAH/wGA
- BP8CgQE8AY8E/wKBATgBnwQAAoEBAAGfBAACgQEBAY8EAAKBAYAFAAKBAYAFAAGAAQEBgAEBBAABgAEB
- AcABjwQAAYABAQHAAQ8B+AF/AfgBfwGAAQEB4AEfAfgBfwH4AX8BgAEBAfgBjwT/AYABAQH4AQ8G/wH4
- AR8G/wHgAQMB8AEfAv8BAgEAAcABAQHAAQcB+AEPAQIBAAGAAQABwAEHAeABAwECAwABgAEDAeABAwGC
- AQMCAAGAAQMBwAEBAcABAwIAAYABAwHAAQEBwAEHAgABgAEDAcABAQHAAQcCAAGAAQMBwAEBAeABDwIA
- AYABAwHAAQEB4AEPAgABgAEDAcABAQHwAQ8CAAHAAQcBwAEBAfABHwIAAcABBwHgAQMB8AEfAYABAAHw
- AR8B4AEDAfgBPwHAAQEB/AF/AfgBDwH4AT8B4AEDAfwBfwH4AQ8B/AE/AfABBwH4AT8B+AEPBv8B8AEP
- Af8BgQT/AcABAwQAAfwB/wGAAQEEAAHgAQEBgAEBAgABjwGHAeABAQQAAYcBxwHgAQEEAAGHAeMBwAEB
- BAABhwHxAYEBAQQAAYcB8AGBAQEEAAGHAfgBgQEBBAABBwE4AYEBAwQAAQcBAAHhAYcEAAEHAYAC/wGA
- AQECAAEHAYEC/wGAAQECAAT/AcABAwIABP8B8AEPAgAC/wIAAf8B4wT/AgAB7wHABP8CAAHHAcAC/wQA
- AccB/AGAAQcEAAHHAfgBgAEBBAABwAEgAYAFAAHAASABgAUAAcABPAYAAUAB/AcAAWAGAAEEASEBAAEB
- BAABzwE/AYABAQQAAf8BHwT/AgAB8wEfBP8CAAHwAT8E/wIAAfgBfwj/AgAB/gF/Av8EAAH8AT8GAAH4
- AR8CAAGMAXwCAAHwAQ8CAAGOASACAAHgAQcCAAGPAwABwAEDAgABjwGcAgABgAEBAgABCAQAAQECAAEM
- ASACAAGAASECAAEwAwABwAFzAgABMQGAAgABgAF/AgABgQEHAwABPwIAAYABBwIAAYABfwIAAYUBBwIA
- AcQD/wGFAQICAAT/AcQBEAIAAv8B4AEHAf0B/wH+AX8C/wHAAQMB+AH/AfwBPwEAAQEBwAEDAfABfwH4
- AR8BAAEBAcABAwHgAQMB8AEfAQABAQHAAQMBwAEBAeABDwEAAQEBwAEDAYABAAHhAQcBAAEBAcABAwIA
- AQMBgwEAAQEBwAEDAgABAwEBAQABAQHAAQMCAAEGASEBAAEBAcABAwGAAQABgAEgAQABAQHAAQMBwAEA
- AcABcAEAAQEBwAEDAeABAQHgAfgBAAEBAcABAwHwAQMBwAE/AQABHwHAAQMB+AEDAYABHwEAAR8BwAED
- AfwBAwGHAR8C/wHgAQcC/wGPAf8L
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+
+ AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs
+ LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu
+ SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAuCoAAAJNU0Z0AUkBTAIBASQB
+ AAGgAQABoAEAARABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMAAUADAAGgAwABAQEAAQgG
+ AAEoGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEAAfABygGmAQABMwUAATMB
+ AAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEAAYABfAH/AQACUAH/AQAB
+ kwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFmAwABmQMAAcwCAAEzAwAC
+ MwIAATMBZgIAATMBmQIAATMBzAIAATMB/wIAAWYDAAFmATMCAAJmAgABZgGZAgABZgHMAgABZgH/AgAB
+ mQMAAZkBMwIAAZkBZgIAApkCAAGZAcwCAAGZAf8CAAHMAwABzAEzAgABzAFmAgABzAGZAgACzAIAAcwB
+ /wIAAf8BZgIAAf8BmQIAAf8BzAEAATMB/wIAAf8BAAEzAQABMwEAAWYBAAEzAQABmQEAATMBAAHMAQAB
+ MwEAAf8BAAH/ATMCAAMzAQACMwFmAQACMwGZAQACMwHMAQACMwH/AQABMwFmAgABMwFmATMBAAEzAmYB
+ AAEzAWYBmQEAATMBZgHMAQABMwFmAf8BAAEzAZkCAAEzAZkBMwEAATMBmQFmAQABMwKZAQABMwGZAcwB
+ AAEzAZkB/wEAATMBzAIAATMBzAEzAQABMwHMAWYBAAEzAcwBmQEAATMCzAEAATMBzAH/AQABMwH/ATMB
+ AAEzAf8BZgEAATMB/wGZAQABMwH/AcwBAAEzAv8BAAFmAwABZgEAATMBAAFmAQABZgEAAWYBAAGZAQAB
+ ZgEAAcwBAAFmAQAB/wEAAWYBMwIAAWYCMwEAAWYBMwFmAQABZgEzAZkBAAFmATMBzAEAAWYBMwH/AQAC
+ ZgIAAmYBMwEAA2YBAAJmAZkBAAJmAcwBAAFmAZkCAAFmAZkBMwEAAWYBmQFmAQABZgKZAQABZgGZAcwB
+ AAFmAZkB/wEAAWYBzAIAAWYBzAEzAQABZgHMAZkBAAFmAswBAAFmAcwB/wEAAWYB/wIAAWYB/wEzAQAB
+ ZgH/AZkBAAFmAf8BzAEAAcwBAAH/AQAB/wEAAcwBAAKZAgABmQEzAZkBAAGZAQABmQEAAZkBAAHMAQAB
+ mQMAAZkCMwEAAZkBAAFmAQABmQEzAcwBAAGZAQAB/wEAAZkBZgIAAZkBZgEzAQABmQEzAWYBAAGZAWYB
+ mQEAAZkBZgHMAQABmQEzAf8BAAKZATMBAAKZAWYBAAOZAQACmQHMAQACmQH/AQABmQHMAgABmQHMATMB
+ AAFmAcwBZgEAAZkBzAGZAQABmQLMAQABmQHMAf8BAAGZAf8CAAGZAf8BMwEAAZkBzAFmAQABmQH/AZkB
+ AAGZAf8BzAEAAZkC/wEAAcwDAAGZAQABMwEAAcwBAAFmAQABzAEAAZkBAAHMAQABzAEAAZkBMwIAAcwC
+ MwEAAcwBMwFmAQABzAEzAZkBAAHMATMBzAEAAcwBMwH/AQABzAFmAgABzAFmATMBAAGZAmYBAAHMAWYB
+ mQEAAcwBZgHMAQABmQFmAf8BAAHMAZkCAAHMAZkBMwEAAcwBmQFmAQABzAKZAQABzAGZAcwBAAHMAZkB
+ /wEAAswCAALMATMBAALMAWYBAALMAZkBAAPMAQACzAH/AQABzAH/AgABzAH/ATMBAAGZAf8BZgEAAcwB
+ /wGZAQABzAH/AcwBAAHMAv8BAAHMAQABMwEAAf8BAAFmAQAB/wEAAZkBAAHMATMCAAH/AjMBAAH/ATMB
+ ZgEAAf8BMwGZAQAB/wEzAcwBAAH/ATMB/wEAAf8BZgIAAf8BZgEzAQABzAJmAQAB/wFmAZkBAAH/AWYB
+ zAEAAcwBZgH/AQAB/wGZAgAB/wGZATMBAAH/AZkBZgEAAf8CmQEAAf8BmQHMAQAB/wGZAf8BAAH/AcwC
+ AAH/AcwBMwEAAf8BzAFmAQAB/wHMAZkBAAH/AswBAAH/AcwB/wEAAv8BMwEAAcwB/wFmAQAC/wGZAQAC
+ /wHMAQACZgH/AQABZgH/AWYBAAFmAv8BAAH/AmYBAAH/AWYB/wEAAv8BZgEAASEBAAGlAQADXwEAA3cB
+ AAOGAQADlgEAA8sBAAOyAQAD1wEAA90BAAPjAQAD6gEAA/EBAAP4AQAB8AH7Af8BAAGkAqABAAOAAwAB
+ /wIAAf8DAAL/AQAB/wMAAf8BAAH/AQAC/wIAA///AP8A/wD/ADUACfQHAAX0BgAV9BAAAfQHFAn0AxQB
+ 9AYAAfQDFAL0BBQB9AQUAfQEFAH0AQAB/wP0BgAD9AH/AQAB9AEUBfQBFAH0BhQC9AEUA/QGAAP0ARQC
+ 9AEUAvQBFAH0ARQC9AEUAfQBFAL0ARQB9AEAAfQBbQEUAfMGAAH0ARQBbQH0AQAB9AEUBfQBFAb0ARQC
+ 9AEUAfQKAAH0ARQC9AQUAfQEFAH0BBQB9AEAAfMBFAGSAfQGAAH0AZIBFAHzAf8B9AEUBfQBFAb0ARQC
+ 9AEUAfQKAAH0ARQC9AEUAvQBFAH0ARQC9AEUAfQBFAL0ARQB9AEAAfMBFAn0AfMBFAH0AQAB9AEUBfQB
+ FAH0BBQB9AEUAvQBFAH0CgAB9AEUAvQEFAH0BBQB9AQUAvQBkgEUAvQCFAL0AhQB9AHzARQBkgL0ARQF
+ 9AEUBvQBFAL0ARQB9AoAAfQBFAL0BBQB9AQUAfQEFAL0ARQBbQL0AhQC9AIUAvQBbQEUAvQHFAb0ARQC
+ 9AEUAfQKAAH0ARQC9AQUAfQEFAH0BBQB9AHzARQBbQr0AW0BFAr0BBQB9AEUAvQBFAH0CgAB9AEUAvQE
+ FAH0BBQB9AQUAfQB8wGSARQB9AH/BwAB9AEUAZIB9AQAAfQBFAj0ARQC9AEUAfQKAAH0ARQC9AEUAvQB
+ FAH0BBQB9AEUAvQBFAH0AQAB8wEUAfQIAAHzARQB9AUAAfQBFAj0ARQC9AEUAfQKAAH0ARQC9AEUAvQB
+ FAH0BBQB9AEUAvQBFAH0AQAB8wEUAZIB9AYAAfQBkgEUAfMFAAH0ARQB9AYUAfQBFAL0ARQD9AYAA/QB
+ FAL0BBQB9AEUAvQBFAH0BBQB9AEAAfQBbQEUAfQGAAH0ARQBbQH0BQAB9AEUCPQBFAL0AxQB9AYAAfQD
+ FAf0BBQG9AEAAf8D9AYAA/QB/wUAAfQBFAj0ARQG9AYABfQFAAb0GQAB9AoUAfQ0AAz0AQAL9DUAAfQB
+ FAH0AxQB9AMUAfQlAA30AwAB9AEUAfQBFAX0ARQB9AQADvQB/wEAD/QBAA/0AgAB9AEUAfQDFAL0AhQG
+ 9AKZCnkBGgH0AQAB9AGZC3kBmQH0AQAB9AyZAXkB9AEAAvQBFAP0ARQD9AEUAfQDFAL0AXkBGgp5AZkB
+ 9AEAAfQNeQH0AQAB9AGZC/QBeQH0AQAB9AIUAfQDFAH0AxQD9AEUAvQBeQHzC3kBGwL0DXkB9AEAAfQB
+ mQv0AXkB9AEADvQBFAL0AXkB9AGZCnkBGgL0DXkB9AEAAfQBmQv0AXkB9AQAAfQBFAT0ARQE9AEUAvQB
+ eQH0ARoKeQGZAvQNeQH0AQAB9AGZC/QBeQH0BAAB9AYUBPQBFAL0AXkL9AF5A/QNeQH0AQAB9A15AfQE
+ AAv0ARQC9AF5C/QBeQP0DXkB9AEAAfQNeQH0BQAB9AEUA/QBFAT0ARQC9AF5C/QBeQH0AQAB9A15AfQB
+ AAH0DXkB9AUAAfQBFAP0BhQC9AF5BvQBGgR5AZkB9AEAAfQMeQGZAfQBAAH0DXkB9AUAAfQBFAv0AXkG
+ 9AGZARoF9AEAAfQBeQb0ARoBmQX0AQAB9Ah5AZkF9AUAAfQBFAT0ARQB9AQAAfMBmQZ5AZkE9AH/AgAB
+ 9AGZB3kBGwH0BQAB9Ah5ARoB9AkAAfQGFAH0BAAK9AYACvQB/wUACvQB/wkACPQFAAH/B/QB/y0AAewB
+ 8wkAAQcB6gHyBAAB/wHsA+oB7AH0Af8F9AH/DAAN9AMAAfQBBwTqAQcB9AcAAf8B7AFtAf8DAAHvAeoB
+ 7wHyAe8B6gHsAfQB2wOzAdsB9AwAAfQLFAH0AwAB8AbqAesB9AcAAfIB6gHvAwAB6gFtAwABkgHqAfQF
+ swH0DAAB9AEUCfQBFAH0AwAC8AH0AQAB7AHyAe8B6gH3CAAB7wHqAfMCAAHqAZIDAAG8AeoB9AWzAfQM
+ AAH0ARQJ9AEUAfQHAAHsAfMB9ALqCAAB/wFtAewB/wEAAeoB7AMAAQcB6gH0AbMB2wHcAdsBswr0AwAB
+ 9AEUCfQBFAH0BwAB7AHzAfIB6gHrCQAB8AHqAQcBAAHsAeoB8wEAAf8B7AHqAfQBswP0AbMH9AKSAfQD
+ AAH0ARQJ9AEUAfQHAAHsAe8C6gHwCgABkgHqAfQB8gLqAewBbQHqAQcB9AHcA7MB3Ab0AfIB6gHwD/QB
+ FAH0BQAB9AEHA+oBBwYAAf8B8QG8AfIBAAH/AeoB7AEAAfMB7wKSAbwBAAH/BfQBbQHsAfIC9AHxAW0B
+ 7AH0AQAB9AcUBvQBFAH0BAAB8gPqAfcB9AYAAfQBbQPqAe0B/wG8AeoBvAsAAfQB8wFtARMCbQEUAe0B
+ 9AH/AQAB9AEUAe0B9AHtARQB9AEUBvQBFAH0AwAB9ALqAe8B6wHzBwAB7AHqAbwB9AEHAeoBBwEAAewB
+ bQH/CgAB9AHyARMB7wH0AfIBkgFtAfQB/wEAAfQBFAH0ARQB9AEUAfQBFAb0ARQB9AMAAQcB6gEHAQAB
+ 7AHzBwAB6gHsAwAB7AHqAQAB8wHqAZIKAAH0Ae0B7AT0AW0BBwH0AQAB9AEUAfQBEwH0ARQB9AEUAvQF
+ FAH0AwABBwHqAfABAAHsAfMHAAHqAbwDAAHvAeoB9AEAAQcB6gHxCQAB9AFtAQcE9AKSAfQBAAH0ARQB
+ 7QH0Ae0B6gH0ARQC9AEUAvQB8QEUAfQDAAHxAeoB7AH0AewB8wH0AQcB9AQAAeoB7wMAAewB6gH/AQAB
+ /wHsAW0B/wgAAfQB7AH3BPQB7AHvAfQBAAH0BxQC9AEUAfQB8QEUAfMB9AQAAfcG6gH0BAABbQHqAfQB
+ AAHzAeoB7AMAAfIB6gHvCAAB9AHwARMBBwL0AfcB6gHzAf8BAAr0ARQB8QEUAfMB9AYAAfAB6wPqAQcB
+ /wQAAfEC6gHsAuoB8QQAAe8B6gHzCAAB9AEHAeoCFAFtAfAB9AUAAfQIFAHzAfQJAAHsAfMIAAHzAe8B
+ kgHvAfIFAAH/AbwB8QkABvQGAAr0DgAB/wL0Af87AAG8AW0CEgFtAfI5AAHyARIB9wHzAfQB8gH0IQAG
+ 9AIABvQBAAL/BAAB9AH/AQABkgFtAf8lAAH0BIoB9AIAAfQEigH0AQAC7AMAAfMBEgHxAQAB6wH3BQAB
+ /w/0Af8P9AEAAfQEigH0AgAB9ASKAfQBAAG8ARIB8wL0AfcBbQH/AQAB6wGSBQAB9AGSAxQB9AEUAewB
+ FAHsAvEB7AIUAvQBkgMUAfQBFAHsARQB7ALxAewCFAH0AQAB9ASKAfQCAAH0BIoB9AEAAf8BbQQSAe8C
+ AAEHAW0B9AQAAfQBFALvARQB9AIUAfABFAH3Ae0BFAHxAQcC9AEUAu8BFAH0AhQB8AEUAfcB7QEUAfEB
+ BwH0AQAB9ASKAfQCAAH0BIoB9AIAAZIB7AH0AfEBEgHxA/QC6wG8AfEBvAL0AfMBbQIUAfQBFAHvAfQB
+ bQHsAW0B7AT0AfMBbQIUAfQBFAHvAfQBbQHsAW0B7AP0AQAG9AIABvQCAAHyARIB9AH3AesDEgFtAQcB
+ kgFtARIBbQHxAfQBBwHvAewBFAH0AhQBBwEUAfcB7wETAe8B9wL0AQcB7wHsARQB9AIUAQcBFAH3Ae8B
+ EwHvAfcB9AEADvQCAAH/AW0BBwFtAQcBEgG8AfQB7wESAfMD/wEAAfQBvAIUAe0B9AEUAZIBFAHsAvMB
+ 9wIUAvQBvAIUAe0B9AEUAZIBFAHsAvMB9wIUAfQBAAH0DIoB9AMAAQcBbQESAfIBEgHwAQAB9AESAfEE
+ AAH/BfQBFAG8AvQB/wX0Af8F9AEUAbwC9AH/BfQBAAH0DIoB9AMAAfMBEgGSAf8BEgHtAe8C6wH0CQAB
+ 9AEUAbwB9AwAAfQBFAG8AfQIAAH0DIoB9AQAAfQB/wH0ARIB7QGSAW0B8goABPQMAAT0CAAB9AyKAfQG
+ AAH0ARIB8QEAAe8BbQH/JQAO9AYAAfQBEgEHAfEBkgFtAf85AAH0AhIBbQHsAfM4AAHxAewB7wHsAvMB
+ uwK0AbUB8wYAAfMB7wHsAesB7AHvAfQVAAb0AQAJ9AIAAQcB7QHzAZIB8wG8AbQB8AL/AfABtAG8AwAB
+ /wEHAewB7wHxAfMB8QHvAewBBwH/CAAH9AQAAfQBkgIUAW0B9AEAAfQBkgUUAbwB9AEAAfEB7AEHAfEB
+ 9wHyAbQB9AX/AbQB8wIAAQcB7AH0Bf8B9AHsAQcGAAH/AfQBBwFtAxQBbQEHAfQB/wIAAfQB8gHsARMB
+ 8wH0AQAB9AHzAW0CFAHqAQcC9AH/AewB8QHvAuwBrgG8Bv8B8AG1AQAB8wHsAfQH/wH0AewB8wUAAfQB
+ kgHqAQcD9AEHAeoBkgH0AwAB9AHyARQB8AH0AQAB/wH0ARMCFAHvAfQCAAHwAe8C/wHtAf8BtAH0Av8D
+ 6wL/AbQBAALvCf8C7wQAAfQBBwHqAfIF9AHyAeoBBwH0AwAB9AFtAewD9AHvAhQBEwHzAf8CAAGSAfIC
+ /wHsAf8BtAP/AesE/wG0AQAB7AHxCf8B8QHsBAAB9AFtAQcH9AEHAW0B9AMAAfQB7wcUAewB9AMAAewD
+ /wHtAf8BtQHwAv8B6wP/AfABtQEAAesB8wT/BOsB/wHzAesEAAH0ARQD9AGSARMBkgP0ARQB9AMAAf8B
+ 9AETAe8B9AHyAxQB8AH0AwAB7AbrAbQC/wHrA/8BtAHwAQAB7AHxBP8B6wT/AfEB7AQAAfIBFAP0AxQD
+ 9AEUAfQEAAH0Ae0BbQH0Ae0CFAFtAfQEAAHsA/8B7QL/AbwBtAHwAv8B8AG0AQcB9AEAAu8E/wHrBP8C
+ 7wQAAfQBFAP0AewBFAHsA/QBFAH0BAAB9AHyARQB8AETAhQB7wH0BAAB9wHxAv8B7AP/AfIBtQGzAa0B
+ kQHxAf8B8QEAAfIB7AH0A/8B6wP/AfQB7AHzBAAB9AFtAQcC9AEHARQBBwL0AQcBbQH0BQAB9AFtAeoC
+ FAETAfMB/wQAAfAB7wL/Ae0G/wHwAe8C/wHvAgAB7wHsAfMC/wHrAv8B8wHsAe8FAAH0AQcB6gHyAvQB
+ FAL0AfIB6gEHAfQFAAH0Ae8DFAHsAfQFAAH/AewB8QEHA+wD6wPsAe8B8AHsAgAB/wHvAewB7wHxAfMB
+ 8QHvAewB7wH/BgAB9AGSAeoBBwH0ARQB9AEHAeoBkgH0BgAB/wH0ARMCFAHwAfQGAAHyAewBBwHwAfcF
+ /wHsAfMBvAHsAfMEAAHzAe8B7AHrAewB7wHzCAAB/wH0AQcBbQMUAW0BBwH0Af8HAAH0Ae0BFAFtAfQI
+ AAHwAe0B8wGSAfMD/wIHAfIB7AHxBwAD6wwAAvQDFAL0CQAB9AHyARQB7wH0CQAB8gHsAfcB7AHyAf8B
+ 8AHsAe8B7AHzCAAD6wwAAfQFFAH0CgAD9AH/CgAB/wHxAfcC6wHsAe8B8QH/CAAF6wsAB/Q4AAH0AQkE
+ tAG8AfQNAAH0AbsCtAG7AfQjAAH/AbwBtAG1AQkC8AEJAbUBtAG8Af8CAAjrAa4BtAEJAvQB8AG0AbwE
+ bQHqAfQB7AHtAf8B7QJtAeoCbQHyBgAB/wH0CQAB/wG7AbQB8Ab/AfABtAG7Af8BAAHrA/8B7wL/AfMB
+ tAb/AbQBkgHvAW0C7AH/AewB7QH/Ae8B6gLsAu8B9AMABPQB8Af0AgABvAG0AfMI/wHzAbQBvAEAAesD
+ /wHvAv8BtQEJBv8B3QEAAfQBbQHvBQAB/wLsAfMGAAH0ARQBkgHsARQB9wQUAbwB9AEAAfQBtAHxCv8B
+ 8QG0Af8B6wb/AbQD/wPrAv8BAAH0AW0B7wH/BQAB9AHsAesGAAH0ARQBkgHzAfcB8wITAQcBvAHzAfQB
+ AAG8AbUM/wG1AbwB6wLvAf8DTAGuA/8B6wT/AQAB9AFtAe8B/wYAAf8BbQHzBAAC9AEUAZID9AHvARQB
+ 6gHwAfQB/wEAAbQBCQX/A20B6wHtAv8BCQG0AesD/wFMAv8BtQEJAv8B6wP/Ad0BAAH0AW0B7wH/BwAB
+ 7QHsAfQCAAP0ARQBkgH0AQAC9AHwAhMB8wH/AQABtAHxBf8BbQb/AfEBtAHrA/8BTAL/AfQBtAL/AesD
+ /wG0AQAB9AFtAe8B/wcAAfQB6wHtAf8BAAH0Ae8B7AEUAZIB9AEAAfQBvAH0AZIBFAG8AfQBAAG0AfEF
+ /wFtBv8B8QG0AesD/wFMA/8BjQG0AfAC9AHwAbQBrgEAAfQBbQHvAf8IAAEHAeoB9AEAAfQB9wIUAZIB
+ 9AEAAfQEFAHwAf8BAAG0AQkF/wFtBv8BCQG0AesC7wH/BUwB8wS0AfcB6wH0Af8BbQHvAf8DAAL/AwAB
+ vAHqAfIBAAL0AfAB7AHvAfQBAAH0AbwB7QHsAQcB9AIAAbwBtQX/AW0G/wG1AbwB6wv/Ae8C/wLrAZIB
+ bQHvAf8DAAH/AfIBBwH/AfQB7AHqAfQDAAT0AgAE9AMAAfQBtAHxBP8BbQX/AfEBtAH/AesD/wHvA/8B
+ 7wP/Ae8C/wHrAZIB6wHqAe8B/wQAAfIBbQHrAW0B6gEHAf8RAAG8AbQB8wP/AfAE/wHzAbQBvAEAAesD
+ /wHvA/8B7wP/Ae8C/wHrAv8B8wHyAf8EAAL/AfEB7QHzAf8SAAH/AbsBtAHwBv8B8AG0AbsB/wEAEOsi
+ AAH/AbwBtAG1AQkC8AEJAbUBtAG8Af8CABDrJAAB9AG8AbUCtAG1AbwB/wQAEOsQABDrCwAB9AHyAfMi
+ AAHrA/8B7wP/Ae8D/wHvA/8DAAH/BgABvAMSAewB9CAAAesD/wHvA/8B7wP/Ae8D/wIAAQcBEgH/BQAB
+ 8QH0Af8B8gHrAZIQABD0AesD/wHvC/8CAAEHARIB/wkAAQcBEgEAAf8I9AP/AwAB9A4UAfQB6wbvAf8F
+ TAH/Au8CAAEHARIB/wgAAf8BkgHrAQAB9AjzAfQC8wL0AQAB9AEUDPQBFAH0AesD/wHvA/8BTAP/AUwD
+ /wIAAQcBEgb/AQABvAHsAW0B7AH0AQAB9AG8ARQB8AH0AxQBbQH0AhQB6gHxAf8B9AQUAfQBFAH0AxQB
+ 9AEUAfQBFAH0AesD/wHvA/8BTAP/AUwD/wIAAQcBEgEHBRIBAAHyAQcBkgHsAfQBAAH0AbwBFAHwAfQB
+ EwFtAQcB8AH0AfABvAEUAfcC9AIUAfQBFAH0ARQB9AEUAfQBFAH0ARQB9AEUAfQB6wP/Ae8D/wFMA/8B
+ TAP/AgABBwESAbwBEgHxA/IEAAHsAfcC9AG8ARQB8AH0AQcBEwFtAfMB9AHtAuoB8AL0AhQB9AEUAfQB
+ FAH0ARQB9AEUAfQBFAH0ARQB9AHrBu8B/wVMAf8C7wH0AQABBwESAf8C7AH/BgAB6wHsAfQB8QHvARQB
+ 8AL0AfABFAGSAfQC8AFtAfQB/wH0BBQB9AEUAfQDFAH0ARQB9AEUAfQB6wP/Ae8L/wEHAesBkgESAv8B
+ 7AHrAfQCAAFtAewB6wESAfEB9AGSAhQB8AH0AeoBkgEUAe0B9AHsAW0BFAG8AvQBFAz0ARQB9AHrA/8B
+ 7wP/Ae8D/wHvBP8BvAHrARIB/wEAAf8B7wFtAfQBAAHxAgcB8wEAAfQB8wH3ARQB8AH0AZIBFAHsAfEB
+ 9AHsAW0B7QH0AQAB9A4UAfQB6wP/Ae8D/wHvA/8B7wP/AgAB/wG8BAAB9wFtBwAB/wz0Af8BABD0EOsI
+ AAHyARIB8iUAEOsEAAHzAfICAAG8ARIB8yUAEOsEAAHzARIC7AESAZImABDrBQAB9AG8AQcBvEcAEOsH
+ AAL0FwAB7wQSAe8EEgHvAewDbQHzAesO/wHrBgAB9ALwAfQGABD0Af8B9AESAbwC9AHrAQcC9AH/AfMC
+ /wGSAusO/wHrBQAB9AHwAhMB8AH0BQAB9A4UAfQBAAH0ARIB8QIAAfQB6wG8BQAB7wFtAesC/wrrAv8B
+ 6wQAAfQB8AQTAfAB9AQAAfQEFAFtAhQG9AEUAfQBAAH0ARIB8QMAAfQB6wG8AQAB/wHvAZIBbQG8AesO
+ /wHrAwAB/wH0AeoBEwLwAhMB8AH0AwAB9AIUARMBBwH0ARMBFAL0ARQBbQL0ARQB9AEAAfQBEgHxBAAB
+ 8wESAfMB/wHvAfcB7AH0AesO/wHrAgAB/wL0AvAC9AHwAhMB8AH0AgAB9AEUARMBvAH0AW0CFAP0ARQB
+ bQH0ARQB9AEAAfQBEgHxBQAB6wHvAwAB6wH3AesO/wHrAQAB/wLzAvQC8wL0AfACEwHwAfQBAAH0ARQB
+ vAX0BRQB7wEUAfQBBwHsARIB8QEAAfQBkgHxAbwBEgK8AvEBbQH3AesC/wrrAv8B6wH/AfQCbQLzAm0D
+ 9AHwAhMB9AEAAfQBFAHvBfQFFAHvARQC9AG8AZIB8gIAAe8C6wHvAQAB8QLrAZIB9AHrDv8B6wEAAfQB
+ 7wEUAm0BFAHvAfQB/wEAAfQB8AEHAfQBAAH0AhQB7wH0AW0CFAP0ARQBbQH0ARQB9AESAfECAAH/AxIB
+ 6gGSAfQB/wEHAesBEgGSAesO/wHrAgAB9AH3AhQB9wH0Af8DAAL0AgAB9AMUAe8B9AETARQC9AEUAW0C
+ 9AEUAfQB7wHsAgAB8wISAgAB7QHvAQcB7AHzAf8B8wHrDv8B6wEAAfQB8wH3AhQB9wHzAfQHAAH0BBQB
+ bQIUBvQBFAH0AQAEEgG8ARIBAAH/AfcBBwHqAfQDAAHrAv8K6wL/AesB/wH0AW0BFALvARQBbQL0BgAB
+ 9A4UAfQBAAESAfIB/wESAfQDEgH3Af8BEgH/AwAB6w7/AesBAAH0AfAB7wL0Au8B9AcAEPQBAAHyARIB
+ 8wESAQABEgEAAf8B7AH/AW0B8wMAAesO/wHrAgAC9AH/AQAC9BkAAf8BbQESAe8BAAESAQAB/wHqAfQB
+ vAHsAfMBAAH0AesO/wHrIgABvAESAf8BAAMSAe0B/wEAAfAB6wESAewQ6xMAAf8I9AH/CQAB/xAAAfIB
+ 9BkAAvQBCQHbBLMB2wEJAvQHAAP0DgAB9AK0Af8GAA/0AwAB9AG6CLMBugH0BgAB9AHxAesB8gH0DAAB
+ /wG0Aq0BtQH/BQAB9AGZC3kBmQH0AwAB9AqzAfQFAAH0AfEB6gHrAW0B8gX0BgAB/wG0Aa0BtAGzAa0B
+ BwUAAfQNeQH0AwAB9AqzAfQEAAH0AfEB6gHvAfQBkgFtAfIB7AETAewB8QH0BAAB/wG1Aq0B8gHwAq0B
+ 8gQAAfQNeQH0AwAB9AqzAfQDAAH0AfEB6gHvA/QBkgFtAvIB9wESAfEB9AMAAfECrQHwAQAB/wG7Aa0B
+ tAH0AwAB9A15AfQDAAH0CrMB9AIAAfQB8QHqAe8F9AGSAW0B8gH0AfcB6wH0AfMBTAEaAfMBrQEJAwAB
+ 8wG0Aa0BtAH/AgAB9A15AfQDAAH0CrMB9AIAAfQC6wf0AZIBbQLyARMB9AEaAkwB8gH0Af8CAAH0AUwB
+ 8QG0Aa0BuwH/AQAB9A15AfQDAAH0CrMB9AIAAfQB8gFtAZIH9AGSAesB8gETAfQB/wNMAfQCAAH0AUwB
+ kwEAAfECrQG8AQAB9A15AfQDAAH0CrMB9AMAAfQB8gFtAZIH9AEHAfcB6wH0AQAB9ANMAvQCTAH/AQAB
+ /wG7Aq0B8wH0DXkB9AMAAfQKswH0BAAB9AHyAW0BkgX0AfIB9wESAfEB9AIAAfQFTAHzAwAB/wG0Aa0B
+ tQH0DHkBmQH0AwAB9AOzBNsDswH0BQAB9AHyAW0BkgP0Ae8BEwHsAfEB9AQAAf8DTAGTBQAB9AG7Af8B
+ 9AF5BvQBGgGZBfQDAAH0AbMBCQb0AQkBswH0BgAB9AHyAW0BkgT0AQcB9AQAAfYBkwRMAZMB/wYAAfQB
+ mQd5ARsB9AcAAfQBugG5AQkBGQLzARkBCQG5AboB9AcAAfQB8gFtBRQB9AMAARsDTAEaAf8BkwFMAW8B
+ 9AUACvQB/wcAAvQBCQHbBLMB2wEJAvQIAAj0AwABbwJMAfIDAAH0ARoB/xgAAf8I9AH/FAAB9AEaAf8M
+ AAFCAU0BPgcAAT4DAAEoAwABQAMAAaADAAEBAQABAQYAAQUWAAP/gQAG/wEAAX8BBwHgAgAC/wIAAQcB
+ 4AIAAYcB4QIAAQcB4AIAAYcB4QIAAR8B+AIAAYcB4AIAAR8B+AIAAYABAQIAAR8B+AYAAR8B+AYAAR8B
+ +AYAAR8B+AIAAQcC8AEAAR8B+AIAAY8B8QHwAQABHwH4AgABhwHhAfABAAEHAeACAAGHAeEB8AEAAQcB
+ 4AIAAYcB4QHwAQABBwHgAfgBHwL/AfABAAb/AfABAAGAAQ8G/wGAAQ8E/wGAAQMBgAEPAQABAQEAAQEB
+ AAEBAYACAAEBAQABAQEAAQEDAAEBAQABAQEAAQEFAAEBAQABAQUAAQEBAAEBAeAEAAEBAQABAQHgBAAB
+ AQEAAQEB4AQAAQEBAAEBAfACAAEBAQABAQEAAQEB8AIAAQEBAAEBAQABAQHwAgABAQEAAQEBAAEBAfAB
+ DwEAAQMBAAEfAQABHwHwAQ8BAAE/AQABHwEAAR8B8AEPAYABPwT/Af4BfwHHAYABAQH/AeABAAHgAR8B
+ wwGAAQEB/wHgAQAB4AEPAeMBnAEBAf8B4AEAAeIBDwHxAZwBAQH/AeABAAH+AQ8B8AGcAgAB4AEAAf4B
+ DwH4AYgCAAHgAQAB/gEPAfwFAAH4AR8BhAFBAQABAQIAAfABPwEAAT8B+AEBAgAB4AF/AQEBHwH4AQEC
+ AAHiAX8BOQEfAfgBAQIAAeIBfwE4AY8B+AEBAgAB4AEPATgBhwH4AQECAAHwAQ8BEQHHAfgBAQEAAQEB
+ +AEPAQEB4wH8AQMB4AEDAf4BfwGDAeMB/gEHAeABBwH/AeEH/wHAB/8BgAT/AoEBPAGPBP8CgQE4AZ8E
+ AAKBAQABnwQAAoEBAQGPBAACgQGABQACgQGABQABgAEBAYABAQQAAYABAQHAAY8EAAGAAQEBwAEPAfgB
+ fwH4AX8BgAEBAeABHwH4AX8B+AF/AYABAQH4AY8E/wGAAQEB+AEPBv8B+AEfBv8B4AEDAfABHwL/AQIB
+ AAHAAQEBwAEHAfgBDwECAQABgAEAAcABBwHgAQMBAgMAAYABAwHgAQMBggEDAgABgAEDAcABAQHAAQMC
+ AAGAAQMBwAEBAcABBwIAAYABAwHAAQEBwAEHAgABgAEDAcABAQHgAQ8CAAGAAQMBwAEBAeABDwIAAYAB
+ AwHAAQEB8AEPAgABwAEHAcABAQHwAR8CAAHAAQcB4AEDAfABHwGAAQAB8AEfAeABAwH4AT8BwAEBAfwB
+ fwH4AQ8B+AE/AeABAwH8AX8B+AEPAfwBPwHwAQcB+AE/AfgBDwb/AfABDwH/AYEE/wHAAQMEAAH8Af8B
+ gAEBBAAB4AEBAYABAQIAAY8BhwHgAQEEAAGHAccB4AEBBAABhwHjAcABAQQAAYcB8QGBAQEEAAGHAfAB
+ gQEBBAABhwH4AYEBAQQAAQcBOAGBAQMEAAEHAQAB4QGHBAABBwGAAv8BgAEBAgABBwGBAv8BgAEBAgAE
+ /wHAAQMCAAT/AfABDwIAAv8CAAH/AeME/wIAAe8BwAT/AgABxwHAAv8EAAHHAfwBgAEHBAABxwH4AYAB
+ AQQAAcABIAGABQABwAEgAYAFAAHAATwGAAFAAfwHAAFgBgABBAEhAQABAQQAAc8BPwGAAQEEAAH/AR8E
+ /wIAAfMBHwT/AgAB8AE/BP8CAAH4AX8I/wIAAf4BfwL/BAAB/AE/BgAB+AEfAgABjAF8AgAB8AEPAgAB
+ jgEgAgAB4AEHAgABjwMAAcABAwIAAY8BnAIAAYABAQIAAQgEAAEBAgABDAEgAgABgAEhAgABMAMAAcAB
+ cwIAATEBgAIAAYABfwIAAYEBBwMAAT8CAAGAAQcCAAGAAX8CAAGFAQcCAAHEA/8BhQECAgAE/wHEARAC
+ AAL/AeABBwH9Af8B/gF/Av8BwAEDAfgB/wH8AT8BAAEBAcABAwHwAX8B+AEfAQABAQHAAQMB4AEDAfAB
+ HwEAAQEBwAEDAcABAQHgAQ8BAAEBAcABAwGAAQAB4QEHAQABAQHAAQMCAAEDAYMBAAEBAcABAwIAAQMB
+ AQEAAQEBwAEDAgABBgEhAQABAQHAAQMBgAEAAYABIAEAAQEBwAEDAcABAAHAAXABAAEBAcABAwHgAQEB
+ 4AH4AQABAQHAAQMB8AEDAcABPwEAAR8BwAEDAfgBAwGAAR8BAAEfAcABAwH8AQMBhwEfAv8B4AEHAv8B
+ jwH/Cw==
+
+
\ No newline at end of file