|
|
1.1 root 1: /*
2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
3:
4: Governed by the TrueCrypt License 2.4 the full text of which is contained
5: in the file License.txt included in TrueCrypt binary and source code
6: distribution packages.
7: */
8:
9: #include "System.h"
10: #include <wx/cmdline.h>
11: #include <wx/tokenzr.h>
12: #include "Core/Core.h"
13: #include "CommandLineInterface.h"
14: #include "LanguageStrings.h"
15: #include "UserInterfaceException.h"
16:
17: namespace TrueCrypt
18: {
19: CommandLineInterface::CommandLineInterface (wxCmdLineParser &parser, UserInterfaceType::Enum interfaceType) :
20: ArgCommand (CommandId::None),
21: StartBackgroundTask (false)
22: {
23: parser.SetSwitchChars (L"-");
24:
25: parser.AddOption (L"", L"auto-mount", _("Auto mount device-hosted/favorite volumes"));
26: parser.AddSwitch (L"", L"background-task", _("Start Background Task"));
27: parser.AddSwitch (L"d", L"dismount", _("Dismount volume"));
28: parser.AddSwitch (L"", L"cache", _("Cache passwords and keyfiles"));
29: parser.AddSwitch (L"C", L"change", _("Change password or keyfiles"));
30: parser.AddSwitch (L"", L"explore", _("Open explorer window for mounted volume"));
31: parser.AddSwitch (L"f", L"force", _("Force mount/dismount/overwrite"));
32: parser.AddSwitch (L"h", L"help", _("Display help"), wxCMD_LINE_OPTION_HELP);
33: parser.AddOption (L"k", L"keyfiles", _("Keyfiles"));
34: parser.AddOption (L"", L"filesystem", _("Filesystem type"));
35: #if !defined(TC_WINDOWS) && !defined(TC_MACOSX)
36: parser.AddOption (L"", L"fs-options", _("Filesystem options"));
37: #endif
38: parser.AddSwitch (L"l", L"list", _("List mounted volumes"));
39: parser.AddOption (L"m", L"mount-options", _("Mount options"));
40: parser.AddOption (L"", L"new-keyfiles", _("New keyfiles"));
41: parser.AddOption (L"", L"new-password", _("New password"));
42: parser.AddSwitch (L"", L"non-interactive", _("Do not interact with user"));
43: parser.AddOption (L"p", L"password", _("Password"));
44: parser.AddSwitch (L"", L"load-preferences", _("Load user preferences"));
45: parser.AddSwitch (L"", L"protect-hidden", _("Protect hidden volume"));
46: parser.AddOption (L"", L"protection-keyfiles", _("Keyfiles for protected hidden volume"));
47: parser.AddOption (L"", L"protection-password", _("Password for protected hidden volume"));
48: parser.AddSwitch (L"v", L"verbose", _("Enable verbose output"));
49: parser.AddOption (L"", L"slot", _("Volume slot number"));
50: parser.AddSwitch (L"", L"test", _("Test internal algorithms"));
51: parser.AddSwitch (L"t", L"text", _("Use text user interface"));
52: parser.AddSwitch (L"", L"version", _("Display version information"));
53: parser.AddParam ( _("Volume path"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
54: parser.AddParam ( _("Mount point"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
55:
56: wxString str;
57: bool param1IsVolume = false;
58: bool param1IsMountedVolumeSpec = false;
59: bool param1IsMountPoint = false;
60:
61: if (parser.Parse () > 0)
62: throw_err (_("Incorrect command line specified."));
63:
64: if (parser.Found (L"help"))
65: {
66: ArgCommand = CommandId::Help;
67: return;
68: }
69:
70: if (parser.Found (L"text") && interfaceType != UserInterfaceType::Text)
71: {
72: wstring msg = wstring (_("Option -t or --text must be specified as the first argument."));
73: wcerr << msg << endl;
74: throw_err (msg);
75: }
76:
77: if (parser.Found (L"version"))
78: {
79: ArgCommand = CommandId::DisplayVersion;
80: return;
81: }
82:
83: // Preferences
84: if (parser.Found (L"load-preferences"))
85: {
86: // Load preferences first to allow command line options to override them
87: Preferences.Load();
88: ArgMountOptions = Preferences.DefaultMountOptions;
89: }
90:
91: // Commands
92: if (parser.Found (L"auto-mount", &str))
93: {
94: CheckCommandSingle();
95:
96: wxStringTokenizer tokenizer (str, L",");
97: while (tokenizer.HasMoreTokens())
98: {
99: wxString token = tokenizer.GetNextToken();
100:
101: if (token == L"devices")
102: {
103: if (ArgCommand == CommandId::AutoMountFavorites)
104: ArgCommand = CommandId::AutoMountDevicesFavorites;
105: else
106: ArgCommand = CommandId::AutoMountDevices;
107:
108: param1IsMountPoint = true;
109: }
110: else if (token == L"favorites")
111: {
112: if (ArgCommand == CommandId::AutoMountDevices)
113: ArgCommand = CommandId::AutoMountDevicesFavorites;
114: else
115: ArgCommand = CommandId::AutoMountFavorites;
116: }
117: else
118: {
119: throw_err (LangString["UNKNOWN_OPTION"] + L": " + token);
120: }
121: }
122: }
123:
124: if (parser.Found (L"change"))
125: {
126: CheckCommandSingle();
127: ArgCommand = CommandId::ChangePassword;
128: param1IsVolume = true;
129: }
130:
131: if (parser.Found (L"dismount"))
132: {
133: CheckCommandSingle();
134: ArgCommand = CommandId::DismountVolumes;
135: param1IsMountedVolumeSpec = true;
136: }
137:
138: if (parser.Found (L"list"))
139: {
140: CheckCommandSingle();
141: ArgCommand = CommandId::ListVolumes;
142: param1IsMountedVolumeSpec = true;
143: }
144:
145: if (parser.Found (L"test"))
146: {
147: CheckCommandSingle();
148: ArgCommand = CommandId::Test;
149: }
150:
151: // Options
152: if (parser.Found (L"background-task"))
153: StartBackgroundTask = true;
154:
155: if (parser.Found (L"cache"))
156: ArgMountOptions.CachePassword = true;
157:
158: if (parser.Found (L"explore"))
159: Preferences.OpenExplorerWindowAfterMount = true;
160:
161: if (parser.Found (L"filesystem", &str))
162: {
163: if (str.IsSameAs (L"none", false))
164: ArgMountOptions.NoFilesystem = true;
165: else
166: ArgMountOptions.FilesystemType = wstring (str);
167: }
168:
169: if (parser.Found (L"force"))
170: ArgForce = true;
171:
172: if (parser.Found (L"keyfiles", &str))
173: ArgKeyfiles = ToKeyfileList (str);
174:
175: if (parser.Found (L"mount-options", &str))
176: {
177: wxStringTokenizer tokenizer (str, L",");
178: while (tokenizer.HasMoreTokens())
179: {
180: wxString token = tokenizer.GetNextToken();
181:
182: if (token == L"readonly" || token == L"ro")
183: ArgMountOptions.Protection = VolumeProtection::ReadOnly;
184: else if (token == L"timestamp" || token == L"ts")
185: ArgMountOptions.PreserveTimestamps = false;
186: #ifdef TC_WINDOWS
187: else if (token == L"removable" || token == L"rm")
188: ArgMountOptions.Removable = true;
189: #endif
190: else
191: throw_err (LangString["UNKNOWN_OPTION"] + L": " + token);
192: }
193: }
194:
195: if (parser.Found (L"new-keyfiles", &str))
196: ArgNewKeyfiles = ToKeyfileList (str);
197:
198: if (parser.Found (L"new-password", &str))
199: ArgNewPassword.reset (new VolumePassword (wstring (str)));
200:
201: if (parser.Found (L"non-interactive"))
202: Preferences.NonInteractive = true;
203:
204: if (parser.Found (L"password", &str))
205: ArgPassword.reset (new VolumePassword (wstring (str)));
206:
207: if (parser.Found (L"protect-hidden") && ArgMountOptions.Protection != VolumeProtection::ReadOnly)
208: ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly;
209:
210: if (parser.Found (L"protection-keyfiles", &str))
211: {
212: ArgMountOptions.ProtectionKeyfiles = ToKeyfileList (str);
213: ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly;
214: }
215:
216: if (parser.Found (L"protection-password", &str))
217: {
218: ArgMountOptions.ProtectionPassword.reset (new VolumePassword (wstring (str)));
219: ArgMountOptions.Protection = VolumeProtection::HiddenVolumeReadOnly;
220: }
221:
222: if (parser.Found (L"slot", &str))
223: {
224: unsigned long number;
225: if (!str.ToULong (&number) || number < Core->GetFirstSlotNumber() || number > Core->GetLastSlotNumber())
226: throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str);
227:
228: ArgMountOptions.SlotNumber = number;
229:
230: if (param1IsMountedVolumeSpec)
231: {
232: shared_ptr <VolumeInfo> volume = Core->GetMountedVolume (number);
233: if (!volume)
234: throw_err (_("No such volume is mounted."));
235:
236: ArgVolumes.push_back (volume);
237: param1IsMountedVolumeSpec = false;
238: }
239: }
240:
241: if (parser.Found (L"verbose"))
242: Preferences.Verbose = true;
243:
244: // Parameters
245: if (parser.GetParamCount() > 0)
246: {
247: if (ArgCommand == CommandId::None)
248: {
249: ArgCommand = CommandId::MountVolume;
250: param1IsVolume = true;
251: }
252:
253: if (param1IsVolume)
254: {
255: wxFileName volPath (parser.GetParam (0));
256:
257: #ifdef TC_WINDOWS
258: if (!parser.GetParam (0).StartsWith (L"\\Device\\"))
259: #endif
260: volPath.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS);
261:
262: ArgVolumePath.reset (new VolumePath (wstring (volPath.GetFullPath())));
263: }
264:
265: if (param1IsMountPoint || parser.GetParamCount() >= 2)
266: {
267: wstring s (parser.GetParam (param1IsMountPoint ? 0 : 1));
268: wxFileName mountPoint (wstring (Directory::AppendSeparator (s)));
269: mountPoint.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS);
270: ArgMountPoint.reset (new DirectoryPath (wstring (mountPoint.GetPath())));
271: }
272: }
273:
274: if (param1IsMountedVolumeSpec)
275: ArgVolumes = GetMountedVolumes (parser.GetParamCount() > 0 ? parser.GetParam (0) : wxString());
276: }
277:
278: CommandLineInterface::~CommandLineInterface ()
279: {
280: }
281:
282: void CommandLineInterface::CheckCommandSingle () const
283: {
284: if (ArgCommand != CommandId::None)
285: throw_err (_("Only a single command can be specified at a time."));
286: }
287:
288: shared_ptr <KeyfileList> CommandLineInterface::ToKeyfileList (const wxString &arg) const
289: {
290: wxStringTokenizer tokenizer (arg, L",", wxTOKEN_RET_EMPTY_ALL);
291:
292: // Handle escaped separator
293: wxArrayString arr;
294: bool prevEmpty = false;
295: while (tokenizer.HasMoreTokens())
296: {
297: wxString token = tokenizer.GetNextToken();
298:
299: if (prevEmpty && token.empty() && tokenizer.HasMoreTokens())
300: {
301: token = tokenizer.GetNextToken();
302: if (!token.empty())
303: {
304: arr.Add (token);
305: prevEmpty = true;
306: continue;
307: }
308: }
309:
310: if (token.empty() && !tokenizer.HasMoreTokens())
311: break;
312:
313: if (prevEmpty || token.empty())
314: {
315: if (arr.Count() < 1)
316: {
317: arr.Add (L"");
318: continue;
319: }
320: arr.Last() += token.empty() ? L',' : token;
321: }
322: else
323: arr.Add (token);
324:
325: prevEmpty = token.empty();
326: }
327:
328: make_shared_auto (KeyfileList, keyfileList);
329: for (size_t i = 0; i < arr.GetCount(); i++)
330: {
331: if (!arr[i].empty())
332: keyfileList->push_back (make_shared <Keyfile> (wstring (arr[i])));
333: }
334:
335: return keyfileList;
336: }
337:
338: VolumeInfoList CommandLineInterface::GetMountedVolumes (const wxString &mountedVolumeSpec) const
339: {
340: VolumeInfoList volumes = Core->GetMountedVolumes ();
341: VolumeInfoList filteredVolumes;
342:
343: wxFileName pathFilter;
344: if (!mountedVolumeSpec.empty())
345: {
346: pathFilter = mountedVolumeSpec;
347: pathFilter.Normalize (wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS);
348: }
349: else
350: return volumes;
351:
352: foreach (shared_ptr <VolumeInfo> volume, volumes)
353: {
354: if (mountedVolumeSpec.empty())
355: {
356: filteredVolumes.push_back (volume);
357: }
358: else if (wxString (volume->Path) == pathFilter.GetFullPath())
359: {
360: filteredVolumes.push_back (volume);
361: }
362: else if (wxString (volume->MountPoint) == pathFilter.GetFullPath()
363: || (wxString (volume->MountPoint) + wxFileName::GetPathSeparator()) == pathFilter.GetFullPath())
364: {
365: filteredVolumes.push_back (volume);
366: }
367: }
368:
369: if (!mountedVolumeSpec.IsEmpty() && filteredVolumes.size() < 1)
370: throw_err (_("No such volume is mounted."));
371:
372: return filteredVolumes;
373: }
374:
375: auto_ptr <CommandLineInterface> CmdLine;
376: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.