Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IR improvements, reworked enc files, added scripts menu #280

Merged
merged 3 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/core/VectorDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,9 @@ class SerialDisplayClass : public VectorDisplayClass {
VectorDisplayClass::begin(width, height);
}

bool getSwapBytes(void) { return false; } // stub
void setSwapBytes(bool swap) { return; } // stub

virtual void begin(int width=VECTOR_DISPLAY_DEFAULT_WIDTH, int height=VECTOR_DISPLAY_DEFAULT_HEIGHT) override {
begin(115200, width, height);
}
Expand Down
41 changes: 37 additions & 4 deletions src/core/display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,43 @@ void displayRedStripe(String text, uint16_t fgcolor, uint16_t bgcolor) {
tft.println(text);
}

void displayError(String txt) { displayRedStripe(txt); }
void displayWarning(String txt) { displayRedStripe(txt, TFT_BLACK,TFT_YELLOW); }
void displayInfo(String txt) { displayRedStripe(txt, TFT_WHITE, TFT_BLUE); }
void displaySuccess(String txt) { displayRedStripe(txt, TFT_WHITE, TFT_DARKGREEN); }
void displayError(String txt) {
#ifndef HAS_SCREEN
Serial.println("ERR: " + txt);
return;
#endif
displayRedStripe(txt);
while(!checkAnyKeyPress()) delay(100);
}

void displayWarning(String txt) {
#ifndef HAS_SCREEN
Serial.println("WARN: " + txt);
return;
#endif
displayRedStripe(txt, TFT_BLACK,TFT_YELLOW);
while(!checkAnyKeyPress()) delay(100);
}

void displayInfo(String txt) {
#ifndef HAS_SCREEN
Serial.println("INFO: " + txt);
return;
#endif
// todo: add newlines to txt if too long
displayRedStripe(txt, TFT_WHITE, TFT_BLUE);
while(!checkAnyKeyPress()) delay(100);
}

void displaySuccess(String txt) {
#ifndef HAS_SCREEN
Serial.println("SUCCESS: " + txt);
return;
#endif
// todo: add newlines to txt if too long
displayRedStripe(txt, TFT_WHITE, TFT_DARKGREEN);
while(!checkAnyKeyPress()) delay(100);
}

