diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2017-12-04 14:15:48 +0200 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2017-12-04 14:15:48 +0200 |
| commit | a635302e9ae4a8ced135620e355697ccf2a27b52 (patch) | |
| tree | 47b0cdebe8958833f45822970117160ce6c9d237 /Software | |
| parent | c47075cc333329fc6bc93679d847cadcb050436f (diff) | |
| download | Tango-a635302e9ae4a8ced135620e355697ccf2a27b52.tar.gz Tango-a635302e9ae4a8ced135620e355697ccf2a27b52.zip | |
Added Tango.Serialization.
Added Tango.Settings.
Diffstat (limited to 'Software')
22 files changed, 1001 insertions, 4 deletions
diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs new file mode 100644 index 000000000..978b14f30 --- /dev/null +++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Serialization; + + +public static class ObjectExtensions +{ + public static T DeepClone<T>(this T obj) where T : class + { + XmlDataSerializer serializer = new XmlDataSerializer(); + using (MemoryStream ms = new MemoryStream()) + { + serializer.SerializeToStream(obj, ms); + ms.Position = 0; + return serializer.DeserializeFromStream<T>(ms); + } + } +} diff --git a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj index e2341ab62..80804f02e 100644 --- a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj +++ b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj @@ -58,6 +58,7 @@ <Compile Include="ExtensionMethods\EnumExtensions.cs" /> <Compile Include="ExtensionMethods\IMessageExtensions.cs" /> <Compile Include="ExtensionMethods\IParameterizedExtensions.cs" /> + <Compile Include="ExtensionMethods\ObjectExtensions.cs" /> <Compile Include="ExtensionMethods\StringExtensions.cs" /> <Compile Include="Helpers\AssemblyHelper.cs" /> <Compile Include="Helpers\PathHelper.cs" /> @@ -71,5 +72,11 @@ <ItemGroup> <None Include="packages.config" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Tango.Serialization\Tango.Serialization.csproj"> + <Project>{22f87980-e990-4686-be81-be63d562c4d5}</Project> + <Name>Tango.Serialization</Name> + </ProjectReference> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs new file mode 100644 index 000000000..565854804 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Serialization +{ + /// <summary> + /// Represents a data serializer for serializing data using binary formatter. + /// </summary> + public class BinaryDataSerializer : IDataSerializer + { + /// <summary> + /// Serialize object to a file. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="filePath">The full path to the file to write.</param> + public void SerializeToFile<T>(T obj, string filePath) + { + using (FileStream fs = new FileStream(filePath,FileMode.Create)) + { + SerializeToStream(obj, fs); + } + } + + /// <summary> + /// Deserialize object from a file. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="filePath">The full path of the data file.</param> + /// <returns>The resulting object.</returns> + public T DeserializeFromFile<T>(string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Open)) + { + return DeserializeFromStream<T>(fs); + } + } + + /// <summary> + /// Serialize object to stream. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="st">The stream to write.</param> + public void SerializeToStream<T>(T obj, Stream st) + { + BinaryFormatter f = new BinaryFormatter(); + f.Serialize(st, obj); + } + + /// <summary> + /// Deserialize object from stream. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="st">Stream to read from.</param> + /// <returns>The resulting object.</returns> + public T DeserializeFromStream<T>(Stream st) + { + BinaryFormatter f = new BinaryFormatter(); + return (T)f.Deserialize(st); + } + + /// <summary> + /// Returns the serializer full name. + /// </summary> + /// <returns></returns> + public override string ToString() + { + return SerializationHelper.GetSerializerName(this); + } + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs b/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs new file mode 100644 index 000000000..e072827fe --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs @@ -0,0 +1,156 @@ +using System; +using System.Text; +using System.Security.Cryptography; +using System.IO; +using System.Linq; +using System.Security; +using System.Runtime.InteropServices; + +namespace Tango.Serialization +{ + /// <summary> + /// Represents a helper class for encryption and decryption of plain text. + /// </summary> + internal static class CryptographyHelper + { + private static SecureString passkey; + + /// <summary> + /// Initializes the <see cref="CryptographyHelper"/> class. + /// </summary> + static CryptographyHelper() + { + passkey = new SecureString(); + passkey.AppendChar('S'); + passkey.AppendChar('@'); + passkey.AppendChar('Y'); + passkey.AppendChar('!'); + } + + // This constant is used to determine the keysize of the encryption algorithm in bits. + // We divide this by 8 within the code below to get the equivalent number of bytes. + private const int Keysize = 256; + + // This constant determines the number of iterations for the password bytes generation function. + private const int DerivationIterations = 1000; + + /// <summary> + /// Encrypts the specified plain text. + /// </summary> + /// <param name="plainText">The plain text.</param> + /// <returns></returns> + public static string Encrypt(string plainText) + { + // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text + // so that the same Salt and IV values can be used when decrypting. + var saltStringBytes = Generate256BitsOfRandomEntropy(); + var ivStringBytes = Generate256BitsOfRandomEntropy(); + var plainTextBytes = Encoding.UTF8.GetBytes(plainText); + using (var password = new Rfc2898DeriveBytes(ConvertSecureStringToString(passkey), saltStringBytes, DerivationIterations)) + { + var keyBytes = password.GetBytes(Keysize / 8); + using (var symmetricKey = new RijndaelManaged()) + { + symmetricKey.BlockSize = 256; + symmetricKey.Mode = CipherMode.CBC; + symmetricKey.Padding = PaddingMode.PKCS7; + using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes)) + { + using (var memoryStream = new MemoryStream()) + { + using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) + { + cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); + cryptoStream.FlushFinalBlock(); + // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes. + var cipherTextBytes = saltStringBytes; + cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray(); + cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray(); + memoryStream.Close(); + cryptoStream.Close(); + return Convert.ToBase64String(cipherTextBytes); + } + } + } + } + } + } + + /// <summary> + /// Decrypts the specified cipher text. + /// </summary> + /// <param name="cipherText">The cipher text.</param> + /// <returns></returns> + public static string Decrypt(string cipherText) + { + // Get the complete stream of bytes that represent: + // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText] + var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText); + // Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes. + var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray(); + // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes. + var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray(); + // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string. + var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray(); + + using (var password = new Rfc2898DeriveBytes(ConvertSecureStringToString(passkey), saltStringBytes, DerivationIterations)) + { + var keyBytes = password.GetBytes(Keysize / 8); + using (var symmetricKey = new RijndaelManaged()) + { + symmetricKey.BlockSize = 256; + symmetricKey.Mode = CipherMode.CBC; + symmetricKey.Padding = PaddingMode.PKCS7; + using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)) + { + using (var memoryStream = new MemoryStream(cipherTextBytes)) + { + using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) + { + var plainTextBytes = new byte[cipherTextBytes.Length]; + var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); + memoryStream.Close(); + cryptoStream.Close(); + return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); + } + } + } + } + } + } + + /// <summary> + /// Generate256s the bits of random entropy. + /// </summary> + /// <returns></returns> + private static byte[] Generate256BitsOfRandomEntropy() + { + var randomBytes = new byte[32]; // 32 Bytes will give us 256 bits. + using (var rngCsp = new RNGCryptoServiceProvider()) + { + // Fill the array with cryptographically secure random bytes. + rngCsp.GetBytes(randomBytes); + } + return randomBytes; + } + + /// <summary> + /// Converts the secure string to string. + /// </summary> + /// <param name="value">The value.</param> + /// <returns></returns> + private static String ConvertSecureStringToString(SecureString value) + { + IntPtr valuePtr = IntPtr.Zero; + try + { + valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value); + return Marshal.PtrToStringUni(valuePtr); + } + finally + { + Marshal.ZeroFreeGlobalAllocUnicode(valuePtr); + } + } + } +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs new file mode 100644 index 000000000..93465967e --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Serialization +{ + /// <summary> + /// Represent an interface for creating a custom data serializer. + /// </summary> + public interface IDataSerializer + { + /// <summary> + /// Serialize object to a file. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="filePath">The full path to the file to write.</param> + void SerializeToFile<T>(T obj, String filePath); + + /// <summary> + /// Deserialize object from a file. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="filePath">The full path of the data file.</param> + /// <returns>The resulting object.</returns> + T DeserializeFromFile<T>(String filePath); + + /// <summary> + /// Serialize object to stream. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="st">The stream to write.</param> + void SerializeToStream<T>(T obj, Stream st); + + /// <summary> + /// Deserialize object from stream. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="st">Stream to read from.</param> + /// <returns>The resulting object.</returns> + T DeserializeFromStream<T>(Stream st); + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs new file mode 100644 index 000000000..674f68289 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs @@ -0,0 +1,87 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Serialization +{ + /// <summary> + /// Represents a data serializer for serializing data using the light weight textual Json format. + /// </summary> + public class JsonDataSerializer : IDataSerializer + { + + /// <summary> + /// Serialize object to a file. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="filePath">The full path to the file to write.</param> + public void SerializeToFile<T>(T obj, string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Create)) + { + SerializeToStream<T>(obj, fs); + } + } + + /// <summary> + /// Deserialize object from a file. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="filePath">The full path of the data file.</param> + /// <returns>The resulting object.</returns> + public T DeserializeFromFile<T>(string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Open)) + { + return DeserializeFromStream<T>(fs); + } + } + + /// <summary> + /// Serialize object to stream. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="st">The stream to write.</param> + public void SerializeToStream<T>(T obj, Stream st) + { + JsonSerializer serializer = new JsonSerializer(); + using (StreamWriter streamReader = new StreamWriter(st)) + { + serializer.Serialize(streamReader, obj); + } + } + + /// <summary> + /// Deserialize object from stream. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="st">Stream to read from.</param> + /// <returns>The resulting object.</returns> + public T DeserializeFromStream<T>(Stream st) + { + JsonSerializer serializer = new JsonSerializer(); + T data; + using (StreamReader streamReader = new StreamReader(st)) + { + data = (T)serializer.Deserialize(streamReader, typeof(T)); + } + return data; + } + + /// <summary> + /// Returns the serializer full name. + /// </summary> + /// <returns></returns> + public override string ToString() + { + return SerializationHelper.GetSerializerName(this); + } + + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..f3c038f0e --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Tango - Serialization Components")] +[assembly: ComVisible(false)]
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs b/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs new file mode 100644 index 000000000..2d00c8621 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Serialization +{ + /// <summary> + /// Contains a collection of IDataSerializer related helper methods. + /// </summary> + public static class SerializationHelper + { + /// <summary> + /// Gets a list of all IDataSerializer implemented types. + /// </summary> + /// <returns></returns> + public static List<Type> GetSerializersTypes() + { + var type = typeof(IDataSerializer); + var serializers = System.Reflection.Assembly.GetAssembly(type).GetTypes().Where(x => type.IsAssignableFrom(x) && !x.IsInterface); + return serializers.ToList(); + } + + /// <summary> + /// Gets a list of all IDataSerializer implemented instances. + /// </summary> + /// <returns></returns> + public static List<IDataSerializer> GetSerializersInstances() + { + var types = GetSerializersTypes(); + + List<IDataSerializer> serializers = new List<IDataSerializer>(); + + foreach (var type in types) + { + var instance = Activator.CreateInstance(type) as IDataSerializer; + serializers.Add(instance); + } + + return serializers; + } + + /// <summary> + /// Returns a serializer instance by type name. + /// </summary> + /// <param name="name">Name of IDataSerializer type.</param> + /// <returns></returns> + public static IDataSerializer GetSerializerByName(String name) + { + var types = GetSerializersTypes(); + var type = types.SingleOrDefault(x => x.Name == name); + return Activator.CreateInstance(type) as IDataSerializer; + } + + /// <summary> + /// Returns the name of the specified IDataSerializer. + /// </summary> + /// <param name="serializer">The specified IDataSerializer.</param> + /// <returns></returns> + public static String GetSerializerName(IDataSerializer serializer) + { + return serializer.GetType().Name; + } + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj b/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj new file mode 100644 index 000000000..453d317f5 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{22F87980-E990-4686-BE81-BE63D562C4D5}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Tango.Serialization</RootNamespace> + <AssemblyName>Tango.Serialization</AssemblyName> + <TargetFrameworkVersion>v4.6</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Google.Protobuf, Version=3.5.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> + <HintPath>..\packages\Google.Protobuf.3.5.0\lib\net45\Google.Protobuf.dll</HintPath> + </Reference> + <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="..\Versioning\GlobalVersionInfo.cs"> + <Link>GlobalVersionInfo.cs</Link> + </Compile> + <Compile Include="BinaryDataSerializer.cs" /> + <Compile Include="CryptographyHelper.cs" /> + <Compile Include="IDataSerializer.cs" /> + <Compile Include="JsonDataSerializer.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="SerializationHelper.cs" /> + <Compile Include="XmlDataSerializer.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs new file mode 100644 index 000000000..0453e9120 --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; + +namespace Tango.Serialization +{ + /// <summary> + /// Represents a data serializer for serializing data using standard xml serializer. + /// </summary> + public class XmlDataSerializer : IDataSerializer + { + + /// <summary> + /// Serialize object to a file. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="filePath">The full path to the file to write.</param> + public void SerializeToFile<T>(T obj, string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Create)) + { + SerializeToStream<T>(obj, fs); + } + } + + /// <summary> + /// Serialize object to encrypted file. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="filePath">The full path to the file to write.</param> + public void SerializeToEncryptedFile<T>(T obj, string filePath) + { + var plainText = SerializeToString(obj); + var cypherText = CryptographyHelper.Encrypt(plainText); + File.WriteAllText(filePath, cypherText); + } + + /// <summary> + /// Serialize object to encrypted string. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + public String SerializeToEncryptedString<T>(T obj) + { + var plainText = SerializeToString(obj); + var cypherText = CryptographyHelper.Encrypt(plainText); + return cypherText; + } + + /// <summary> + /// Deserialize object from encrypted file. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="filePath">The full path of the data file.</param> + /// <returns>The resulting object.</returns> + public T DeserializeFromEncryptedFile<T>(string filePath) + { + var cypherText = File.ReadAllText(filePath); + var plainText = CryptographyHelper.Decrypt(cypherText); + return DeserializeFromString<T>(plainText); + } + + /// <summary> + /// Deserialize object from encrypted string. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <returns>The resulting object.</returns> + public T DeserializeFromEncryptedString<T>(string encyptedString) + { + var plainText = CryptographyHelper.Decrypt(encyptedString); + return DeserializeFromString<T>(plainText); + } + + /// <summary> + /// Deserialize object from a file. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="filePath">The full path of the data file.</param> + /// <returns>The resulting object.</returns> + public T DeserializeFromFile<T>(string filePath) + { + using (FileStream fs = new FileStream(filePath, FileMode.Open)) + { + return DeserializeFromStream<T>(fs); + } + } + + + /// <summary> + /// Serialize object to stream. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <param name="st">The stream to write.</param> + public void SerializeToStream<T>(T obj, Stream st) + { + XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround. + f.Serialize(st, obj); + } + + /// <summary> + /// Serialize object to string. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <returns></returns> + public String SerializeToString<T>(T obj) + { + XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround. + + using (StringWriter textWriter = new StringWriter()) + { + f.Serialize(textWriter, obj); + return textWriter.ToString(); + } + } + + /// <summary> + /// Deserialize object from stream. + /// </summary> + /// <typeparam name="T">Type of object to deserialize.</typeparam> + /// <param name="st">Stream to read from.</param> + /// <returns>The resulting object.</returns> + public T DeserializeFromStream<T>(Stream st) + { + XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround. + return (T)f.Deserialize(st); + } + + /// <summary> + /// Deserialize object from string. + /// </summary> + /// <typeparam name="T">Type of specified object.</typeparam> + /// <param name="obj">The specified object.</param> + /// <returns></returns> + public T DeserializeFromString<T>(String str) + { + XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround. + using (TextReader reader = new StringReader(str)) + { + return (T)f.Deserialize(reader); + } + } + + /// <summary> + /// Returns the serializer full name. + /// </summary> + /// <returns></returns> + public override string ToString() + { + return SerializationHelper.GetSerializerName(this); + } + + } +} diff --git a/Software/Visual_Studio/Tango.Serialization/packages.config b/Software/Visual_Studio/Tango.Serialization/packages.config new file mode 100644 index 000000000..dbb73d29f --- /dev/null +++ b/Software/Visual_Studio/Tango.Serialization/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Google.Protobuf" version="3.5.0" targetFramework="net46" /> + <package id="Newtonsoft.Json" version="10.0.3" targetFramework="net46" /> +</packages>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Settings/DataBase.cs b/Software/Visual_Studio/Tango.Settings/DataBase.cs new file mode 100644 index 000000000..1a504d0ac --- /dev/null +++ b/Software/Visual_Studio/Tango.Settings/DataBase.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Settings +{ + [Serializable] + public class DataBase + { + public String SQLServerAddress { get; set; } + + public DataBase() + { + SQLServerAddress = "localhost\\SQLEXPRESS"; + } + } +} diff --git a/Software/Visual_Studio/Tango.Settings/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.Settings/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..d5b3aa0ae --- /dev/null +++ b/Software/Visual_Studio/Tango.Settings/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Tango - Global Settings")] +[assembly: ComVisible(false)]
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Settings/SettingsCollection.cs b/Software/Visual_Studio/Tango.Settings/SettingsCollection.cs new file mode 100644 index 000000000..c6f98f187 --- /dev/null +++ b/Software/Visual_Studio/Tango.Settings/SettingsCollection.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Serialization; + +namespace Tango.Settings +{ + [Serializable] + public class SettingsCollection + { + public DataBase DataBase { get; set; } + + /// <summary> + /// Initializes a new instance of the <see cref="SettingsCollection"/> class. + /// </summary> + public SettingsCollection() + { + DataBase = new DataBase(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Settings/SettingsManager.cs b/Software/Visual_Studio/Tango.Settings/SettingsManager.cs new file mode 100644 index 000000000..8455cb91d --- /dev/null +++ b/Software/Visual_Studio/Tango.Settings/SettingsManager.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Logging; +using Tango.Serialization; + +namespace Tango.Settings +{ + /// <summary> + /// Represents a settings manager for loading and saving application settings. + /// </summary> + public static class SettingsManager + { + /// <summary> + /// Gets or sets a value indicating whether the settings manager is initialized. + /// </summary> + public static bool IsInitialized { get; private set; } + + /// <summary> + /// Gets or sets the default settings. + /// </summary> + /// <value> + /// The default. + /// </value> + public static SettingsCollection Default { get; private set; } + + /// <summary> + /// Gets or sets the default file path. + /// </summary> + /// <value> + /// The default file path. + /// </value> + public static String DefaultFilePath { get; private set; } + + /// <summary> + /// Gets or sets the default folder for application settings. + /// </summary> + public static String DefaultFolder { get; private set; } + + /// <summary> + /// Saves application settings to XML file. + /// </summary> + /// <param name="filePath">The path to the XML file.</param> + /// <param name="stCollection">The instance of the SettingsCollection to save.</param> + public static void SaveToXML(String filePath, SettingsCollection stCollection) + { + LogManager.Log("Saving application configuration to " + "'" + filePath + "'"); + XmlDataSerializer serializer = new XmlDataSerializer(); + serializer.SerializeToFile<SettingsCollection>(stCollection, filePath); + } + + /// <summary> + /// Loads application settings from XML file. + /// </summary> + /// <param name="filePath">The file path.</param> + /// <returns></returns> + public static SettingsCollection LoadFromXML(String filePath) + { + LogManager.Log("Loading application configuration from " + "'" + filePath + "'"); + XmlDataSerializer serialier = new XmlDataSerializer(); + return serialier.DeserializeFromFile<SettingsCollection>(filePath); + } + + /// <summary> + /// Saves the default settings. + /// </summary> + public static void SaveDefaultSettings() + { + SaveToXML(DefaultFilePath, Default); + } + + /// <summary> + /// Restores to default. + /// </summary> + public static void RestoreToDefault() + { + Default = new SettingsCollection(); + SaveDefaultSettings(); + } + + /// <summary> + /// Initializes the <see cref="SettingsManager"/> class. + /// </summary> + static SettingsManager() + { + Initialize(); + } + + /// <summary> + /// Initializes the settings manager. + /// </summary> + private static void Initialize() + { + if (IsInitialized) return; + + LogManager.Log("Initializing application configuration..."); + + DefaultFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Settings.xml"); + DefaultFolder = Path.GetDirectoryName(DefaultFilePath); + + try + { + Default = LoadFromXML(DefaultFilePath); + } + catch (Exception ex) + { + LogManager.Log(ex, "Could not load application configuration."); + + try + { + LogManager.Log("Creating application configuration directory structure..."); + Directory.CreateDirectory(DefaultFolder); + } + catch (Exception ex2) + { + LogManager.Log(ex2, "Could not generate directory structure."); + } + } + + if (Default == null) + { + Default = new SettingsCollection(); + + try + { + LogManager.Log("Generating default configuration file."); + SaveToXML(DefaultFilePath, Default); + } + catch (Exception ex) + { + LogManager.Log(ex, "Could not generate default configuration file."); + } + } + else + { + LogManager.Log("Application configuration loaded successfully."); + } + + IsInitialized = true; + } + } +} diff --git a/Software/Visual_Studio/Tango.Settings/Tango.Settings.csproj b/Software/Visual_Studio/Tango.Settings/Tango.Settings.csproj new file mode 100644 index 000000000..2916075bf --- /dev/null +++ b/Software/Visual_Studio/Tango.Settings/Tango.Settings.csproj @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Tango.Settings</RootNamespace> + <AssemblyName>Tango.Settings</AssemblyName> + <TargetFrameworkVersion>v4.6</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="..\Versioning\GlobalVersionInfo.cs"> + <Link>GlobalVersionInfo.cs</Link> + </Compile> + <Compile Include="DataBase.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="SettingsCollection.cs" /> + <Compile Include="SettingsManager.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.Logging\Tango.Logging.csproj"> + <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project> + <Name>Tango.Logging</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.Serialization\Tango.Serialization.csproj"> + <Project>{22f87980-e990-4686-be81-be63d562c4d5}</Project> + <Name>Tango.Serialization</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs b/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs index 2cd9e2d41..ae39e118b 100644 --- a/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs +++ b/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using remote = Tango.DAL.Remote.DB; using local = Tango.DAL.Local.DB; +using Tango.Settings; namespace Tango.Synchronization.Remote { @@ -12,7 +13,7 @@ namespace Tango.Synchronization.Remote { public static void Synchronize(String sqliteDbFile, String serialNumber) { - using (var remoteDB = new remote.RemoteDB("LOCALHOST\\SQLEXPRESS", false)) + using (var remoteDB = new remote.RemoteDB(SettingsManager.Default.DataBase.SQLServerAddress, false)) { using (var localDB = new local.LocalDB(sqliteDbFile)) { diff --git a/Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj b/Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj index 30208539c..009f79047 100644 --- a/Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj +++ b/Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj @@ -96,6 +96,10 @@ <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project> <Name>Tango.Logging</Name> </ProjectReference> + <ProjectReference Include="..\Tango.Settings\Tango.Settings.csproj"> + <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project> + <Name>Tango.Settings</Name> + </ProjectReference> </ItemGroup> <ItemGroup /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> diff --git a/Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs index a04e5605d..e9fa5e6ba 100644 --- a/Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs +++ b/Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs @@ -2,6 +2,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Tango.DAL; using System.Linq; +using Tango.Settings; namespace Tango.UnitTesting { @@ -14,7 +15,7 @@ namespace Tango.UnitTesting { String guid = Guid.NewGuid().ToString(); - using (var db = new DAL.Remote.DB.RemoteDB("LOCALHOST\\SQLEXPRESS", false)) + using (var db = new DAL.Remote.DB.RemoteDB(SettingsManager.Default.DataBase.SQLServerAddress, false)) { var action = new DAL.Remote.DB.ACTION(); action.CODE = 1; @@ -27,7 +28,7 @@ namespace Tango.UnitTesting db.SaveChanges(); } - using (var db = new DAL.Remote.DB.RemoteDB("LOCALHOST\\SQLEXPRESS", false)) + using (var db = new DAL.Remote.DB.RemoteDB(SettingsManager.Default.DataBase.SQLServerAddress, false)) { var action = db.ACTIONS.Single(x => x.GUID == guid); db.ACTIONS.Remove(action); diff --git a/Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs index 26d197bcf..3f39211cf 100644 --- a/Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs +++ b/Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using remote = Tango.DAL.Remote.DB; using local = Tango.DAL.Local.DB; using Tango.Synchronization.Remote; +using Tango.Settings; namespace Tango.UnitTesting { @@ -27,7 +28,7 @@ namespace Tango.UnitTesting [TestMethod] public void Generate_Demo_Remote_Machine() { - using (var remoteDB = new remote.RemoteDB("LOCALHOST\\SQLEXPRESS", false)) + using (var remoteDB = new remote.RemoteDB(SettingsManager.Default.DataBase.SQLServerAddress, false)) { var organization = new remote.ORGANIZATION() { diff --git a/Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj b/Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj index fd9d04b34..79dab4c0d 100644 --- a/Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj +++ b/Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj @@ -112,6 +112,10 @@ <Project>{40073806-914e-4e78-97ab-fa9639308ebe}</Project> <Name>Tango.Protobuf</Name> </ProjectReference> + <ProjectReference Include="..\Tango.Settings\Tango.Settings.csproj"> + <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project> + <Name>Tango.Settings</Name> + </ProjectReference> <ProjectReference Include="..\Tango.SharedUI\Tango.SharedUI.csproj"> <Project>{ac489889-6e50-4f16-9dba-ff4c6f9ec72b}</Project> <Name>Tango.SharedUI</Name> diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 15cc293c6..21533bfd7 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -63,6 +63,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.DAL.Local", "Tango.DA EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.MachineDesigner.UI", "Utilities\Tango.MachineDesigner.UI\Tango.MachineDesigner.UI.csproj", "{116DFDB0-7681-46FE-8BAD-FE8AE09BB076}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Settings", "Tango.Settings\Tango.Settings.csproj", "{D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Serialization", "Tango.Serialization\Tango.Serialization.csproj", "{22F87980-E990-4686-BE81-BE63D562C4D5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -335,6 +339,30 @@ Global {116DFDB0-7681-46FE-8BAD-FE8AE09BB076}.Release|x64.Build.0 = Release|Any CPU {116DFDB0-7681-46FE-8BAD-FE8AE09BB076}.Release|x86.ActiveCfg = Release|Any CPU {116DFDB0-7681-46FE-8BAD-FE8AE09BB076}.Release|x86.Build.0 = Release|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|x64.ActiveCfg = Debug|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|x64.Build.0 = Debug|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|x86.ActiveCfg = Debug|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|x86.Build.0 = Debug|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|Any CPU.Build.0 = Release|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|x64.ActiveCfg = Release|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|x64.Build.0 = Release|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|x86.ActiveCfg = Release|Any CPU + {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|x86.Build.0 = Release|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|x64.ActiveCfg = Debug|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|x64.Build.0 = Debug|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|x86.ActiveCfg = Debug|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|x86.Build.0 = Debug|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|Any CPU.Build.0 = Release|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|x64.ActiveCfg = Release|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|x64.Build.0 = Release|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|x86.ActiveCfg = Release|Any CPU + {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE |
