using log4net;
using log4net.Core;
using Renci.SshNet;
using Renci.SshNet.Security;
using SSH_Test;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Management.Automation; //for powershell
using System.Collections.ObjectModel;

using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Win32.SafeHandles;
using System.Diagnostics.Eventing.Reader;

namespace SSH_Test
{
    public class Utilities
    {

        public static ILog log;
        public Utilities(ILog Log)
        {
            log = Log;
         
        }
        public static string RunaTask(cTask currentTask, Profile profile, cConInfo conInfo, Aes aes)
        {
            
            string result = "-------------------------------------------------------------------------\n";
            result += string.Format("{0:s} Task {1}: {2}, profile: {3} \n", DateTime.Now, currentTask.iTaskNum, currentTask.sTaskDescription, currentTask.sProfile);
            result += "-------------------------------------------------------------------------\n";
            cHostInfo hostInfo = new cHostInfo();
            log.Info(string.Format("Run task: {0}, profile: {1}", currentTask.sTaskDescription, currentTask.sProfile));
            
            //foreach (var c in currentTask.dParameters)
            //    log.Info(string.Format("Parameter {0}: {1}", c.Key, c.Value));

            switch (profile.ProfileType)
            {
                case "SSH":
                    hostInfo.host = currentTask.dParameters["{IP Address}"];
                    hostInfo.username = currentTask.dParameters["{User Name}"];
                    hostInfo.password = currentTask.dParameters["{Password}"];
                    hostInfo.device = currentTask.sTaskDevice.ToString();
                    hostInfo.dParameters = new Dictionary<string, string>();
                    hostInfo.Commands = profile.ProfileCommands;



                    try
                    {
                        Thread thread1 = new Thread(new ParameterizedThreadStart(fSSH));
                        hostInfo.TftpIP = conInfo.sTftpIP;
                        hostInfo.SftpIP = conInfo.sTftpIP;
                        hostInfo.SftpPassword = conInfo.sTftpPassword;
                        hostInfo.SftpUsername = conInfo.sTftpUsername;
                        thread1.Start(hostInfo);
                    }
                    catch (Exception ex1)
                    {
                        log.Error(ex1);
                    }

                    break;

                case "SSH_Catalyst":

                    hostInfo.host = currentTask.dParameters["{IP Address}"];
                    hostInfo.username = currentTask.dParameters["{User Name}"];
                    hostInfo.password = currentTask.dParameters["{Password}"];
                    hostInfo.device = currentTask.sTaskDevice.ToString();
                    hostInfo.dParameters = new Dictionary<string, string>();
                    hostInfo.Commands = profile.ProfileCommands;
                    try
                    {
                        Thread thread2 = new Thread(new ParameterizedThreadStart(fSSH_Catalyst));
                        hostInfo.TftpIP = conInfo.sTftpIP;
                        hostInfo.SftpIP = conInfo.sTftpIP;
                        hostInfo.SftpPassword = conInfo.sTftpPassword;
                        hostInfo.SftpUsername = conInfo.sTftpUsername;
                        thread2.Start(hostInfo);
                    }
                    catch (Exception ex1)
                    {
                        log.Error(ex1);

                    }


                    break;


                case "RAC9":
                    int i = 0;
                    string command = "";


                    //if (!conInfo.bisLocal)
                    //{
                    //    command = " --nocertwarn -r " + conInfo.sIDracIP + " -u " + conInfo.sIDracUsername + " -p " + conInfo.sIDracPassword + " ";
                    //}

                    foreach (string c in profile.ProfileCommands)
                    {
                        Process process = new Process();
                        process.StartInfo.FileName = "racadm.exe";
                        process.StartInfo.UseShellExecute = false; // Required for 'runas' verb
                        process.StartInfo.Verb = "runas"; // Request administrator privileges
                        process.StartInfo.WorkingDirectory = Environment.CurrentDirectory; // current working dir
                        process.StartInfo.RedirectStandardOutput = true;

                        //log.Info(string.Format("From RAC9 try to run: {0}", c));
                        log.Info(string.Format("From RAC9 try to run: {0}", c));
                        try
                        {

                            string tempfile = DateTime.Now.ToString().Replace(":", "").Replace(" ", "") + ".txt";

                            process.StartInfo.Arguments = command + " " + c;

                            process.Start();
                            string temp = process.StandardOutput.ReadToEnd();
                            log.Info(string.Format("From RAC9 {0}: {1}", currentTask.sTaskDevice.ToString(), result));
                            result += temp;
                            process.WaitForExit();


                        }
                        catch (Win32Exception ex)
                        {
                            log.Error(string.Format($"Error: {ex.Message}. The user likely declined the UAC prompt."));

                        }
                    }
                    break;

                case "CMD":

                    foreach (string c in profile.ProfileCommands)
                    {
                        command = " ";
                        i = 0;

                        //apply values to parameters accordingly
                        try
                        {
                            if (profile.ProfileParameters.Length > 0)
                            {
                                string ee = c;
                                foreach (string ss in profile.ProfileParameters)
                                {

                                    ee = ee.Replace(ss, currentTask.dParameters[ss]);

                                }

                                //log.Info(string.Format("{0} => {1}", c, ee));
                                command += ee;

                            }
                            else
                                command = c;

                        }
                        catch (Exception ex)
                        { }


                        //log.Info(command);



                        // create a process
                        Process process = new Process();
                        process.StartInfo.FileName = "cmd.exe";
                        process.StartInfo.UseShellExecute = false; // Required for 'runas' verb
                        process.StartInfo.Verb = "runas"; // Request administrator privileges
                        process.StartInfo.WorkingDirectory = Environment.CurrentDirectory; // current working dir
                        process.StartInfo.RedirectStandardOutput = true;
                        process.StartInfo.RedirectStandardInput = true;

                        try
                        {

                            process.StartInfo.Arguments = string.Format(" /c {0}", command);
                            //log.Info(string.Format("command to run: {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments));

                            process.Start();

                            StreamReader sr = process.StandardOutput;
                            StreamWriter si = process.StandardInput;
                            si.Write("\n");
                            string temp = sr.ReadToEnd();


                            log.Info(string.Format("From CMD {0}: {1}", currentTask.sTaskDevice.ToString(), temp));
                            result += temp;
                            process.WaitForExit();


                        }
                        catch (Win32Exception ex)
                        {
                            log.Error(ex);
                        }
                        i++;
                    }
                    break;

                case "Powershell":

                    foreach (string c in profile.ProfileCommands)
                    {
                        command = "";
                        i = 0;

                        //apply values to parameters accordingly
                        try
                        {
                            if (profile.ProfileParameters.Length > 0)
                            {
                                string ee = c;
                                foreach (string ss in profile.ProfileParameters)
                                {

                                    ee = ee.Replace(ss, currentTask.dParameters[ss]);

                                }
                                //log.Info(string.Format("{0} => {1}", c, ee));
                                command += ee;

                            }
                            else
                                command = c;

                        }
                        catch (Exception ex)
                        { }


                        log.Info(command);
                       
                        using (PowerShell ps = PowerShell.Create())
                        {
                            if (command.Contains("-File") || command.Contains("-file"))
                            {
                                // command contains "-File" for running a script, check if file was encrypted with USI prefix.
                                string PSPath = Environment.CurrentDirectory + "\\PS\\";
                                //contruct the path, remove -File|-file from command:
                                string pattern = "-file";
                                command = command.Replace("\"","");
                                PSPath += Regex.Replace(command, pattern, "", RegexOptions.IgnoreCase).Trim();
                                
                                try
                                {
                                    string data = File.ReadAllText(PSPath);
                                    //check if PS file is encrypted
                                    if (data.Contains("Unified Systems Inc."))
                                    {
                                        byte[] bData = File.ReadAllBytes(PSPath);
                                        string ddata = DecryptStringFromBytes(bData,aes.Key);
                                        ps.AddScript(ddata);
                                    }
                                    else 
                                    {
                                        result += " Cannot open Powershell script file.";
                                    }
                                }
                                catch {
                                    log.Error(string.Format("Failed to open PS file at: {0}", PSPath));
                                }
                                
                                
                            }
                            else
                            {

                                // FOR more detailed output, uncommend the below
                                //ps.AddScript(string.Format("{0}|OUt-String",command));
                                //Comment the below if the above is used.
                                ps.AddScript(command);
                            }

                            Collection<PSObject> results = ps.Invoke();


                            foreach (PSObject Item in results)
                            {
                                if (Item != null)
                                {
                                    // Access the underlying object for its actual value
                                    result += string.Format("{0} \n", Item.ToString());
                                }                            
                             
                            }

                            // Check for errors
                            if (ps.Streams.Error.Count > 0)
                            {
                                log.Error("\nErrors encountered:");
                                foreach (ErrorRecord error in ps.Streams.Error)
                                {
                                    
                                    log.Error(error.ToString());
                                    result += string.Format("Failed to execute \n {0}", error.ToString());
                                }
                            }


                        }


                        ////////////////// OLD  - NEED TO REWRITE TO WORK WITH ENCRYPTED PS SCRIPTS 20260223 ////////////////

                        //Process process = new Process();
                        //process.StartInfo.FileName = "powershell";
                        //process.StartInfo.UseShellExecute = false; // Required for 'runas' verb
                        //process.StartInfo.Verb = "runas"; // Request administrator privileges
                        //process.StartInfo.RedirectStandardOutput = true;
                        //string folderPathPS = Environment.CurrentDirectory + "\\PS\\";
                        //process.StartInfo.WorkingDirectory = folderPathPS; // current working dir

                        //log.Info(process.StartInfo.WorkingDirectory);


                        //// check if Powershell Script folder "PS" exists, if not , create one.
                        //if (!Directory.Exists(folderPathPS))
                        //{
                        //    Directory.CreateDirectory(folderPathPS);
                        //    log.Info(string.Format("Cound not find folder PS, create new {0}", folderPathPS));

                        //}


                        //try
                        //{
                        ////    // will create temporary ps script file from command for better compatibility 

                        ////    string tempfile = Path.GetRandomFileName() + ".ps1";

                        ////    if (command.Contains("-File") || command.Contains("-file"))
                        ////    {
                        ////        // command contains "-File" for running a script, do nothing
                        ////        command = "-NoProfile -ExecutionPolicy Bypass  " + command;
                        ////    }
                        ////    else
                        ////    {
                        ////        //create ps script file from command
                        ////        try
                        ////        {
                        ////            File.WriteAllText(".\\PS\\" + tempfile, command);
                        ////        }
                        ////        catch
                        ////        {
                        ////            log.Error(string.Format("Cannot create or write temporary Powershell script file {0}", tempfile));
                        ////        }
                        ////        command = string.Format("-NoProfile -ExecutionPolicy Bypass -File {0}", tempfile);

                        ////    }
                        ////    //log.Info(string.Format(command));
                        ////    process.StartInfo.Arguments = command;

                        ////    process.Start();
                        ////    string temp = process.StandardOutput.ReadToEnd();


                        //    //log.Info(string.Format("From Powershell {0}: {1}", currentTask.sTaskDevice.ToString(), temp));
                        //    //result += temp;

                        //    //process.WaitForExit();
                        //    //try
                        //    //{
                        //    //    File.Delete(".\\PS\\" + tempfile);
                        //    //    log.Info(string.Format("Deleted temporary PS file: ", tempfile));
                        //    //}


                        //    //catch (Exception ex)
                        //    //{
                        //    //    log.Error(string.Format("Cannot delete temporary PS file: ", tempfile));
                        //    //    log.Error(ex);
                        //    //}


                        //}
                        //catch (Win32Exception ex)
                        //{
                        //    log.Error(ex);

                        //}



                        i++;
                    }
                    break;

                default:
                    break;

            }
            result += "\n#########################################################################################################\n\n";
            return result;
        }


