using ICSharpCode.SharpZipLib.Zip; using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; namespace ndpack { class Program { static Task ReadPassword(string prompt = null, CancellationToken token = default) { TaskCompletionSource comp = new TaskCompletionSource(); List pwd = new List(); bool set = false; _ = Task.Run(() => { if (prompt != null) Console.Write(prompt); try { using var _c = token.Register(() => { if (!set) { set = true; comp.SetException(new OperationCanceledException()); } }); while (true) { ConsoleKeyInfo i = Console.ReadKey(true); if (token.IsCancellationRequested) break; if (i.Key == ConsoleKey.Enter) { Console.WriteLine(); break; } else if (i.Key == ConsoleKey.Backspace) { if (pwd.Count > 0) { pwd.RemoveAt(pwd.Count - 1); } } else if (i.KeyChar != '\u0000') { pwd.Add(i.KeyChar); } } if (!set) { set = true; if (token.IsCancellationRequested) comp.SetException(new OperationCanceledException()); else comp.SetResult(new string(pwd.ToArray())); } } catch (Exception ex) { Console.WriteLine(); pwd.Clear(); if (!set) { set = true; comp.SetException(ex); } } }); return comp.Task; } static void usage() { Console.WriteLine("Usage: ndpack -c "); Console.WriteLine("Usage: ndpack -e "); Console.WriteLine("Usage: ndpack -u "); Console.WriteLine("Usage: ndpack -d "); } static async Task CopyDirectory(string SourcePath, string DestinationPath) { Exception bad = null; await Task.Run(() => { try { //Now Create all of the directories foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories)) Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath)); //Copy all the files & Replaces any files with the same name foreach (string newPath in Directory.GetFiles(SourcePath, "*", SearchOption.AllDirectories)) File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), true); }catch(Exception ex) { bad = ex; } }); if (bad != null) throw bad; } static async Task create(string output, string dumpf, string dirf) { FastZip fs = new FastZip(); using var tdir = new TempDirectory(); await Task.Yield(); Console.WriteLine("Copying dump..."); File.Copy(dumpf, Path.Combine(tdir.Directory.FullName, Path.GetFileName(dumpf))); Console.WriteLine($"Copying images..."); var ipath = Path.Combine(tdir.Directory.FullName, new DirectoryInfo(dirf).Name); Directory.CreateDirectory(ipath); await CopyDirectory(dirf, ipath); await Task.Yield(); fs.CreateZip(output, tdir.Directory.FullName, true, null, null); } static async Task unpack(string inputArchive, string outputDir) { if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir); var fs = new FastZip(); await Task.Yield(); fs.ExtractZip(inputArchive, outputDir, null); } static async Task decrypt(string inf, string of, string kf, Func> password) { using var infs = new FileStream(inf, FileMode.Open, FileAccess.Read); using var enc = new encaes.AesEncryptor(infs); using (var kfs = new FileStream(kf, FileMode.Open, FileAccess.Read)) { enc.Key = await encaes.AesEncryptor.LoadKey(kfs, () => { var tsk = password(); tsk.Wait(); if (tsk.IsFaulted) throw tsk.Exception; else return tsk.Result; }); } using var ofs = new FileStream(of, FileMode.Create); await enc.Decrypt(ofs); } static async Task encrypt(string inf, string outf, string kf, Func> password) { using var infs = new FileStream(inf, FileMode.Open, FileAccess.Read); using var enc = new encaes.AesEncryptor(infs); using (var kfs = new FileStream(kf, FileMode.Open, FileAccess.Read)) { enc.Key = await encaes.AesEncryptor.LoadKey(kfs, () => { var tsk = password(); tsk.Wait(); if (tsk.IsFaulted) throw tsk.Exception; else return tsk.Result; }); } using (var ofs = new FileStream(outf, FileMode.Create)) { await enc.Encrypt(ofs); } } static async Task Main(string[] args) { if (args.Length < 3) { usage(); return; } else { switch (args[0].ToLower()) { case "-c": if (args.Length < 4) { usage(); return; } try { await create(args[3], args[1], args[2]); } catch (Exception ex) { Console.WriteLine("Error creating: " + ex.Message); } break; case "-e": if(args.Length<5) { usage(); return; } try { string realOutput = args[4]; using var tf = TempFile.WithNoStream(); await create(tf.File.FullName, args[1], args[2]); Console.WriteLine("Encrypting..."); await encrypt(tf.File.FullName, realOutput, args[3], async () => { return await ReadPassword("Password: "); }); } catch (Exception ex) { Console.WriteLine("Error creating: " + ex.Message); } break; case "-u": try { Console.WriteLine("Unpacking..."); await unpack(args[1], args[2]); } catch (Exception ex) { Console.WriteLine("Error unpacking: " + ex.Message); } break; case "-d": if (args.Length < 4) { usage(); return; } try { using var arcfs = TempFile.WithNoStream(); Console.WriteLine("Decrypting..."); await decrypt(args[1], arcfs.File.FullName, args[2], async () => { return await ReadPassword("Password: "); }); Console.WriteLine("Unpacking..."); await unpack(arcfs.File.FullName, args[3]); } catch (Exception ex) { Console.WriteLine("Error unpacking: " + ex.Message); } break; default: usage(); return; } } } } }