/******************************************************************************/ /* SlunkCrypt, by LoRd_MuldeR */ /* This work has been released under the CC0 1.0 Universal license! */ /******************************************************************************/ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Threading; using com.muldersoft.slunkcrypt.gui.utils; namespace com.muldersoft.slunkcrypt.gui.process { internal class SlunkCryptRunner : ProcessRunner { public enum Mode { Encrypt, Decrypt } private const string FILENAME_FORMAT = "slunkcrypt-cli-{0}.exe"; private const string COMMAND_ENCRYPT = "-e"; private const string COMMAND_DECRYPT = "-d"; private static readonly Regex RX_PROGRESS = new Regex(@"(\d+)\.(\d)%", RegexOptions.Compiled); private readonly FileStream m_executableFile; // ============================================================================= // Exception classes // ============================================================================= public class ExecutableNotFoundException : FileNotFoundException { public ExecutableNotFoundException(string message, string fileName) : base(message, fileName) { } } // ============================================================================= // Constructor // ============================================================================= public SlunkCryptRunner(Dispatcher dispatcher, ProcessPriorityClass? priorityClass = null) : base(dispatcher, priorityClass) { m_executableFile = GetExecutableFile(); } // ============================================================================= // Public methods // ============================================================================= public async Task ExecuteAsync(Mode mode, string inputFile, string outputFile, string password) { Dictionary environmentVariables = new Dictionary(); environmentVariables.Add("SLUNK_PASSPHRASE", password); string[] arguments = new string[] { GetCommandString(mode), inputFile, outputFile }; return await ExecAsnyc(m_executableFile.Name, arguments, environmentVariables); } public override void Dispose() { base.Dispose(); try { m_executableFile.Dispose(); } catch { } } // ============================================================================= // Internal methods // ============================================================================= private static FileStream GetExecutableFile() { FileStream executableFile = null; string appBaseDirectory = AppDomain.CurrentDomain.BaseDirectory; CPUFeatures cpuFeatures = CPUFeatures.Features; if (cpuFeatures.x64 && CheckExecutableFile(ref executableFile, appBaseDirectory, "x64")) { Trace.Assert(executableFile != null); return executableFile; } if (cpuFeatures.sse2 && CheckExecutableFile(ref executableFile, appBaseDirectory, "sse2")) { Trace.Assert(executableFile != null); return executableFile; } if (CheckExecutableFile(ref executableFile, appBaseDirectory, "i686")) { Trace.Assert(executableFile != null); return executableFile; } throw new ExecutableNotFoundException("SlunkCrypt executable file not found!", FILENAME_FORMAT); } private static bool CheckExecutableFile(ref FileStream executableFile, string appBaseDirectory, string suffix) { try { executableFile = new FileStream(Path.Combine(appBaseDirectory, String.Format(FILENAME_FORMAT, suffix)), FileMode.Open, FileAccess.Read, FileShare.Read); Version appVersion = VersionInfo.Version; FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(executableFile.Name); if (string.Equals(fileVersion.FileDescription, "SlunkCrypt", StringComparison.OrdinalIgnoreCase) && string.Equals(fileVersion.CompanyName, "Muldersoft", StringComparison.OrdinalIgnoreCase) && (fileVersion.FileMajorPart == appVersion.Major) && (fileVersion.FileMinorPart == appVersion.Minor)) { return true; } executableFile.Dispose(); /*clean-up*/ } catch { } return false; } protected override double ParseProgressString(StringBuilder currentLine) { Match match; double progress, result = double.NaN; do { match = RX_PROGRESS.Match(currentLine.ToString()); if (match.Success) { if (!double.IsNaN(progress = ParseProgressValue(match))) { result = progress; } currentLine.Remove(match.Index, match.Length); } } while (match.Success); return result; } private static double ParseProgressValue(Match match) { uint intPart, fractPart; if (uint.TryParse(match.Groups[1].Value, out intPart) && uint.TryParse(match.Groups[2].Value, out fractPart)) { return ((intPart * 10) + fractPart) / 1000.0; } return double.NaN; } private static string GetCommandString(Mode mode) { switch(mode) { case Mode.Encrypt: return COMMAND_ENCRYPT; case Mode.Decrypt: return COMMAND_DECRYPT; default: throw new ArgumentException("Invalid mode!"); } } } }