        // SSH 
        public static void fSSH(object data)
        {
            try
            {
                cHostInfo hostinfo = (cHostInfo)data;
                string host = hostinfo.host;
                string device = hostinfo.device;
                string username = hostinfo.username;
                string password = hostinfo.password;
                string tftpIp = hostinfo.TftpIP;
                string sftpIp = hostinfo.SftpIP;
                string sftpUsername = hostinfo.SftpUsername;
                string sftpPassword = hostinfo.SftpPassword;
                string[] Commands = hostinfo.Commands;
                var client = new SshClient(hostinfo.host, hostinfo.username, hostinfo.password);
                log.Info(string.Format("From fSSH {0}: Establishing a connection", device));


                client.Connect();
                log.Info(client.ConnectionInfo.ServerVersion);

                if (client.IsConnected)
                {
                    var shellStream = client.CreateShellStream("xterm", 80, 24, 800, 600, 1024);
                    var output = "";
                    var result = "";

                    //wait for "User Name:"

                    output = shellStream.Expect(new Regex(@"Name:|name:"));
                    log.Info(string.Format("From fSSH {0}: {1}", device, output));


                    //send username
                    shellStream.WriteLine(username);

                    //wait for "Password:"
                    output = shellStream.Expect(new Regex(@"word:"));
                    log.Info(string.Format("From fSSH {0}: {1}", device, output));

                    //send password
                    shellStream.WriteLine(password);

                    //wait for "Prompt:"
                    output = shellStream.Expect(new Regex(@"#"));
                    log.Info(string.Format("From fSSH {0}: {1}", device, output));

                    output = "";

                    //create filename
                    string datetime = DateTime.Now.ToString().Replace(":", "");
                    datetime = datetime.Replace(" ", "_");
                    // string filePath = string.Format("{0}_{1}.txt", currentTask.sTaskDevice, datetime.Replace("-", ""));
                    string filePath = string.Format("{0}_{1}.txt", device, datetime.Replace("-", ""));

                    foreach (string c in Commands)
                    {
                        switch (c)
                        {
                            //enable
                            case "enable":
                                output = "";
                                shellStream.WriteLine(c);
                                //wait for "Password:"
                                output = shellStream.Expect(new Regex(@"word:"));
                                log.Info(string.Format("From fSSH {0}: {1}", device, c));


                                //send password
                                shellStream.WriteLine(password);
                                break;

                            // tftp
                            case string s when Regex.IsMatch(c, @"tftp"):
                                output = "";
                                string command = string.Format("{0}{1}/{2}", c, tftpIp, filePath);
                                log.Info(string.Format("From fSSH {0}: {1}", device, command));


                                //send tftp command 
                                shellStream.WriteLine(command);


                                //wait "<return>" to send "space" and loop until get prompt
                                while (!Regex.IsMatch(output, "#"))
                                {
                                    output = shellStream.Expect(new Regex(@"More|<return>|#"));

                                    shellStream.WriteLine(" ");
                                    string[] lines = output.Split('\n');
                                    var output1 = "";
                                    for (int ii = 0; ii < (lines.Length - 1); ii++)
                                        output1 += lines[ii];
                                    log.Info(output1);

                                    result += output1;
                                }
                                break;
                            default:
                                shellStream.WriteLine(c);
                                //wait for "Prompt:"
                                output = shellStream.Expect(new Regex(@"#"));
                                log.Info(string.Format("From fSSH_Test {0}: {1}", device, output));

                                break;

                        }
                    }
                }

                client.Disconnect();
                log.Info(string.Format("From SSH_Test: Disconnected"));

            }
            catch (Exception e)
            {
                log.Error("SSH function: cannot run SSH");
                log.Error(e);

            }

        }
        public static void fSSH_Catalyst(object data)
        {
            try
            {
                cHostInfo hostinfo = (cHostInfo)data;

                string host = hostinfo.host;
                string device = hostinfo.device;
                string username = hostinfo.username;
                string password = hostinfo.password;
                string tftpIp = hostinfo.TftpIP;
                string sftpIp = hostinfo.SftpIP;
                string sftpUsername = hostinfo.SftpUsername;
                string sftpPassword = hostinfo.SftpPassword;
                string[] Commands = hostinfo.Commands;

                var client = new SshClient(hostinfo.host, hostinfo.username, hostinfo.password);
                log.Info(string.Format("From fSSH_Catalyst {0}: Establishing a connection {1}", device, host));


                client.Connect();
                log.Info(string.Format("From fSSH_Catalyst {0}: {1}", device, client.ConnectionInfo.ServerVersion));



                if (client.IsConnected)
                {
                    var shellStream = client.CreateShellStream("xterm", 80, 24, 800, 600, 1024);
                    var output = "";
                    var result = "";
                    var prompt = "";
                    //output = "";
                    output = shellStream.Expect(new Regex(@"#"));
                    log.Info(string.Format("From fSSH_Catalyst {0}: {1}", device, output));

                    prompt = output;

                    shellStream.WriteLine("");
                    shellStream.Flush();

                    output = shellStream.Expect(new Regex(prompt));
                    log.Info(string.Format("From fSSH_Catalyst {0}: {1}", device, output));


                    //create filename
                    string datetime = DateTime.Now.ToString().Replace(":", "");
                    datetime = datetime.Replace(" ", "_");
                    // string filePath = string.Format("{0}_{1}.txt", currentTask.sTaskDevice, datetime.Replace("-", ""));
                    string filePath = string.Format("{0}_{1}.txt", device, datetime.Replace("-", ""));

                    foreach (string c in Commands)
                    {
                        switch (c)
                        {
                            //enable
                            case "enable":
                                output = "";
                                shellStream.WriteLine(c);
                                //wait for "Password:"
                                output = shellStream.Expect(new Regex(@"word:"));
                                log.Info(string.Format("From fSSH_Catalyst {0}: {1}", device, c));


                                //send password
                                shellStream.WriteLine(password);
                                break;

                            // tftp
                            case string s when Regex.IsMatch(c, @"tftp"):
                                output = "";

                                string command = string.Format("{0}{1}/{2}", c, tftpIp, filePath);

                                log.Info(string.Format("From fSSH_Catalyst {0}: {1}", device, command));
                                //send tftp command 
                                output = "";
                                shellStream.WriteLine(command);
                                shellStream.Flush();

                                //handle shell interaction, wait for "?" then send "enter"

                                output = shellStream.Expect(new Regex(@"\?"));

                                log.Info(string.Format("From fSSH_Catalyst{0}: {1}", device, output));
                                while (output.Contains("?"))
                                {
                                    output = "";
                                    shellStream.WriteLine("");
                                    shellStream.Flush();
                                    output = shellStream.Expect(new Regex(@"\?|#"));
                                    log.Info(string.Format("From fSSH_Catalyst  {0}: {1}", device, output));

                                }

                                break;
                            default:
                                shellStream.WriteLine(c);
                                //wait for "Prompt:"
                                output = shellStream.Expect(prompt);

                                log.Info(string.Format("From fSSH_Catalyst {0}: {1}", device, output));
                                break;

                        }
                    }

                }

                client.Disconnect();
                log.Info(string.Format("From SSH_Catalyst: Disconnected"));


            }
            catch (Exception e)
            {
                log.Error("SSH_Catalyst function: cannot run SSH_Catalyst");
                log.Error(e);

            }
        }

