fix little endian vs big endian in the macros... again... but this time correct
[RRG-proxmark3.git] / client / src / preferences.c
blob3228498f4278ec42c63b927c4040be35a37e53b2
1 //-----------------------------------------------------------------------------
2 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
3 // at your option, any later version. See the LICENSE.txt file for the text of
4 // the license.
5 //-----------------------------------------------------------------------------
6 // Preferences Functions
7 //-----------------------------------------------------------------------------
8 // Notes
9 // To add a new setting
10 // Add the new setting to the session_arg_t; in ui.h
11 // Add the default value for the setting in the settings_load page below
12 // Update the preferences_load_callback to load your setting into the stucture
13 // Update the preferences_save_callback to ensure your setting gets saved when needed.
14 // use the preference as needed : session.<preference name>
15 // Can use (session.preferences_loaded) to check if json settings file was used
16 //-----------------------------------------------------------------------------
18 #include "preferences.h"
19 #include "comms.h"
20 #include "emv/emvjson.h"
21 #include <string.h>
22 #include "cmdparser.h"
23 #include <ctype.h>
24 #include <dirent.h>
25 #include <proxmark3.h>
26 #include "cliparser.h"
28 static int CmdHelp(const char *Cmd);
29 static int setCmdHelp(const char *Cmd);
31 static char *prefGetFilename(void) {
32 char *path;
34 if (searchHomeFilePath(&path, NULL, preferencesFilename, false) == PM3_SUCCESS)
35 return path;
36 else
37 return strdup(preferencesFilename);
40 int preferences_load(void) {
42 // Set all defaults
43 session.client_debug_level = cdbOFF;
44 // session.device_debug_level = ddbOFF;
45 session.window_changed = false;
46 session.plot.x = 10;
47 session.plot.y = 30;
48 session.plot.h = 400;
49 session.plot.w = 800;
50 session.overlay.x = session.plot.x;
51 session.overlay.y = 60 + session.plot.y + session.plot.h;
52 session.overlay.h = 200;
53 session.overlay.w = session.plot.w;
54 session.overlay_sliders = true;
55 session.show_hints = true;
57 session.bar_mode = STYLE_VALUE;
58 setDefaultPath(spDefault, "");
59 setDefaultPath(spDump, "");
60 setDefaultPath(spTrace, "");
62 // default save path
63 if (get_my_user_directory() != NULL) // should return path to .proxmark3 folder
64 setDefaultPath(spDefault, get_my_user_directory());
65 else
66 setDefaultPath(spDefault, ".");
68 // default dump path
69 if (get_my_user_directory() != NULL) // should return path to .proxmark3 folder
70 setDefaultPath(spDump, get_my_user_directory());
71 else
72 setDefaultPath(spDump, ".");
74 // default dump path
75 if (get_my_user_directory() != NULL) // should return path to .proxmark3 folder
76 setDefaultPath(spTrace, get_my_user_directory());
77 else
78 setDefaultPath(spTrace, ".");
80 if (session.incognito) {
81 PrintAndLogEx(INFO, "No preferences file will be loaded");
82 return PM3_SUCCESS;
85 // loadFileJson wants these, so pass in place holder values, though not used
86 // in settings load;
87 uint8_t dummyData = 0x00;
88 size_t dummyDL = 0x00;
90 // to better control json cant find file error msg.
91 char *fn = prefGetFilename();
92 if (fileExists(fn)) {
93 if (loadFileJSON(fn, &dummyData, sizeof(dummyData), &dummyDL, &preferences_load_callback) == PM3_SUCCESS) {
94 session.preferences_loaded = true;
97 free(fn);
98 // Note, if session.settings_loaded == false then the settings_save
99 // will be called in main () to save settings as set in defaults and main() checks.
101 return PM3_SUCCESS;
104 // Save all settings from memory (struct) to file
105 int preferences_save(void) {
106 // Note sure if backup has value ?
107 if (session.incognito) {
108 PrintAndLogEx(INFO, "No preferences file will be saved");
109 return PM3_SUCCESS;
111 PrintAndLogEx(INFO, "Saving preferences...");
113 char *fn = prefGetFilename();
114 int fnLen = strlen(fn) + 5; // .bak\0
116 // [FILENAME_MAX+sizeof(preferencesFilename)+10]
117 char *backupFilename = (char *)calloc(fnLen, sizeof(uint8_t));
118 if (backupFilename == NULL) {
119 PrintAndLogEx(ERR, "failed to allocate memory");
120 free(fn);
121 return PM3_EMALLOC;
123 snprintf(backupFilename, fnLen, "%s.bak", fn);
125 if (fileExists(backupFilename)) {
126 if (remove(backupFilename) != 0) {
127 PrintAndLogEx(FAILED, "Error - could not delete old settings backup file \"%s\"", backupFilename);
128 free(fn);
129 free(backupFilename);
130 return PM3_ESOFT;
134 if (fileExists(fn)) {
135 if (rename(fn, backupFilename) != 0) {
136 PrintAndLogEx(FAILED, "Error - could not backup settings file \"%s\" to \"%s\"", fn, backupFilename);
137 free(fn);
138 free(backupFilename);
139 return PM3_ESOFT;
143 uint8_t dummyData = 0x00;
144 size_t dummyDL = 0x00;
146 if (saveFileJSON(fn, jsfCustom, &dummyData, dummyDL, &preferences_save_callback) != PM3_SUCCESS)
147 PrintAndLogEx(ERR, "Error saving preferences to \"%s\"", fn);
149 free(fn);
150 free(backupFilename);
151 return PM3_SUCCESS;
154 void preferences_save_callback(json_t *root) {
156 JsonSaveStr(root, "FileType", "settings");
158 // Emoji
159 switch (session.emoji_mode) {
160 case EMO_ALIAS:
161 JsonSaveStr(root, "show.emoji", "alias");
162 break;
163 case EMO_EMOJI:
164 JsonSaveStr(root, "show.emoji", "emoji");
165 break;
166 case EMO_ALTTEXT:
167 JsonSaveStr(root, "show.emoji", "alttext");
168 break;
169 case EMO_NONE:
170 JsonSaveStr(root, "show.emoji", "none");
171 break;
172 default:
173 JsonSaveStr(root, "show.emoji", "ALIAS");
176 JsonSaveBoolean(root, "show.hints", session.show_hints);
178 JsonSaveBoolean(root, "os.supports.colors", session.supports_colors);
180 JsonSaveStr(root, "file.default.savepath", session.defaultPaths[spDefault]);
181 JsonSaveStr(root, "file.default.dumppath", session.defaultPaths[spDump]);
182 JsonSaveStr(root, "file.default.tracepath", session.defaultPaths[spTrace]);
184 // Plot window
185 JsonSaveInt(root, "window.plot.xpos", session.plot.x);
186 JsonSaveInt(root, "window.plot.ypos", session.plot.y);
187 JsonSaveInt(root, "window.plot.hsize", session.plot.h);
188 JsonSaveInt(root, "window.plot.wsize", session.plot.w);
190 // Overlay/Slider window
191 JsonSaveInt(root, "window.overlay.xpos", session.overlay.x);
192 JsonSaveInt(root, "window.overlay.ypos", session.overlay.y);
193 JsonSaveInt(root, "window.overlay.hsize", session.overlay.h);
194 JsonSaveInt(root, "window.overlay.wsize", session.overlay.w);
195 JsonSaveBoolean(root, "window.overlay.sliders", session.overlay_sliders);
197 // Log level, convert to text
198 switch (session.client_debug_level) {
199 case cdbOFF:
200 JsonSaveStr(root, "client.debug.level", "off");
201 break;
202 case cdbSIMPLE:
203 JsonSaveStr(root, "client.debug.level", "simple");
204 break;
205 case cdbFULL:
206 JsonSaveStr(root, "client.debug.level", "full");
207 break;
208 default:
209 JsonSaveStr(root, "logging.level", "NORMAL");
212 switch (session.bar_mode) {
213 case STYLE_BAR:
214 JsonSaveStr(root, "show.bar.mode", "bar");
215 break;
216 case STYLE_MIXED:
217 JsonSaveStr(root, "show.bar.mode", "mixed");
218 break;
219 case STYLE_VALUE:
220 JsonSaveStr(root, "show.bar.mode", "value");
221 break;
222 default:
223 JsonSaveStr(root, "show.bar.mode", "value");
226 switch (session.device_debug_level) {
227 case ddbOFF:
228 JsonSaveStr(root, "device.debug.level", "off");
229 break;
230 case ddbERROR:
231 JsonSaveStr(root, "device.debug.level", "error");
232 break;
233 case ddbINFO:
234 JsonSaveStr(root, "device.debug.level", "info");
235 break;
236 case ddbDEBUG:
237 JsonSaveStr(root, "device.debug.level", "debug");
238 break;
239 case ddbEXTENDED:
240 JsonSaveStr(root, "device.debug.level", "extended");
241 break;
242 default:
243 JsonSaveStr(root, "logging.level", "NORMAL");
247 void preferences_load_callback(json_t *root) {
248 json_error_t up_error = {0};
249 int b1;
250 int i1;
251 const char *s1;
252 char tempStr [500]; // to use str_lower() since json unpack uses const char *
254 // Logging Level
255 if (json_unpack_ex(root, &up_error, 0, "{s:s}", "client.debug.level", &s1) == 0) {
256 strncpy(tempStr, s1, sizeof(tempStr) - 1);
257 str_lower(tempStr);
258 if (strncmp(tempStr, "off", 3) == 0) session.client_debug_level = cdbOFF;
259 if (strncmp(tempStr, "simple", 6) == 0) session.client_debug_level = cdbSIMPLE;
260 if (strncmp(tempStr, "full", 4) == 0) session.client_debug_level = cdbFULL;
263 // default save path
264 if (json_unpack_ex(root, &up_error, 0, "{s:s}", "file.default.savepath", &s1) == 0)
265 setDefaultPath(spDefault, s1);
267 // default dump path
268 if (json_unpack_ex(root, &up_error, 0, "{s:s}", "file.default.dumppath", &s1) == 0)
269 setDefaultPath(spDump, s1);
271 // default trace path
272 if (json_unpack_ex(root, &up_error, 0, "{s:s}", "file.default.tracepath", &s1) == 0)
273 setDefaultPath(spTrace, s1);
275 // window plot
276 if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.plot.xpos", &i1) == 0)
277 session.plot.x = i1;
278 if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.plot.ypos", &i1) == 0)
279 session.plot.y = i1;
280 if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.plot.hsize", &i1) == 0)
281 session.plot.h = i1;
282 if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.plot.wsize", &i1) == 0)
283 session.plot.w = i1;
285 // overlay/slider plot
286 if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.overlay.xpos", &i1) == 0)
287 session.overlay.x = i1;
288 if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.overlay.ypos", &i1) == 0)
289 session.overlay.y = i1;
290 if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.overlay.hsize", &i1) == 0)
291 session.overlay.h = i1;
292 if (json_unpack_ex(root, &up_error, 0, "{s:i}", "window.overlay.wsize", &i1) == 0)
293 session.overlay.w = i1;
294 if (json_unpack_ex(root, &up_error, 0, "{s:b}", "window.overlay.sliders", &b1) == 0)
295 session.overlay_sliders = (bool)b1;
297 // show options
298 if (json_unpack_ex(root, &up_error, 0, "{s:s}", "show.emoji", &s1) == 0) {
299 strncpy(tempStr, s1, sizeof(tempStr) - 1);
300 str_lower(tempStr);
301 if (strncmp(tempStr, "alias", 5) == 0) session.emoji_mode = EMO_ALIAS;
302 if (strncmp(tempStr, "emoji", 5) == 0) session.emoji_mode = EMO_EMOJI;
303 if (strncmp(tempStr, "alttext", 7) == 0) session.emoji_mode = EMO_ALTTEXT;
304 if (strncmp(tempStr, "none", 4) == 0) session.emoji_mode = EMO_NONE;
307 if (json_unpack_ex(root, &up_error, 0, "{s:b}", "show.hints", &b1) == 0)
308 session.show_hints = (bool)b1;
310 if (json_unpack_ex(root, &up_error, 0, "{s:b}", "os.supports.colors", &b1) == 0)
311 session.supports_colors = (bool)b1;
313 // bar mode
314 if (json_unpack_ex(root, &up_error, 0, "{s:s}", "show.bar.mode", &s1) == 0) {
315 strncpy(tempStr, s1, sizeof(tempStr) - 1);
316 str_lower(tempStr);
317 if (strncmp(tempStr, "bar", 5) == 0) session.bar_mode = STYLE_BAR;
318 if (strncmp(tempStr, "mixed", 5) == 0) session.bar_mode = STYLE_MIXED;
319 if (strncmp(tempStr, "value", 7) == 0) session.bar_mode = STYLE_VALUE;
323 // Logging Level
324 if (json_unpack_ex(root, &up_error, 0, "{s:s}", "device.debug.level", &s1) == 0) {
325 strncpy(tempStr, s1, sizeof(tempStr) - 1);
326 str_lower(tempStr);
327 if (strncmp(tempStr, "off", 3) == 0) session.device_debug_level = ddbOFF;
328 if (strncmp(tempStr, "error", 5) == 0) session.device_debug_level = ddbERROR;
329 if (strncmp(tempStr, "info", 4) == 0) session.device_debug_level = ddbINFO;
330 if (strncmp(tempStr, "debug", 5) == 0) session.device_debug_level = ddbDEBUG;
331 if (strncmp(tempStr, "extended", 8) == 0) session.device_debug_level = ddbEXTENDED;
336 // Help Functions
338 // Preference Processing Functions
339 // typedef enum preferenceId {prefNONE,prefHELP,prefEMOJI,prefCOLOR,prefPLOT,prefOVERLAY,prefHINTS,prefCLIENTDEBUG} preferenceId_t;
340 typedef enum prefShowOpt {prefShowNone, prefShowOLD, prefShowNEW} prefShowOpt_t;
342 static const char *prefShowMsg(prefShowOpt_t Opt) {
343 switch (Opt) {
344 case prefShowOLD:
345 return "( " _YELLOW_("old") " )";
346 case prefShowNEW:
347 return "( " _GREEN_("new") " )";
348 case prefShowNone:
349 return "";
351 return "";
354 static void showEmojiState(prefShowOpt_t opt) {
356 switch (session.emoji_mode) {
357 case EMO_ALIAS:
358 PrintAndLogEx(INFO, " %s emoji.................. "_GREEN_("alias"), prefShowMsg(opt));
359 break;
360 case EMO_EMOJI:
361 PrintAndLogEx(INFO, " %s emoji.................. "_GREEN_("emoji"), prefShowMsg(opt));
362 break;
363 case EMO_ALTTEXT:
364 PrintAndLogEx(INFO, " %s emoji.................. "_GREEN_("alttext"), prefShowMsg(opt));
365 break;
366 case EMO_NONE:
367 PrintAndLogEx(INFO, " %s emoji.................. "_GREEN_("none"), prefShowMsg(opt));
368 break;
369 default:
370 PrintAndLogEx(INFO, " %s emoji.................. "_RED_("unknown"), prefShowMsg(opt));
374 static void showColorState(prefShowOpt_t opt) {
376 if (session.supports_colors)
377 PrintAndLogEx(INFO, " %s color.................. "_GREEN_("ansi"), prefShowMsg(opt));
378 else
379 PrintAndLogEx(INFO, " %s color.................. "_WHITE_("off"), prefShowMsg(opt));
382 static void showClientDebugState(prefShowOpt_t opt) {
384 switch (session.client_debug_level) {
385 case cdbOFF:
386 PrintAndLogEx(INFO, " %s client debug........... "_WHITE_("off"), prefShowMsg(opt));
387 break;
388 case cdbSIMPLE:
389 PrintAndLogEx(INFO, " %s client debug........... "_GREEN_("simple"), prefShowMsg(opt));
390 break;
391 case cdbFULL:
392 PrintAndLogEx(INFO, " %s client debug........... "_GREEN_("full"), prefShowMsg(opt));
393 break;
394 default:
395 PrintAndLogEx(INFO, " %s client debug........... "_RED_("unknown"), prefShowMsg(opt));
399 static void showDeviceDebugState(prefShowOpt_t opt) {
400 switch (session.device_debug_level) {
401 case ddbOFF:
402 PrintAndLogEx(INFO, " %s device debug........... "_WHITE_("off"), prefShowMsg(opt));
403 break;
404 case ddbERROR:
405 PrintAndLogEx(INFO, " %s device debug........... "_GREEN_("error"), prefShowMsg(opt));
406 break;
407 case ddbINFO:
408 PrintAndLogEx(INFO, " %s device debug........... "_GREEN_("info"), prefShowMsg(opt));
409 break;
410 case ddbDEBUG:
411 PrintAndLogEx(INFO, " %s device debug........... "_GREEN_("debug"), prefShowMsg(opt));
412 break;
413 case ddbEXTENDED:
414 PrintAndLogEx(INFO, " %s device debug........... "_GREEN_("extended"), prefShowMsg(opt));
415 break;
416 default:
417 PrintAndLogEx(INFO, " %s device debug........... "_RED_("unknown"), prefShowMsg(opt));
422 static void showSavePathState(savePaths_t path_index, prefShowOpt_t opt) {
424 char s[50];
425 switch (path_index) {
426 case spDefault:
427 strcpy(s, "default save path......");
428 break;
429 case spDump:
430 strcpy(s, "dump save path.........");
431 break;
432 case spTrace:
433 strcpy(s, "trace save path........");
434 break;
435 case spItemCount:
436 default:
437 strcpy(s, _RED_("unknown")" save path......");
440 if (path_index < spItemCount) {
441 if ((session.defaultPaths[path_index] == NULL) || (strcmp(session.defaultPaths[path_index], "") == 0)) {
442 PrintAndLogEx(INFO, " %s %s "_WHITE_("not set"),
443 prefShowMsg(opt),
446 } else {
447 PrintAndLogEx(INFO, " %s %s "_GREEN_("%s"),
448 prefShowMsg(opt),
450 session.defaultPaths[path_index]
456 static void showPlotPosState(void) {
457 PrintAndLogEx(INFO, " Plot window............ X "_GREEN_("%4d")" Y "_GREEN_("%4d")" H "_GREEN_("%4d")" W "_GREEN_("%4d"),
458 session.plot.x,
459 session.plot.y,
460 session.plot.h,
461 session.plot.w
465 static void showOverlayPosState(void) {
466 PrintAndLogEx(INFO, " Slider/Overlay window.. X "_GREEN_("%4d")" Y "_GREEN_("%4d")" H "_GREEN_("%4d")" W "_GREEN_("%4d"),
467 session.overlay.x,
468 session.overlay.y,
469 session.overlay.h,
470 session.overlay.w
474 static void showHintsState(prefShowOpt_t opt) {
475 if (session.show_hints)
476 PrintAndLogEx(INFO, " %s hints.................. "_GREEN_("on"), prefShowMsg(opt));
477 else
478 PrintAndLogEx(INFO, " %s hints.................. "_WHITE_("off"), prefShowMsg(opt));
481 static void showPlotSliderState(prefShowOpt_t opt) {
482 if (session.overlay_sliders)
483 PrintAndLogEx(INFO, " %s show plot sliders...... "_GREEN_("on"), prefShowMsg(opt));
484 else
485 PrintAndLogEx(INFO, " %s show plot sliders...... "_WHITE_("off"), prefShowMsg(opt));
488 static void showBarModeState(prefShowOpt_t opt) {
490 switch (session.bar_mode) {
491 case STYLE_BAR:
492 PrintAndLogEx(INFO, " %s barmode................ "_GREEN_("bar"), prefShowMsg(opt));
493 break;
494 case STYLE_MIXED:
495 PrintAndLogEx(INFO, " %s barmode................ "_GREEN_("mixed"), prefShowMsg(opt));
496 break;
497 case STYLE_VALUE:
498 PrintAndLogEx(INFO, " %s barmode................ "_GREEN_("value"), prefShowMsg(opt));
499 break;
500 default:
501 PrintAndLogEx(INFO, " %s barmode............... "_RED_("unknown"), prefShowMsg(opt));
505 static int setCmdEmoji(const char *Cmd) {
506 CLIParserContext *ctx;
507 CLIParserInit(&ctx, "prefs set emoji ",
508 "Set presistent preference of using emojis in the client",
509 "prefs set emoji --alias"
512 void *argtable[] = {
513 arg_param_begin,
514 arg_lit0(NULL, "alias", "show alias for emoji"),
515 arg_lit0(NULL, "emoji", "show emoji"),
516 arg_lit0(NULL, "alttext", "show alt text for emoji"),
517 arg_lit0(NULL, "none", "don't show emoji or text"),
518 arg_param_end
520 CLIExecWithReturn(ctx, Cmd, argtable, true);
521 bool show_a = arg_get_lit(ctx, 1);
522 bool show_e = arg_get_lit(ctx, 2);
523 bool show_alt = arg_get_lit(ctx, 3);
524 bool show_none = arg_get_lit(ctx, 4);
525 CLIParserFree(ctx);
527 if ((show_a + show_e + show_alt + show_none) > 1) {
528 PrintAndLogEx(FAILED, "Can only set one option");
529 return PM3_EINVARG;
532 emojiMode_t new_value = session.emoji_mode;
534 if (show_a) {
535 new_value = EMO_ALIAS;
537 if (show_e) {
538 new_value = EMO_EMOJI;
540 if (show_alt) {
541 new_value = EMO_ALTTEXT;
543 if (show_none) {
544 new_value = EMO_NONE;
547 if (session.emoji_mode != new_value) {// changed
548 showEmojiState(prefShowOLD);
549 session.emoji_mode = new_value;
550 showEmojiState(prefShowNEW);
551 preferences_save();
552 } else {
553 showEmojiState(prefShowNone);
556 return PM3_SUCCESS;
559 static int setCmdColor(const char *Cmd) {
560 CLIParserContext *ctx;
561 CLIParserInit(&ctx, "prefs set color ",
562 "Set presistent preference of using colors in the client",
563 "prefs set color --ansi"
566 void *argtable[] = {
567 arg_param_begin,
568 arg_lit0(NULL, "ansi", "use ANSI colors"),
569 arg_lit0(NULL, "off", "don't use colors"),
570 arg_param_end
572 CLIExecWithReturn(ctx, Cmd, argtable, true);
573 bool use_c = arg_get_lit(ctx, 1);
574 bool use_n = arg_get_lit(ctx, 2);
575 CLIParserFree(ctx);
577 if ((use_c + use_n) > 1) {
578 PrintAndLogEx(FAILED, "Can only set one option");
579 return PM3_EINVARG;
582 bool new_value = session.supports_colors;
583 if (use_c) {
584 new_value = true;
587 if (use_n) {
588 new_value = false;
591 if (session.supports_colors != new_value) {
592 showColorState(prefShowOLD);
593 session.supports_colors = new_value;
594 showColorState(prefShowNEW);
595 preferences_save();
596 } else {
597 showColorState(prefShowNone);
600 return PM3_SUCCESS;
603 static int setCmdDebug(const char *Cmd) {
604 CLIParserContext *ctx;
605 CLIParserInit(&ctx, "prefs set clientdebug ",
606 "Set presistent preference of using clientside debug level",
607 "prefs set clientdebug --simple"
610 void *argtable[] = {
611 arg_param_begin,
612 arg_lit0(NULL, "off", "no debug messages"),
613 arg_lit0(NULL, "simple", "simple debug messages"),
614 arg_lit0(NULL, "full", "full debug messages"),
615 arg_param_end
617 CLIExecWithReturn(ctx, Cmd, argtable, true);
618 bool use_off = arg_get_lit(ctx, 1);
619 bool use_simple = arg_get_lit(ctx, 2);
620 bool use_full = arg_get_lit(ctx, 3);
621 CLIParserFree(ctx);
623 if ((use_off + use_simple + use_full) > 1) {
624 PrintAndLogEx(FAILED, "Can only set one option");
625 return PM3_EINVARG;
628 clientdebugLevel_t new_value = session.client_debug_level;
630 if (use_off) {
631 new_value = cdbOFF;
633 if (use_simple) {
634 new_value = cdbSIMPLE;
636 if (use_full) {
637 new_value = cdbFULL;
640 if (session.client_debug_level != new_value) {
641 showClientDebugState(prefShowOLD);
642 session.client_debug_level = new_value;
643 g_debugMode = new_value;
644 showClientDebugState(prefShowNEW);
645 preferences_save();
646 } else {
647 showClientDebugState(prefShowNone);
650 return PM3_SUCCESS;
653 static int setCmdDeviceDebug (const char *Cmd)
655 CLIParserContext *ctx;
656 CLIParserInit(&ctx, "prefs set devicedebug ",
657 "Set presistent preference of device side debug level",
658 "prefs set devicedebug --on"
661 void *argtable[] = {
662 arg_param_begin,
663 arg_lit0(NULL, "off", "no debug messages"),
664 arg_lit0(NULL, "error", "error messages"),
665 arg_lit0(NULL, "info", "info messages"),
666 arg_lit0(NULL, "dbg", "debug messages"),
667 arg_lit0(NULL, "ext", "extended debug messages"),
668 arg_param_end
670 CLIExecWithReturn(ctx, Cmd, argtable, true);
671 bool use_off = arg_get_lit(ctx, 1);
672 bool use_err = arg_get_lit(ctx, 2);
673 bool use_info = arg_get_lit(ctx, 3);
674 bool use_dbg = arg_get_lit(ctx, 4);
675 bool use_ext = arg_get_lit(ctx, 5);
676 CLIParserFree(ctx);
678 if ( (use_off + use_err + use_info + use_dbg + use_ext) > 1) {
679 PrintAndLogEx(FAILED, "Can only set one option");
680 return PM3_EINVARG;
683 devicedebugLevel_t new_value = session.device_debug_level;
685 if (use_off) {
686 new_value = ddbOFF;
688 if (use_err) {
689 new_value = ddbERROR;
691 if (use_info) {
692 new_value = ddbINFO;
694 if (use_dbg) {
695 new_value = ddbDEBUG;
697 if (use_ext) {
698 new_value = ddbEXTENDED;
701 if (session.device_debug_level != new_value) {// changed
702 showDeviceDebugState (prefShowOLD);
703 session.device_debug_level = new_value;
704 showDeviceDebugState (prefShowNEW);
705 preferences_save();
706 } else {
707 showDeviceDebugState (prefShowNone);
710 if (session.pm3_present) {
711 PrintAndLogEx (INFO,"setting device debug loglevel");
712 SendCommandNG(CMD_SET_DBGMODE, &session.device_debug_level, 1);
713 PacketResponseNG resp;
714 if (WaitForResponseTimeout(CMD_SET_DBGMODE, &resp, 2000) == false)
715 PrintAndLogEx (WARNING,"failed to set device debug loglevel");
717 return PM3_SUCCESS;
721 static int setCmdHint(const char *Cmd) {
722 CLIParserContext *ctx;
723 CLIParserInit(&ctx, "prefs set hints ",
724 "Set presistent preference of showing hint messages in the client",
725 "prefs set hints --on"
728 void *argtable[] = {
729 arg_param_begin,
730 arg_lit0(NULL, "off", "hide hints"),
731 arg_lit0(NULL, "on", "show hints"),
732 arg_param_end
734 CLIExecWithReturn(ctx, Cmd, argtable, true);
735 bool use_off = arg_get_lit(ctx, 1);
736 bool use_on = arg_get_lit(ctx, 2);
737 CLIParserFree(ctx);
739 if ((use_off + use_on) > 1) {
740 PrintAndLogEx(FAILED, "Can only set one option");
741 return PM3_EINVARG;
744 bool new_value = session.show_hints;
745 if (use_off) {
746 new_value = false;
748 if (use_on) {
749 new_value = true;
752 if (session.show_hints != new_value) {
753 showHintsState(prefShowOLD);
754 session.show_hints = new_value;
755 showHintsState(prefShowNEW);
756 preferences_save();
757 } else {
758 showHintsState(prefShowNone);
761 return PM3_SUCCESS;
764 static int setCmdPlotSliders(const char *Cmd) {
765 CLIParserContext *ctx;
766 CLIParserInit(&ctx, "prefs set plotsliders",
767 "Set presistent preference of showing the plotslider control in the client",
768 "prefs set plotsliders --on"
771 void *argtable[] = {
772 arg_param_begin,
773 arg_lit0(NULL, "off", "hide plot slider controls"),
774 arg_lit0(NULL, "on", "show plot slider controls"),
775 arg_param_end
777 CLIExecWithReturn(ctx, Cmd, argtable, true);
778 bool use_off = arg_get_lit(ctx, 1);
779 bool use_on = arg_get_lit(ctx, 2);
780 CLIParserFree(ctx);
782 if ((use_off + use_on) > 1) {
783 PrintAndLogEx(FAILED, "Can only set one option");
784 return PM3_EINVARG;
787 bool new_value = session.overlay_sliders;
788 if (use_off) {
789 new_value = false;
791 if (use_on) {
792 new_value = true;
795 if (session.overlay_sliders != new_value) {
796 showPlotSliderState(prefShowOLD);
797 session.overlay_sliders = new_value;
798 showPlotSliderState(prefShowNEW);
799 preferences_save();
800 } else {
801 showPlotSliderState(prefShowNone);
803 return PM3_SUCCESS;
806 static int setCmdSavePaths(const char *Cmd) {
807 CLIParserContext *ctx;
808 CLIParserInit(&ctx, "prefs set savepaths",
809 "Set presistent preference of file paths in the client",
810 "prefs set savepaths --dump /home/mydumpfolder -> all dump files will be saved into this folder\n"
811 "prefs set savepaths --def /home/myfolder -c -> create if needed, all files will be saved into this folder"
814 void *argtable[] = {
815 arg_param_begin,
816 arg_lit0("c", "create", "create directory if it does not exist"),
817 arg_str0(NULL, "def", "<path>", "default path"),
818 arg_str0(NULL, "dump", "<path>", "dump file path"),
819 arg_str0(NULL, "trace", "<path>", "trace path"),
820 arg_param_end
822 CLIExecWithReturn(ctx, Cmd, argtable, true);
823 bool create_dir = arg_get_lit(ctx, 1);
825 int deflen = 0;
826 char def_path[FILE_PATH_SIZE] = {0};
827 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)def_path, FILE_PATH_SIZE, &deflen);
829 int dulen = 0;
830 char dump_path[FILE_PATH_SIZE] = {0};
831 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)dump_path, FILE_PATH_SIZE, &dulen);
833 int tlen = 0;
834 char trace_path[FILE_PATH_SIZE] = {0};
835 CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)trace_path, FILE_PATH_SIZE, &tlen);
836 CLIParserFree(ctx);
838 if (deflen == 0 && dulen == 0 && tlen == 0) {
839 PrintAndLogEx(FAILED, "Must give at least one path");
840 return PM3_EINVARG;
843 savePaths_t path_item = spItemCount;
844 char *path = NULL;
845 if (deflen) {
846 path_item = spDefault;
847 path = def_path;
849 if (dulen) {
850 path_item = spDump;
851 path = dump_path;
853 if (tlen) {
854 path_item = spTrace;
855 path = trace_path;
858 // remove trailing slash.
859 size_t nplen = strlen(path);
860 if ((path[nplen - 1] == '/') || (path[nplen - 1] == '\\')) {
861 path[nplen - 1] = 0x00;
864 // Check path
865 if (fileExists(path) == false && create_dir == false) {
866 PrintAndLogEx(ERR, "path does not exist... "_RED_("%s"), path);
869 // do we need to create it
870 // if (!fileExists(newValue))
871 // create_path (newValue); //mkdir (newValue,0x777);
873 if (path_item < spItemCount) {
874 if (strcmp(path, session.defaultPaths[path_item]) != 0) {
875 showSavePathState(path_item, prefShowOLD);
876 setDefaultPath(path_item, path);
877 showSavePathState(path_item, prefShowNEW);
878 preferences_save();
879 } else {
880 showSavePathState(path_item, prefShowNone);
884 return PM3_SUCCESS;
887 static int setCmdBarMode(const char *Cmd) {
888 CLIParserContext *ctx;
889 CLIParserInit(&ctx, "prefs set barmode",
890 "Set presistent preference of HF/LF tune command styled output in the client",
891 "prefs set barmode --mix"
894 void *argtable[] = {
895 arg_param_begin,
896 arg_lit0(NULL, "bar", "measured values as bar only"),
897 arg_lit0(NULL, "mix", "measured values as numbers and bar"),
898 arg_lit0(NULL, "val", "measured values only"),
899 arg_param_end
901 CLIExecWithReturn(ctx, Cmd, argtable, true);
902 bool show_bar = arg_get_lit(ctx, 1);
903 bool show_mix = arg_get_lit(ctx, 2);
904 bool show_val = arg_get_lit(ctx, 3);
905 CLIParserFree(ctx);
907 if ((show_bar + show_mix + show_val) > 1) {
908 PrintAndLogEx(FAILED, "Can only set one option");
909 return PM3_EINVARG;
912 barMode_t new_value = session.bar_mode;
913 if (show_bar) {
914 new_value = STYLE_BAR;
916 if (show_mix) {
917 new_value = STYLE_MIXED;
919 if (show_val) {
920 new_value = STYLE_VALUE;
923 if (session.bar_mode != new_value) {
924 showBarModeState(prefShowOLD);
925 session.bar_mode = new_value;
926 showBarModeState(prefShowNEW);
927 preferences_save();
928 } else {
929 showBarModeState(prefShowNone);
931 return PM3_SUCCESS;
934 static int getCmdEmoji(const char *Cmd) {
935 CLIParserContext *ctx;
936 CLIParserInit(&ctx, "prefs get emoji",
937 "Get preference of using emojis in the client",
938 "prefs get emoji"
940 void *argtable[] = {
941 arg_param_begin,
942 arg_param_end
944 CLIExecWithReturn(ctx, Cmd, argtable, true);
945 CLIParserFree(ctx);
946 showEmojiState(prefShowNone);
947 return PM3_SUCCESS;
950 static int getCmdHint(const char *Cmd) {
951 CLIParserContext *ctx;
952 CLIParserInit(&ctx, "prefs get hints",
953 "Get preference of showing hint messages in the client",
954 "prefs get hints"
956 void *argtable[] = {
957 arg_param_begin,
958 arg_param_end
960 CLIExecWithReturn(ctx, Cmd, argtable, true);
961 CLIParserFree(ctx);
962 showHintsState(prefShowNone);
963 return PM3_SUCCESS;
966 static int getCmdColor(const char *Cmd) {
967 CLIParserContext *ctx;
968 CLIParserInit(&ctx, "prefs get color",
969 "Get preference of using colors in the client",
970 "prefs get color"
972 void *argtable[] = {
973 arg_param_begin,
974 arg_param_end
976 CLIExecWithReturn(ctx, Cmd, argtable, true);
977 CLIParserFree(ctx);
978 showColorState(prefShowNone);
979 return PM3_SUCCESS;
982 static int getCmdDebug(const char *Cmd) {
983 CLIParserContext *ctx;
984 CLIParserInit(&ctx, "prefs get clientdebug",
985 "Get preference of using clientside debug level",
986 "prefs get clientdebug"
988 void *argtable[] = {
989 arg_param_begin,
990 arg_param_end
992 CLIExecWithReturn(ctx, Cmd, argtable, true);
993 CLIParserFree(ctx);
994 showClientDebugState(prefShowNone);
995 return PM3_SUCCESS;
998 static int getCmdPlotSlider(const char *Cmd) {
999 CLIParserContext *ctx;
1000 CLIParserInit(&ctx, "prefs get plotsliders",
1001 "Get preference of showing the plotslider control in the client",
1002 "prefs get plotsliders"
1004 void *argtable[] = {
1005 arg_param_begin,
1006 arg_param_end
1008 CLIExecWithReturn(ctx, Cmd, argtable, true);
1009 CLIParserFree(ctx);
1010 showPlotSliderState(prefShowNone);
1011 return PM3_SUCCESS;
1014 static int getCmdBarMode(const char *Cmd) {
1015 CLIParserContext *ctx;
1016 CLIParserInit(&ctx, "prefs get barmode",
1017 "Get preference of HF/LF tune command styled output in the client",
1018 "prefs get barmode"
1020 void *argtable[] = {
1021 arg_param_begin,
1022 arg_param_end
1024 CLIExecWithReturn(ctx, Cmd, argtable, true);
1025 CLIParserFree(ctx);
1026 showBarModeState(prefShowNone);
1027 return PM3_SUCCESS;
1030 static int getCmdSavePaths(const char *Cmd) {
1031 CLIParserContext *ctx;
1032 CLIParserInit(&ctx, "prefs get savepaths",
1033 "Get preference of file paths in the client",
1034 "prefs get savepaths"
1036 void *argtable[] = {
1037 arg_param_begin,
1038 arg_param_end
1040 CLIExecWithReturn(ctx, Cmd, argtable, true);
1041 CLIParserFree(ctx);
1042 showSavePathState(spDefault, prefShowNone);
1043 showSavePathState(spDump, prefShowNone);
1044 showSavePathState(spTrace, prefShowNone);
1045 return PM3_SUCCESS;
1048 static command_t CommandTableGet[] = {
1049 {"barmode", getCmdBarMode, AlwaysAvailable, "Get bar mode preference"},
1050 {"clientdebug", getCmdDebug, AlwaysAvailable, "Get client debug level preference"},
1051 {"color", getCmdColor, AlwaysAvailable, "Get color support preference"},
1052 {"savepaths", getCmdSavePaths, AlwaysAvailable, "Get file folder "},
1053 // {"devicedebug", getCmdDeviceDebug, AlwaysAvailable, "Get device debug level"},
1054 {"emoji", getCmdEmoji, AlwaysAvailable, "Get emoji display preference"},
1055 {"hints", getCmdHint, AlwaysAvailable, "Get hint display preference"},
1056 {"plotsliders", getCmdPlotSlider, AlwaysAvailable, "Get plot slider display preference"},
1057 {NULL, NULL, NULL, NULL}
1060 static command_t CommandTableSet[] = {
1061 {"help", setCmdHelp, AlwaysAvailable, "This help"},
1062 {"barmode", setCmdBarMode, AlwaysAvailable, "Set bar mode"},
1063 {"clientdebug", setCmdDebug, AlwaysAvailable, "Set client debug level"},
1064 {"color", setCmdColor, AlwaysAvailable, "Set color support"},
1065 {"emoji", setCmdEmoji, AlwaysAvailable, "Set emoji display"},
1066 {"hints", setCmdHint, AlwaysAvailable, "Set hint display"},
1067 {"savepaths", setCmdSavePaths, AlwaysAvailable, "... to be adjusted next ... "},
1068 // {"devicedebug", setCmdDeviceDebug, AlwaysAvailable, "Set device debug level"},
1069 {"plotsliders", setCmdPlotSliders, AlwaysAvailable, "Set plot slider display"},
1070 {NULL, NULL, NULL, NULL}
1073 static int setCmdHelp(const char *Cmd) {
1074 (void)Cmd; // Cmd is not used so far
1075 CmdsHelp(CommandTableSet);
1076 return PM3_SUCCESS;
1079 static int CmdPrefGet(const char *Cmd) {
1080 clearCommandBuffer();
1081 return CmdsParse(CommandTableGet, Cmd);
1084 static int CmdPrefSet(const char *Cmd) {
1085 clearCommandBuffer();
1086 return CmdsParse(CommandTableSet, Cmd);
1089 static int CmdPrefShow(const char *Cmd) {
1090 CLIParserContext *ctx;
1091 CLIParserInit(&ctx, "prefs show",
1092 "Show all persistent preferences",
1093 "prefs show"
1095 void *argtable[] = {
1096 arg_param_begin,
1097 arg_param_end
1099 CLIExecWithReturn(ctx, Cmd, argtable, true);
1100 CLIParserFree(ctx);
1102 if (session.preferences_loaded) {
1103 char *fn = prefGetFilename();
1104 PrintAndLogEx(NORMAL, "");
1105 PrintAndLogEx(INFO, "Using "_YELLOW_("%s"), fn);
1106 free(fn);
1107 } else {
1108 PrintAndLogEx(WARNING, "Preferences file not loaded");
1111 PrintAndLogEx(INFO, "Current settings");
1112 showEmojiState(prefShowNone);
1113 showHintsState(prefShowNone);
1114 showColorState(prefShowNone);
1115 showPlotPosState();
1116 showOverlayPosState();
1117 showSavePathState(spDefault, prefShowNone);
1118 showSavePathState(spDump, prefShowNone);
1119 showSavePathState(spTrace, prefShowNone);
1120 showClientDebugState(prefShowNone);
1121 showPlotSliderState(prefShowNone);
1122 // showDeviceDebugState(prefShowNone);
1124 showBarModeState(prefShowNone);
1125 PrintAndLogEx(NORMAL, "");
1126 return PM3_SUCCESS;
1129 static int CmdPrefSave (const char *Cmd) {
1130 preferences_save();
1131 return PM3_SUCCESS;
1134 static command_t CommandTable[] = {
1135 {"help", CmdHelp, AlwaysAvailable, "This help"},
1136 {"get", CmdPrefGet, AlwaysAvailable, "{ Get a preference }"},
1137 {"set", CmdPrefSet, AlwaysAvailable, "{ Set a preference }"},
1138 {"show", CmdPrefShow, AlwaysAvailable, "Show all preferences"},
1139 {NULL, NULL, NULL, NULL}
1142 static int CmdHelp(const char *Cmd) {
1143 (void)Cmd; // Cmd is not used so far
1144 CmdsHelp(CommandTable);
1145 return PM3_SUCCESS;
1148 int CmdPreferences(const char *Cmd) {
1149 clearCommandBuffer();
1150 return CmdsParse(CommandTable, Cmd);