void setPadCursor(int16_t padx, int16_t pady) {
for (int y=0; y<pady; y++) tft.println();
Expand Down
3 changes: 3 additions & 0 deletions src/core/main_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ MainMenu::MainMenu() {
&othersMenu,
&clockMenu,
&configMenu,
#if !defined(CORE) && !defined(CORE2)
&scriptsMenu,
#endif
};

_totalItems = _menuItems.size();
Expand Down
2 changes: 2 additions & 0 deletions src/core/main_menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "menu_items/RFIDMenu.h"
#include "menu_items/RFMenu.h"
#include "menu_items/WifiMenu.h"
#include "menu_items/ScriptsMenu.h"


class MainMenu {
Expand All @@ -25,6 +26,7 @@ class MainMenu {
RFIDMenu rfidMenu;
RFMenu rfMenu;
WifiMenu wifiMenu;
ScriptsMenu scriptsMenu;

MainMenu();
~MainMenu();
Expand Down
56 changes: 56 additions & 0 deletions src/core/menu_items/ScriptsMenu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

#include "ScriptsMenu.h"
#include "core/display.h"
#include "core/settings.h"
#include "modules/bjs_interpreter/interpreter.h" // for JavaScript interpreter


void ScriptsMenu::optionsMenu() {

String Folder = "/scripts";
FS* fs = NULL;
if(SD.exists(Folder)) fs = &SD;
if(LittleFS.exists(Folder)) fs = &LittleFS;
if(!fs) return; // dir not found

//String fileList[MAXFILES][3];
//readFs(fs, Folder, fileList, "bjs");

options = { };

File root = fs->open(Folder);
if (!root || !root.isDirectory()) return; // not a dir
File file2 = root.openNextFile();

while (file2) {
if (file2.isDirectory()) continue;
String fileName = String(file2.name());
if( ! fileName.endsWith(".js") && ! fileName.endsWith(".bjs")) continue;
// else append to the choices
String entry_title = String(file2.name()); entry_title = entry_title.substring(0, entry_title.lastIndexOf(".")); // remove the extension
options.push_back({entry_title.c_str(), [=]() { run_bjs_script_headless(*fs, file2.path()); }});
file2 = root.openNextFile();
}
file2.close();
root.close();

options.push_back({"Load...", [=]() { run_bjs_script(); }});
options.push_back({"Main Menu", [=]() { backToMenu(); }});

delay(200);
loopOptions(options,false,true,"Scripts");
}

String ScriptsMenu::getName() {
return _name;
}

void ScriptsMenu::draw() {
// draw the icon
tft.fillRect(iconX,iconY,80,80,BGCOLOR);
int i=0;
for(i=0;i<6;i++) {
tft.drawArc(40+iconX,40+iconY,30,20,15+60*i,45+60*i,FGCOLOR,BGCOLOR,true);
}
tft.drawArc(40+iconX,40+iconY,22,8,0,360,FGCOLOR,BGCOLOR,false);
}
18 changes: 18 additions & 0 deletions src/core/menu_items/ScriptsMenu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef __SCRIPTS_MENU_H__
#define __SCRIPTS_MENU_H__

#include "MenuItemInterface.h"


class ScriptsMenu : public MenuItemInterface {
public:
void optionsMenu(void);
void draw(void);
String getName(void);

private:
String _name = "Scripts";

};

#endif
171 changes: 162 additions & 9 deletions src/core/passwords.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@
#include <Arduino.h>
#include <MD5Builder.h>

#include "passwords.h"
#include "globals.h"
#include "sd_functions.h"
#include "mykeyboard.h"
#include "modules/rf/rf.h" //for hexCharToDecimal

String xorEncryptDecrypt(const String &input, const String &password) {
uint8_t md5Hash[16];

String xorEncryptDecryptMD5(const String &input, const String &password, const int MD5_PASSES) {

MD5Builder md5;
md5.begin();
md5.add(password);
md5.calculate();
String hash = password;

for (int i = 0; i < MD5_PASSES; i++) {
md5.begin();
md5.add(hash);
md5.calculate();
}

uint8_t md5Hash[16];
md5.getBytes(md5Hash); // Store MD5 hash in the output array

String output = input; // Copy input to output for modification
Expand All @@ -22,11 +33,153 @@ String xorEncryptDecrypt(const String &input, const String &password) {



bool isValidAscii(const String &text) {
for (int i = 0; i < text.length(); i++) {
char c = text[i];
// Check if the character is within the printable ASCII range or is a newline/carriage return
if (!(c >= 32 && c <= 126) && c != 10 && c != 13) {
return false; // Invalid character found
}
}
return true; // All characters are valid
}

/* OLD:
String readDecryptedFileOLD(FS &fs, String filepath) {
String cyphertext = readSmallFile(fs, filepath);
if(cyphertext.length() == 0) return "";

if(cachedPassword.length()==0) {
cachedPassword = keyboard("", 32, "password");
if(cachedPassword.length()==0) return ""; // cancelled
}

//Serial.println(cyphertext);
//Serial.println(cachedPassword);

// else try to decrypt
String plaintext = decryptString(cyphertext, cachedPassword);

// check if really plaintext
if(!isValidAscii(plaintext)) {
// invalidate cached password -> will ask again on the next try
cachedPassword = "";
Serial.println("invalid password");
//Serial.println(plaintext);
return "";
}

// else
return plaintext;
}
*/

String readDecryptedFile(FS &fs, String filepath) {

if(cachedPassword.length()==0) {
cachedPassword = keyboard("", 32, "password");
if(cachedPassword.length()==0) return ""; // cancelled
}

File cyphertextFile = fs.open(filepath, FILE_READ);
if(!cyphertextFile) return "";

String line;
String cypertextData = "";
String plaintext = "";
bool unsupported_params = false;

while (cyphertextFile.available() ) {
line = cyphertextFile.readStringUntil('\n');
if(line.startsWith("Filetype:") && !line.endsWith("Bruce Encrypted File")) unsupported_params = true;
if(line.startsWith("Algo:") && !line.endsWith("XOR")) unsupported_params = true;
if(line.startsWith("KeyDerivationAlgo:") && !line.endsWith("MD5")) unsupported_params = true;
if(line.startsWith("KeyDerivationPasses:") && !line.endsWith("10")) unsupported_params = true; // TODO: parse
if(line.startsWith("Data:")) cypertextData = line.substring(strlen("Data:"));
}

cyphertextFile.close();

if(unsupported_params || cypertextData.length() == 0) {
displayError("err: invalid Encrypted file (altered?)");
return "";
}

// else try decrypting
cypertextData.trim();
String cypertextDataDec = "";
cypertextDataDec.reserve(cypertextData.length());

uint8_t decimal = 0;
char temp[3]; // Temporary storage for each hex pair

for (int i = 0; i < cypertextData.length(); i += 3) {
// Converts two characters hex to a single byte

uint8_t highNibble = hexCharToDecimal(cypertextData[i]);
uint8_t lowNibble = hexCharToDecimal(cypertextData[i + 1]);
decimal = (highNibble << 4) | lowNibble;

//Serial.println((char) decimal);

//cypertextDataDec += decimal;
//cypertextDataDec_index += 1;

//temp[0] = cypertextData[i]; // First hex nibble
//temp[1] = cypertextData[i + 1]; // Second hex nibble
//temp[2] = '\0'; // Null-terminate the string

// Convert the hex pair to a byte (char)
//char decimal = (char) strtol(temp, NULL, 16);
/*
cypertextDataDec[i/3] = decimal;
*/
cypertextDataDec += (char) decimal;
//Serial.println(decimal);
}

//Serial.println(cachedPassword);
//Serial.println(cypertextData);
//Serial.println(cypertextDataDec);

plaintext = xorEncryptDecryptMD5(cypertextDataDec, cachedPassword, 10);

if(!isValidAscii(plaintext)) {
// invalidate cached password -> will ask again on the next try
cachedPassword = "";
displayError("decryption failed (invalid password?)");
//Serial.println(plaintext);
return "";
}
//else
return(plaintext);
}


//void writeEncryptedFile(FS &fs, String filepath, String& plaintext)


String encryptString(String& plaintext, const String& password_str) {
// TODO: add "XOR" header
return xorEncryptDecrypt(plaintext, password_str);
String dataStr = xorEncryptDecryptMD5(plaintext, password_str, 10);
String dataStrHex = "";

for (size_t i = 0; i < dataStr.length(); i++)
dataStrHex += String(dataStr[i], HEX) + " ";
dataStrHex.toUpperCase();
dataStrHex.trim();

String out = "Filetype: Bruce Encrypted File\nVersion: 1\n";
out += "Algo: XOR\n"; // TODO: add AES
out += "KeyDerivationAlgo: MD5\n";
out += "KeyDerivationPasses: 10\n";
out += "Data: " + dataStrHex + "\n";

return out;
}

String decryptString(String& cypertext, const String& password_str) {
return xorEncryptDecrypt(cypertext, password_str);
/* OLD:
String decryptString(String& cypertext, const String& password_str)

return xorEncryptDecryptMD5(cypertextData, password_str);
}
*/
5 changes: 5 additions & 0 deletions src/core/passwords.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@

#include <Arduino.h>
#include <FS.h>
#include <LittleFS.h>
#include <SD.h>

String encryptString(String& plaintext, const String& password_str);

String decryptString(String& cypertext, const String& password_str);

String readDecryptedFile(FS &fs, String filepath);
Loading
Loading