        //Seriallize Tasklist to a Json file
        public void SaveTasklist(List<cTask> data, string filePath, Aes aes)
        {
            JsonSerializerOptions options = new JsonSerializerOptions
            {
                //save with indentation
                WriteIndented = true,
                // enable case insensitive
                PropertyNameCaseInsensitive = true,
                // ignore null property
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull

            };
            string jsonString = JsonSerializer.Serialize(data, options);

            File.WriteAllBytes(filePath, EncryptStringAES(jsonString,aes.Key));
        }
        //Deseriallize Tasklist from a Json file
        public List<cTask> LoadTaskList(string filePath, Aes aes)
        {
            JsonSerializerOptions options = new JsonSerializerOptions
            {
                //save with indentation
                WriteIndented = true,
                // enable case insensitive
                PropertyNameCaseInsensitive = true,
                // ignore null property
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenReading

            };

            if (File.Exists(filePath))
            {
                try
                {
                    
                    log.Info(string.Format("Try loading {0}", filePath));
                    string jsonString = "";
                    
                    if (File.Exists(filePath))
                    {
                        try
                        {
                            //read json data from file
                            byte[] bData = File.ReadAllBytes(filePath);

                            //decrypt data and save to file

                            jsonString = DecryptStringFromBytes(bData, aes.Key);

                        }
                        catch (Exception ex)
                        {
                            //could not read tasklist.json properly
                            log.Error(string.Format("Could not load {0} for decrypting", filePath));
                            log.Error(ex);
                        }


                    }


                    return JsonSerializer.Deserialize<List<cTask>>(jsonString, options);                    
                }
                catch (Exception ex)
                {
                    //could not read tasklist.json properly
                    log.Error(string.Format("Could not load {0}", filePath));
                    log.Error(ex);

                    //return an empty list if file could not be read

                    return new List<cTask>();

                }

            }
            return new List<cTask>(); // Return an empty list if file doesn't exist
        }
        //Seriallize Profile to a Json file
        public void SaveProfile(List<Profile> data, string filePath)
        {
            JsonSerializerOptions options = new JsonSerializerOptions
            {
                WriteIndented = true
            };
            string jsonString = JsonSerializer.Serialize(data, options);
            File.WriteAllText(filePath, jsonString);
        }


