Winify – Rev 14

Subversion Repositories:
Rev:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using Servers;
using Winify.Utilities;

namespace Winify.Servers.Serialization
{
    public static class ServersSerialization
    {
        #region Public Enums, Properties and Fields

        /// <summary>
        ///     Cached XML serializer for the configuration.
        /// </summary>
        public static XmlSerializer XmlSerializer { get; } = new XmlSerializer(typeof(global::Servers.Servers));

        #endregion

        #region Public Methods

        public static async Task<ServersSerializationState> Deserialize(string file)
        {
            var validationEventArgs = new List<ValidationEventArgs>();

            void XmlReaderSettingsValidationEventHandler(object sender, ValidationEventArgs e)
            {
                validationEventArgs.Add(e);
            }

            global::Servers.Servers servers;

            var settings = new XmlReaderSettings();

            try
            {
                settings.Async = true;
                settings.DtdProcessing = DtdProcessing.Parse;
                settings.ValidationType = ValidationType.Schema;

                settings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema |
                                           XmlSchemaValidationFlags.ProcessSchemaLocation |
                                           XmlSchemaValidationFlags.ReportValidationWarnings |
                                           XmlSchemaValidationFlags.ProcessIdentityConstraints;

                settings.Schemas = new XmlSchemaSet();

                settings.ValidationEventHandler += XmlReaderSettingsValidationEventHandler;

                settings.Schemas.Add("urn:winify-servers-schema", "Servers.xsd");

                using (var fileStream =
                    new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    using (var xmlReader = XmlReader.Create(fileStream,
                        settings))
                    {
                        var stringBuilder = new StringBuilder();

                        using (var stringWriter = new StringWriter(stringBuilder))
                        {
                            while (await xmlReader.ReadAsync())
                            {
                                await stringWriter.WriteAsync(await xmlReader.ReadOuterXmlAsync());
                            }
                        }

                        using (var stringReader = new StringReader(stringBuilder.ToString()))
                        {
                            servers =
                                (global::Servers.Servers) XmlSerializer
                                    .Deserialize(stringReader);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                return new ServersSerializationFailure(ex, validationEventArgs);
            }
            finally
            {
                settings.ValidationEventHandler -=
                    XmlReaderSettingsValidationEventHandler;
            }

            // Decrypt password.
            var deviceId = Miscellaneous.GetMachineGuid();
            var protectedServers = new global::Servers.Servers
            {
                Server = new BindingListWithCollectionChanged<Server>()
            };
            foreach (var server in servers.Server)
            {
                var unarmored = Convert.FromBase64String(server.Password);
                var decrypted = Encoding.UTF8.GetString(AES.Decrypt(unarmored, deviceId));

                protectedServers.Server.Add(new Server(server.Name, server.Url, server.Username, decrypted));
            }

            return new ServersSerializationSuccess(protectedServers, validationEventArgs);
        }

        public static async Task<ServersSerializationState> Serialize(global::Servers.Servers servers, string file)
        {
            try
            {
                using (var memoryStream = new MemoryStream())
                {
                    using (var xmlWriter =
                        XmlWriter.Create(memoryStream,
                            new XmlWriterSettings
                            {
                                Async = true,
                                Indent = true,
                                IndentChars = "    ",
                                OmitXmlDeclaration = false
                            }))
                    {
                        await xmlWriter.WriteDocTypeAsync("Servers",
                            null,
                            null,
                            "<!ATTLIST Servers xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>");

                        // Encrypt password for all servers.
                        var deviceId = Miscellaneous.GetMachineGuid();
                        var protectedServers = new global::Servers.Servers
                        {
                            Server = new BindingListWithCollectionChanged<Server>()
                        };
                        foreach (var server in servers.Server)
                        {
                            var encrypted = AES.Encrypt(Encoding.UTF8.GetBytes(server.Password), deviceId);
                            var armored = Convert.ToBase64String(encrypted);

                            protectedServers.Server.Add(new Server(server.Name, server.Url, server.Username, armored));
                        }

                        XmlSerializer.Serialize(xmlWriter, protectedServers);

                        using (var fileStream =
                            new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
                        {
                            memoryStream.Position = 0L;

                            await memoryStream.CopyToAsync(fileStream);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                return new ServersSerializationFailure(ex);
            }

            return new ServersSerializationSuccess();
        }

        public static async Task<ServersSerializationState> Serialize(global::Servers.Servers servers,
                                                                      MemoryStream outputStream)
        {
            try
            {
                using (var memoryStream = new MemoryStream())
                {
                    using (var xmlWriter =
                        XmlWriter.Create(memoryStream,
                            new XmlWriterSettings
                            {
                                Async = true,
                                Indent = true,
                                IndentChars = "    ",
                                OmitXmlDeclaration = false
                            }))
                    {
                        await xmlWriter.WriteDocTypeAsync("Servers",
                            null,
                            null,
                            "<!ATTLIST Servers xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>");

                        // Encrypt password for all servers.
                        var deviceId = Miscellaneous.GetMachineGuid();
                        var protectedServers = new global::Servers.Servers
                        {
                            Server = new BindingListWithCollectionChanged<Server>()
                        };
                        foreach (var server in servers.Server)
                        {
                            var encrypted = AES.Encrypt(Encoding.UTF8.GetBytes(server.Password), deviceId);
                            var armored = Convert.ToBase64String(encrypted);

                            protectedServers.Server.Add(new Server(server.Name, server.Url, server.Username, armored));
                        }

                        XmlSerializer.Serialize(xmlWriter, protectedServers);

                        memoryStream.Position = 0L;

                        await memoryStream.CopyToAsync(outputStream);
                    }
                }
            }
            catch (Exception ex)
            {
                return new ServersSerializationFailure(ex);
            }

            return new ServersSerializationSuccess();
        }

        #endregion
    }
}

Generated by GNU Enscript 1.6.5.90.