-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
224 lines (190 loc) · 8.39 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
using PerrysNetConsole;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Prompt = Sharprompt.Prompt;
namespace SafeFolder;
public static class Program
{
private struct ProgramOptions {
public string FolderPath { get; init; }
public string? BlacklistFiles { get; init; }
public bool HelpRequested { get; init; }
public bool VersionRequested { get; init; }
public bool InMemory { get; init; }
public bool ClearTraces { get; init; }
public bool Encrypt { get; init; }
public bool Decrypt { get; init; }
public string? Password { get; init; }
public bool Verbose { get; init; }
}
private static readonly Dictionary<string, Flag> _flags = new() {
{ "nogui", new Flag("nogui", "n") },
{ "blacklist", new Flag("blacklist", "b", true) },
{ "help", new Flag("help", "h") },
{ "version", new Flag("version", "v") },
{ "memory", new Flag("inmemory", "m") },
{ "clear", new Flag("cleartraces", "c") },
{ "encrypt", new Flag("encrypt", "e") },
{ "decrypt", new Flag("decrypt", "d") },
{ "password", new Flag("password", "p", true) },
{ "verbosity", new Flag("verbosity", "V") }
};
private static async Task Main(string[] args) {
bool isNoGui = Flag.HasFlag(args, _flags["nogui"]);
bool helpRequested = Flag.HasFlag(args, _flags["help"]);
bool versionRequested = Flag.HasFlag(args, _flags["version"]);
bool inMemory = Flag.HasFlag(args, _flags["memory"]);
bool clearTraces = Flag.HasFlag(args, _flags["clear"]);
bool encrypt = Flag.HasFlag(args, _flags["encrypt"]);
bool decrypt = Flag.HasFlag(args, _flags["decrypt"]);
bool verbose = Flag.HasFlag(args, _flags["verbosity"]);
bool pwdIncluded = Flag.TryGetFlagValue(args, _flags["password"], out string password);
bool blacklistIncluded = Flag.TryGetFlagValue(args, _flags["blacklist"], out string blacklist);
List<string> folderPaths = Flag.GetStrayArgs(args, _flags.Values);
if(folderPaths.Count == 0)
folderPaths.Add(Directory.GetCurrentDirectory());
foreach (string folderPath in folderPaths) {
// pack flags information on one struct
ProgramOptions opt = new() {
FolderPath = folderPath,
BlacklistFiles = blacklistIncluded ? blacklist : null,
HelpRequested = helpRequested,
VersionRequested = versionRequested,
InMemory = inMemory,
ClearTraces = clearTraces,
Encrypt = encrypt,
Decrypt = decrypt,
Password = pwdIncluded ? password : null,
Verbose = verbose
};
if (isNoGui || helpRequested || versionRequested)
await StartCli(opt);
else
await StartInteractive(folderPath);
}
}
private static async Task StartInteractive(string folder) {
Utils.ShowSplashScreen();
string? state = Prompt.Select("What do you want", new[] {
"Encrypt Files",
"Decrypt Files",
"Info about program",
"Exit"
});
bool useRam = false; // just initialize these because compiler doesnt like switches
bool clearTraces = false;
switch (state) {
case "Info about program":
Utils.WriteLine("SafeFolder\n");
Utils.ShowInfoScreen();
Console.WriteLine("Press any key to close the program.");
Console.ReadKey();
return;
case "Exit":
return;
case "Encrypt Files":
useRam = Prompt.Confirm("Encrypt files in memory? (Fast, but demands more ram)");
clearTraces = Prompt.Confirm("Clear traces? (Very Slow, but more secure)");
break;
case "Decrypt Files":
useRam = Prompt.Confirm("Decrypt files in memory? (Fast, but demands more ram)");
clearTraces = Prompt.Confirm("Clear traces? (Very Slow, but more secure)");
break;
}
Progress progressBar = new();
string? pwd = Prompt.Password("Enter password",
placeholder: "Take Care With CAPS-LOCK",
validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) });
if (state == "Encrypt Files") {
string? pwd2 = Prompt.Password("Re-Enter password",
placeholder: "Take Care With CAPS-LOCK",
validators: new[] { Sharprompt.Validators.Required(), Sharprompt.Validators.MinLength(4) });
if (pwd != pwd2) {
Console.WriteLine("The passwords do not match! Aborting");
Console.ReadKey();
return;
}
}
byte[] key = Utils.DeriveKeyFromString(pwd);
string pwdHash = Utils.GetHash(Utils.HashBytes(key));
Engine engine = new(new EngineConfiguration {
FolderPath = folder,
ProgressBar = progressBar,
UseRam = useRam,
ClearTraces = clearTraces
});
switch (state) {
case "Encrypt Files":
// have to encrypt
progressBar.Start();
progressBar.Message(Message.LEVEL.INFO, "Encrypting files...");
await engine.PackFiles(key, pwdHash);
break;
case "Decrypt Files":
// have to decrypt
progressBar.Start();
progressBar.Message(Message.LEVEL.INFO, "Decrypting files...");
await engine.UnpackFiles(key, pwdHash);
break;
}
progressBar.Message(Message.LEVEL.SUCCESS, $"Done in {engine.Elapsed:mm\\:ss\\:fff}!");
progressBar.Update(100);
progressBar.Stop();
CoEx.WriteLine();
Console.WriteLine("Press any key to close the program.");
Console.ReadKey();
}
private static bool CheckForInputError(ProgramOptions opt) {
switch (opt) {
case { Decrypt: false, Encrypt: false }:
Utils.WriteLine("You must specify either --encrypt(-e) or --decrypt(-d)", ConsoleColor.Red);
return true;
case { Decrypt: true, Encrypt: true }:
Utils.WriteLine("You can't specify both --encrypt(-e) and --decrypt(-d)", ConsoleColor.Red);
return true;
}
if(opt.Password == null) {
Utils.WriteLine("You must specify a password using '--password <PASSWORD>' or '-p <PASSWORD>'", ConsoleColor.Red);
return true;
}
if (opt.Password.Length >= 4) return false;
Utils.WriteLine("Password must be at least 4 characters long", ConsoleColor.Red);
return true;
}
private static async Task StartCli(ProgramOptions opt) {
if (opt.HelpRequested) {
Utils.ShowInfoScreen();
return;
}
if (opt.VersionRequested) {
string version = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown";
Utils.WriteLine($"Current SafeFolder version: {version}", version == "Unknown" ? ConsoleColor.Red : ConsoleColor.Green);
return;
}
bool error = CheckForInputError(opt); // returns true on error, false on success
if (error)
return;
byte[] key = Utils.DeriveKeyFromString(opt.Password!);
string pwdHash = Utils.GetHash(Utils.HashBytes(key));
Directory.SetCurrentDirectory(opt.FolderPath);
Engine engine = new(new EngineConfiguration {
ProgressBar = null,
FolderPath = opt.FolderPath,
Blacklist = opt.BlacklistFiles ?? "",
UseRam = opt.InMemory,
ClearTraces = opt.ClearTraces
});
if(opt.Verbose)
Utils.WriteLine($"{(opt.Encrypt ? "Encrypting" : "Decrypting")} files now");
if (opt.Encrypt) {
await engine.PackFiles(key, pwdHash);
}else {
await engine.UnpackFiles(key, pwdHash);
}
if (opt.Verbose)
Utils.WriteLine($"Done in {engine.Elapsed:mm\\:ss\\:fff}!");
}
}