        //Deseriallize Profile from a Json file
        public List<Profile> LoadProfile(string filePath, Aes aes)
        {

            if (File.Exists(filePath))
            {
                try
                {
                    string jsonString = "";
                    try
                    {
                        //read json data from file
                        byte[] bData = File.ReadAllBytes(filePath);                    

                        //decrypt data and save to file

                        jsonString = DecryptStringFromBytes(bData, aes.Key);

                    }
                    catch (Exception ex)
                    {
                        //could not read tasklist.json properly
                        log.Error(string.Format("Could not load {0} for decrypting", filePath));
                        log.Error(ex);
                    }
                    log.Info("Process profile.json");
                    return JsonSerializer.Deserialize<List<Profile>>(jsonString);
                }
                catch (Exception ex)
                {
                    //could not read profile.json properly
                    log.Error("Could not load profile.json");
                    log.Error(ex);

                    //return an empty list if file could not be read

                    return new List<Profile>();

                }

            }
            return new List<Profile>(); // Return an empty list if file doesn't exist
        }

        //Encrypt a file with AES, append "Unified Systems Inc." + IV at the beginning of the file
        public static byte[] EncryptStringAES(string sData, byte[] key)
        {
            // Check arguments
            if (sData == null || sData.Length <= 0)
                throw new ArgumentNullException(nameof(sData));
            if (key == null || key.Length <= 0)
                throw new ArgumentNullException(nameof(Key));
            
            byte[] encrypted ;
            byte[] USI = Encoding.UTF8.GetBytes("Unified Systems Inc.");
            Aes aes = Aes.Create();
            
            aes.Key = key;
            // Create an encryptor.
            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

            // Use streams for encryption.
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        // Write all data to the stream.
                        swEncrypt.Write(sData);
                    }

