clang format

This commit is contained in:
Brendan O'Leary 2025-12-16 21:42:36 -05:00
parent e9e6982eea
commit 05da79f6ad
9 changed files with 192 additions and 198 deletions

View File

@ -2,6 +2,7 @@
#include <SD.h> #include <SD.h>
#include <WiFi.h> #include <WiFi.h>
#include <algorithm> #include <algorithm>
#include "config.h" #include "config.h"
@ -11,10 +12,7 @@ CrossPointWebServer crossPointWebServer;
// Folders/files to hide from the web interface file browser // Folders/files to hide from the web interface file browser
// Note: Items starting with "." are automatically hidden // Note: Items starting with "." are automatically hidden
static const char* HIDDEN_ITEMS[] = { static const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
"System Volume Information",
"XTCache"
};
static const size_t HIDDEN_ITEMS_COUNT = sizeof(HIDDEN_ITEMS) / sizeof(HIDDEN_ITEMS[0]); static const size_t HIDDEN_ITEMS_COUNT = sizeof(HIDDEN_ITEMS) / sizeof(HIDDEN_ITEMS[0]);
// Helper function to escape HTML special characters to prevent XSS // Helper function to escape HTML special characters to prevent XSS
@ -25,12 +23,24 @@ static String escapeHtml(const String& input) {
for (size_t i = 0; i < input.length(); i++) { for (size_t i = 0; i < input.length(); i++) {
char c = input.charAt(i); char c = input.charAt(i);
switch (c) { switch (c) {
case '&': output += "&amp;"; break; case '&':
case '<': output += "&lt;"; break; output += "&amp;";
case '>': output += "&gt;"; break; break;
case '"': output += "&quot;"; break; case '<':
case '\'': output += "&#39;"; break; output += "&lt;";
default: output += c; break; break;
case '>':
output += "&gt;";
break;
case '"':
output += "&quot;";
break;
case '\'':
output += "&#39;";
break;
default:
output += c;
break;
} }
} }
return output; return output;
@ -849,9 +859,7 @@ static const char* FILES_PAGE_FOOTER = R"rawliteral(
CrossPointWebServer::CrossPointWebServer() {} CrossPointWebServer::CrossPointWebServer() {}
CrossPointWebServer::~CrossPointWebServer() { CrossPointWebServer::~CrossPointWebServer() { stop(); }
stop();
}
void CrossPointWebServer::begin() { void CrossPointWebServer::begin() {
if (running) { if (running) {
@ -1176,7 +1184,8 @@ void CrossPointWebServer::handleFileList() {
html += "<tr class=\"" + rowClass + "\">"; html += "<tr class=\"" + rowClass + "\">";
html += "<td><span class=\"file-icon\">" + icon + "</span>"; html += "<td><span class=\"file-icon\">" + icon + "</span>";
html += "<a href=\"/files?path=" + folderPath + "\" class=\"folder-link\">" + escapeHtml(file.name) + "</a>" + badge + "</td>"; html += "<a href=\"/files?path=" + folderPath + "\" class=\"folder-link\">" + escapeHtml(file.name) + "</a>" +
badge + "</td>";
html += "<td>" + typeStr + "</td>"; html += "<td>" + typeStr + "</td>";
html += "<td>" + sizeStr + "</td>"; html += "<td>" + sizeStr + "</td>";
// Escape quotes for JavaScript string // Escape quotes for JavaScript string
@ -1184,7 +1193,8 @@ void CrossPointWebServer::handleFileList() {
escapedName.replace("'", "\\'"); escapedName.replace("'", "\\'");
String escapedPath = folderPath; String escapedPath = folderPath;
escapedPath.replace("'", "\\'"); escapedPath.replace("'", "\\'");
html += "<td class=\"actions-col\"><button class=\"delete-btn\" onclick=\"openDeleteModal('" + escapedName + "', '" + escapedPath + "', true)\" title=\"Delete folder\">🗑️</button></td>"; html += "<td class=\"actions-col\"><button class=\"delete-btn\" onclick=\"openDeleteModal('" + escapedName +
"', '" + escapedPath + "', true)\" title=\"Delete folder\">🗑️</button></td>";
html += "</tr>"; html += "</tr>";
} else { } else {
rowClass = file.isEpub ? "epub-file" : ""; rowClass = file.isEpub ? "epub-file" : "";
@ -1209,7 +1219,8 @@ void CrossPointWebServer::handleFileList() {
escapedName.replace("'", "\\'"); escapedName.replace("'", "\\'");
String escapedPath = filePath; String escapedPath = filePath;
escapedPath.replace("'", "\\'"); escapedPath.replace("'", "\\'");
html += "<td class=\"actions-col\"><button class=\"delete-btn\" onclick=\"openDeleteModal('" + escapedName + "', '" + escapedPath + "', false)\" title=\"Delete file\">🗑️</button></td>"; html += "<td class=\"actions-col\"><button class=\"delete-btn\" onclick=\"openDeleteModal('" + escapedName +
"', '" + escapedPath + "', false)\" title=\"Delete file\">🗑️</button></td>";
html += "</tr>"; html += "</tr>";
} }
} }
@ -1288,8 +1299,7 @@ void CrossPointWebServer::handleUpload() {
} }
Serial.printf("[%lu] [WEB] File created: %s\n", millis(), filePath.c_str()); Serial.printf("[%lu] [WEB] File created: %s\n", millis(), filePath.c_str());
} } else if (upload.status == UPLOAD_FILE_WRITE) {
else if (upload.status == UPLOAD_FILE_WRITE) {
if (uploadFile && uploadError.isEmpty()) { if (uploadFile && uploadError.isEmpty()) {
size_t written = uploadFile.write(upload.buf, upload.currentSize); size_t written = uploadFile.write(upload.buf, upload.currentSize);
if (written != upload.currentSize) { if (written != upload.currentSize) {
@ -1300,8 +1310,7 @@ void CrossPointWebServer::handleUpload() {
uploadSize += written; uploadSize += written;
} }
} }
} } else if (upload.status == UPLOAD_FILE_END) {
else if (upload.status == UPLOAD_FILE_END) {
if (uploadFile) { if (uploadFile) {
uploadFile.close(); uploadFile.close();
@ -1310,8 +1319,7 @@ void CrossPointWebServer::handleUpload() {
Serial.printf("[%lu] [WEB] Upload complete: %s (%d bytes)\n", millis(), uploadFileName.c_str(), uploadSize); Serial.printf("[%lu] [WEB] Upload complete: %s (%d bytes)\n", millis(), uploadFileName.c_str(), uploadSize);
} }
} }
} } else if (upload.status == UPLOAD_FILE_ABORTED) {
else if (upload.status == UPLOAD_FILE_ABORTED) {
if (uploadFile) { if (uploadFile) {
uploadFile.close(); uploadFile.close();
// Try to delete the incomplete file // Try to delete the incomplete file

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <WebServer.h> #include <WebServer.h>
#include <functional> #include <functional>
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -17,8 +17,7 @@ constexpr char WIFI_FILE[] = "/sd/.crosspoint/wifi.bin";
// Obfuscation key - "CrossPoint" in ASCII // Obfuscation key - "CrossPoint" in ASCII
// This is NOT cryptographic security, just prevents casual file reading // This is NOT cryptographic security, just prevents casual file reading
constexpr uint8_t OBFUSCATION_KEY[] = {0x43, 0x72, 0x6F, 0x73, 0x73, constexpr uint8_t OBFUSCATION_KEY[] = {0x43, 0x72, 0x6F, 0x73, 0x73, 0x50, 0x6F, 0x69, 0x6E, 0x74};
0x50, 0x6F, 0x69, 0x6E, 0x74};
constexpr size_t KEY_LENGTH = sizeof(OBFUSCATION_KEY); constexpr size_t KEY_LENGTH = sizeof(OBFUSCATION_KEY);
void WifiCredentialStore::obfuscate(std::string& data) const { void WifiCredentialStore::obfuscate(std::string& data) const {
@ -46,7 +45,8 @@ bool WifiCredentialStore::saveToFile() const {
for (const auto& cred : credentials) { for (const auto& cred : credentials) {
// Write SSID (plaintext - not sensitive) // Write SSID (plaintext - not sensitive)
serialization::writeString(file, cred.ssid); serialization::writeString(file, cred.ssid);
Serial.printf("[%lu] [WCS] Saving SSID: %s, password length: %zu\n", millis(), cred.ssid.c_str(), cred.password.size()); Serial.printf("[%lu] [WCS] Saving SSID: %s, password length: %zu\n", millis(), cred.ssid.c_str(),
cred.password.size());
// Write password (obfuscated) // Write password (obfuscated)
std::string obfuscatedPwd = cred.password; std::string obfuscatedPwd = cred.password;
@ -94,7 +94,8 @@ bool WifiCredentialStore::loadFromFile() {
// Read and deobfuscate password // Read and deobfuscate password
serialization::readString(file, cred.password); serialization::readString(file, cred.password);
Serial.printf("[%lu] [WCS] Loaded SSID: %s, obfuscated password length: %zu\n", millis(), cred.ssid.c_str(), cred.password.size()); Serial.printf("[%lu] [WCS] Loaded SSID: %s, obfuscated password length: %zu\n", millis(), cred.ssid.c_str(),
cred.password.size());
obfuscate(cred.password); // XOR is symmetric, so same function deobfuscates obfuscate(cred.password); // XOR is symmetric, so same function deobfuscates
Serial.printf("[%lu] [WCS] After deobfuscation, password length: %zu\n", millis(), cred.password.size()); Serial.printf("[%lu] [WCS] After deobfuscation, password length: %zu\n", millis(), cred.password.size());
@ -148,9 +149,7 @@ const WifiCredential* WifiCredentialStore::findCredential(const std::string& ssi
return nullptr; return nullptr;
} }
bool WifiCredentialStore::hasSavedCredential(const std::string& ssid) const { bool WifiCredentialStore::hasSavedCredential(const std::string& ssid) const { return findCredential(ssid) != nullptr; }
return findCredential(ssid) != nullptr;
}
void WifiCredentialStore::clearAll() { void WifiCredentialStore::clearAll() {
credentials.clear(); credentials.clear();

View File

@ -4,25 +4,16 @@
// Keyboard layouts - lowercase // Keyboard layouts - lowercase
const char* const OnScreenKeyboard::keyboard[NUM_ROWS] = { const char* const OnScreenKeyboard::keyboard[NUM_ROWS] = {
"`1234567890-=", "`1234567890-=", "qwertyuiop[]\\", "asdfghjkl;'", "zxcvbnm,./",
"qwertyuiop[]\\",
"asdfghjkl;'",
"zxcvbnm,./",
"^ _____<OK" // ^ = shift, _ = space, < = backspace, OK = done "^ _____<OK" // ^ = shift, _ = space, < = backspace, OK = done
}; };
// Keyboard layouts - uppercase/symbols // Keyboard layouts - uppercase/symbols
const char* const OnScreenKeyboard::keyboardShift[NUM_ROWS] = { const char* const OnScreenKeyboard::keyboardShift[NUM_ROWS] = {"~!@#$%^&*()_+", "QWERTYUIOP{}|", "ASDFGHJKL:\"",
"~!@#$%^&*()_+", "ZXCVBNM<>?", "^ _____<OK"};
"QWERTYUIOP{}|",
"ASDFGHJKL:\"",
"ZXCVBNM<>?",
"^ _____<OK"
};
OnScreenKeyboard::OnScreenKeyboard(GfxRenderer& renderer, InputManager& inputManager, OnScreenKeyboard::OnScreenKeyboard(GfxRenderer& renderer, InputManager& inputManager, const std::string& title,
const std::string& title, const std::string& initialText, const std::string& initialText, size_t maxLength, bool isPassword)
size_t maxLength, bool isPassword)
: renderer(renderer), : renderer(renderer),
inputManager(inputManager), inputManager(inputManager),
title(title), title(title),
@ -54,12 +45,18 @@ int OnScreenKeyboard::getRowLength(int row) const {
// Return actual length of each row based on keyboard layout // Return actual length of each row based on keyboard layout
switch (row) { switch (row) {
case 0: return 13; // `1234567890-= case 0:
case 1: return 13; // qwertyuiop[]backslash return 13; // `1234567890-=
case 2: return 11; // asdfghjkl;' case 1:
case 3: return 10; // zxcvbnm,./ return 13; // qwertyuiop[]backslash
case 4: return 10; // ^, space (5 wide), backspace, OK (2 wide) case 2:
default: return 0; return 11; // asdfghjkl;'
case 3:
return 10; // zxcvbnm,./
case 4:
return 10; // ^, space (5 wide), backspace, OK (2 wide)
default:
return 0;
} }
} }

View File

@ -31,11 +31,8 @@ class OnScreenKeyboard {
* @param maxLength Maximum length of input text (0 for unlimited) * @param maxLength Maximum length of input text (0 for unlimited)
* @param isPassword If true, display asterisks instead of actual characters * @param isPassword If true, display asterisks instead of actual characters
*/ */
OnScreenKeyboard(GfxRenderer& renderer, InputManager& inputManager, OnScreenKeyboard(GfxRenderer& renderer, InputManager& inputManager, const std::string& title = "Enter Text",
const std::string& title = "Enter Text", const std::string& initialText = "", size_t maxLength = 0, bool isPassword = false);
const std::string& initialText = "",
size_t maxLength = 0,
bool isPassword = false);
/** /**
* Handle button input. Call this in your screen's handleInput(). * Handle button input. Call this in your screen's handleInput().

View File

@ -41,8 +41,7 @@ class SettingsScreen final : public Screen {
void activateCurrentSetting(); void activateCurrentSetting();
public: public:
explicit SettingsScreen(GfxRenderer& renderer, InputManager& inputManager, explicit SettingsScreen(GfxRenderer& renderer, InputManager& inputManager, const std::function<void()>& onGoHome,
const std::function<void()>& onGoHome,
const std::function<void()>& onGoWifi) const std::function<void()>& onGoWifi)
: Screen(renderer, inputManager), onGoHome(onGoHome), onGoWifi(onGoWifi) {} : Screen(renderer, inputManager), onGoHome(onGoHome), onGoWifi(onGoWifi) {}
void onEnter() override; void onEnter() override;

View File

@ -136,7 +136,8 @@ void WifiScreen::selectNetwork(int index) {
// Use saved password - connect directly // Use saved password - connect directly
enteredPassword = savedCred->password; enteredPassword = savedCred->password;
usedSavedPassword = true; usedSavedPassword = true;
Serial.printf("[%lu] [WiFi] Using saved password for %s, length: %zu\n", millis(), selectedSSID.c_str(), enteredPassword.size()); Serial.printf("[%lu] [WiFi] Using saved password for %s, length: %zu\n", millis(), selectedSSID.c_str(),
enteredPassword.size());
attemptConnection(); attemptConnection();
return; return;
} }
@ -144,9 +145,7 @@ void WifiScreen::selectNetwork(int index) {
if (selectedRequiresPassword) { if (selectedRequiresPassword) {
// Show password entry // Show password entry
state = WifiScreenState::PASSWORD_ENTRY; state = WifiScreenState::PASSWORD_ENTRY;
keyboard.reset(new OnScreenKeyboard( keyboard.reset(new OnScreenKeyboard(renderer, inputManager, "Enter WiFi Password",
renderer, inputManager,
"Enter WiFi Password",
"", // No initial text "", // No initial text
64, // Max password length 64, // Max password length
false // Show password by default (hard keyboard to use) false // Show password by default (hard keyboard to use)
@ -263,14 +262,12 @@ void WifiScreen::handleInput() {
// Handle save prompt state // Handle save prompt state
if (state == WifiScreenState::SAVE_PROMPT) { if (state == WifiScreenState::SAVE_PROMPT) {
if (inputManager.wasPressed(InputManager::BTN_LEFT) || if (inputManager.wasPressed(InputManager::BTN_LEFT) || inputManager.wasPressed(InputManager::BTN_UP)) {
inputManager.wasPressed(InputManager::BTN_UP)) {
if (savePromptSelection > 0) { if (savePromptSelection > 0) {
savePromptSelection--; savePromptSelection--;
updateRequired = true; updateRequired = true;
} }
} else if (inputManager.wasPressed(InputManager::BTN_RIGHT) || } else if (inputManager.wasPressed(InputManager::BTN_RIGHT) || inputManager.wasPressed(InputManager::BTN_DOWN)) {
inputManager.wasPressed(InputManager::BTN_DOWN)) {
if (savePromptSelection < 1) { if (savePromptSelection < 1) {
savePromptSelection++; savePromptSelection++;
updateRequired = true; updateRequired = true;
@ -293,14 +290,12 @@ void WifiScreen::handleInput() {
// Handle forget prompt state (connection failed with saved credentials) // Handle forget prompt state (connection failed with saved credentials)
if (state == WifiScreenState::FORGET_PROMPT) { if (state == WifiScreenState::FORGET_PROMPT) {
if (inputManager.wasPressed(InputManager::BTN_LEFT) || if (inputManager.wasPressed(InputManager::BTN_LEFT) || inputManager.wasPressed(InputManager::BTN_UP)) {
inputManager.wasPressed(InputManager::BTN_UP)) {
if (forgetPromptSelection > 0) { if (forgetPromptSelection > 0) {
forgetPromptSelection--; forgetPromptSelection--;
updateRequired = true; updateRequired = true;
} }
} else if (inputManager.wasPressed(InputManager::BTN_RIGHT) || } else if (inputManager.wasPressed(InputManager::BTN_RIGHT) || inputManager.wasPressed(InputManager::BTN_DOWN)) {
inputManager.wasPressed(InputManager::BTN_DOWN)) {
if (forgetPromptSelection < 1) { if (forgetPromptSelection < 1) {
forgetPromptSelection++; forgetPromptSelection++;
updateRequired = true; updateRequired = true;
@ -330,8 +325,7 @@ void WifiScreen::handleInput() {
// Handle connected state // Handle connected state
if (state == WifiScreenState::CONNECTED) { if (state == WifiScreenState::CONNECTED) {
if (inputManager.wasPressed(InputManager::BTN_BACK) || if (inputManager.wasPressed(InputManager::BTN_BACK) || inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
// Exit screen on success // Exit screen on success
onGoBack(); onGoBack();
return; return;
@ -340,8 +334,7 @@ void WifiScreen::handleInput() {
// Handle connection failed state // Handle connection failed state
if (state == WifiScreenState::CONNECTION_FAILED) { if (state == WifiScreenState::CONNECTION_FAILED) {
if (inputManager.wasPressed(InputManager::BTN_BACK) || if (inputManager.wasPressed(InputManager::BTN_BACK) || inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
// If we used saved credentials, offer to forget the network // If we used saved credentials, offer to forget the network
if (usedSavedPassword) { if (usedSavedPassword) {
state = WifiScreenState::FORGET_PROMPT; state = WifiScreenState::FORGET_PROMPT;