                    encrypted = msEncrypt.ToArray();
                }
            }


            //return encrypted data with USI + IV at the beginning
            byte[] USIIV = USI.Concat(aes.IV).ToArray();   
            return USIIV.Concat(encrypted).ToArray();
        }


        //Decrypt a file with AES, with "Unified Systems Inc." + IV at the beginning of the file
        public static string DecryptStringFromBytes(byte[] eDdata, byte[] Key)
        {
            // Check arguments.
            if (eDdata == null || eDdata.Length <= 0)
                throw new ArgumentNullException(nameof(eDdata));
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException(nameof(Key));

            //extract IV and remove USI + IV
            byte[] IV = new byte[16];
            byte[] USI = Encoding.UTF8.GetBytes("Unified Systems Inc.");
            byte[] USIIV = USI.Concat(IV).ToArray();


            Array.Copy(eDdata, 0, USIIV, 0, USIIV.Length);
            Array.Copy(USIIV,USI.Length,IV, 0, IV.Length);
            
            //remove USIIV from bData:

            int dataLength = eDdata.Length - USIIV.Length;
            byte[] bdatanoIV = new byte[dataLength];

            Array.Copy(eDdata, USIIV.Length, bdatanoIV, 0, dataLength);


            // Declare the string used to hold the decrypted text.
            string sData = null;

            using (Aes aes = Aes.Create())
            {
                aes.Key = Key;
                aes.IV = IV;

                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(bdatanoIV))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            sData = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return sData;
        }






    }

        public class cHostInfo
    {
        public string device { get; set; }
        public string host { get; set; }
        public string username { get; set; }
        public string password { get; set; }
        public string TftpIP { get; set; }

        public string SftpIP { get; set; }
        public string SftpUsername { get; set; }
        public string SftpPassword { get; set; }
        public string[] Commands { get; set; }
        public Dictionary<string, string> dParameters { get; set; }

        public cHostInfo()
        {
            device = "";
            host = "localhost";
            username = "";
            password = "";
            TftpIP = "127.0.0.1";
            SftpIP = "127.0.0.1";
            SftpUsername = "";
            SftpPassword = "";
        }

    }


    [Serializable]
    public class cTask
    {
        public int iTaskNum { get; set; }
        public String sTaskDescription { get; set; }
        public String sTaskDevice { get; set; }
        public bool bTaskSelect { get; set; }
        public String sProfile { get; set; }
        public Dictionary<string, string> dParameters { get; set; }
        public cTask()
        {
            this.iTaskNum = 0;
            this.sTaskDescription = "";
            this.sTaskDevice = "";
            this.bTaskSelect = false;
            this.sProfile = "";
            this.dParameters = new Dictionary<string, string>();
        }
        public cTask(int iTaskNum, string uTaskDescription, string uTaskDevice, bool bTaskSelect, string sProfile)
        {
            this.iTaskNum = iTaskNum;
            this.sTaskDescription = uTaskDescription;
            this.sTaskDevice = uTaskDevice;            
            this.bTaskSelect = bTaskSelect;
            this.sProfile = sProfile;
            this.dParameters = new Dictionary<string, string>();
        }
    }

    [Serializable]
    public class cConInfo
    {

        public String sTftpIP { get; set; }
        public String sTftpUsername { get; set; }
        public String sTftpPassword { get; set; }
        public String sSftpIP { get; set; }
        public String sSftpUsername { get; set; }
        public String sSftpPassword { get; set; }
        public cConInfo(string TftpIP, string TftpUsername, string TftpPassword, string SftpIP, String SftpUsername, String SftPassword)
        {
            this.sTftpIP = TftpIP;
            this.sTftpUsername = TftpUsername;
            this.sTftpPassword = TftpPassword;
            this.sSftpIP = SftpIP;
            this.sSftpUsername = SftpUsername;
            this.sSftpPassword = SftPassword;

        }
    }            


}
