fix(ui): validate and clamp dialog input
Tighten input handling across several dialogs so bad/edge input can't produce a doomed request or a confusing display: - app_security: passphrase strength meter now factors character-class diversity — an all-one-class string downgrades one tier so "aaaaaaaa" no longer scores as high as a mixed one. - block_info: clamp the height field to the chain tip and hide/deny "Next" at the tip (was only yielding a raw RPC error). - address_label: trim surrounding whitespace before saving; a whitespace-only label clears it (mirrors clearing the icon). - send_tab: re-clamp the amount when a Max send has its fee bumped in the confirm popup (kept the total within budget) and NUL-terminate the strncpy'd address/memo when a payment URI overwrites the form. - settings_page: reject an empty/whitespace-only lite wallet path before dispatching an unusable open/restore request. - peers_tab: guard ExtractIP against an empty address. - transaction_details: disable "View in explorer" when the configured explorer URL is empty/whitespace so we never open a garbage link. - app: seed-backup "Skip" now requires a second, deliberate click with a fund-loss warning before it dismisses. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
43
src/app.cpp
43
src/app.cpp
@@ -2278,6 +2278,7 @@ void App::renderLiteFirstRunPrompt()
|
||||
static std::vector<std::pair<std::string, bool>> chips; // shuffled (word, consumed)
|
||||
static int progress = 0; // # words confirmed in order
|
||||
static double wrongFlashUntil = 0.0; // brief "not the next word" hint
|
||||
static bool skipConfirm = false; // "Skip" backup requires a second confirming click
|
||||
static bool creating = false; // async create (with failover) in flight
|
||||
// Restore-from-seed step (step 3). The seed buffer is SECRET — wiped in finish() and on Back.
|
||||
static char restoreSeed[512] = {};
|
||||
@@ -2305,6 +2306,7 @@ void App::renderLiteFirstRunPrompt()
|
||||
chips.clear();
|
||||
progress = 0;
|
||||
step = 0;
|
||||
skipConfirm = false;
|
||||
creating = false;
|
||||
lite_firstrun_dismissed_ = true;
|
||||
ImGui::CloseCurrentPopup();
|
||||
@@ -2415,14 +2417,28 @@ void App::renderLiteFirstRunPrompt()
|
||||
std::mt19937 rng{std::random_device{}()};
|
||||
std::shuffle(chips.begin(), chips.end(), rng);
|
||||
progress = 0;
|
||||
skipConfirm = false;
|
||||
step = 2;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ui::material::TactileButton("Copy", ImVec2(80, 0))) copySecretToClipboard(seed);
|
||||
ImGui::SameLine();
|
||||
if (ui::material::TactileButton("Skip", ImVec2(80, 0))) {
|
||||
ui::Notifications::instance().success(TR("lite_welcome_created"), 6.0f);
|
||||
finish();
|
||||
if (ui::material::TactileButton(skipConfirm ? "Skip anyway" : "Skip", ImVec2(120, 0))) {
|
||||
if (!skipConfirm) {
|
||||
skipConfirm = true; // require a second, deliberate click
|
||||
} else {
|
||||
ui::Notifications::instance().success(TR("lite_welcome_created"), 6.0f);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
if (skipConfirm) {
|
||||
ImGui::Spacing();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + 380.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ui::material::Error());
|
||||
ImGui::TextUnformatted("You have not backed up your seed — funds could be lost. "
|
||||
"Skip anyway?");
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
} else if (step == 2) {
|
||||
// ── Verify: tap the words in order ──────────────────────────────────────
|
||||
@@ -2471,11 +2487,24 @@ void App::renderLiteFirstRunPrompt()
|
||||
}
|
||||
if (!verified) ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
if (ui::material::TactileButton("Back", ImVec2(80, 0))) step = 1;
|
||||
if (ui::material::TactileButton("Back", ImVec2(80, 0))) { skipConfirm = false; step = 1; }
|
||||
ImGui::SameLine();
|
||||
if (ui::material::TactileButton("Skip", ImVec2(80, 0))) {
|
||||
ui::Notifications::instance().success(TR("lite_welcome_created"), 6.0f);
|
||||
finish();
|
||||
if (ui::material::TactileButton(skipConfirm ? "Skip anyway" : "Skip", ImVec2(120, 0))) {
|
||||
if (!skipConfirm) {
|
||||
skipConfirm = true; // require a second, deliberate click
|
||||
} else {
|
||||
ui::Notifications::instance().success(TR("lite_welcome_created"), 6.0f);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
if (skipConfirm) {
|
||||
ImGui::Spacing();
|
||||
ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + 380.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ui::material::Error());
|
||||
ImGui::TextUnformatted("You have not backed up your seed — funds could be lost. "
|
||||
"Skip anyway?");
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
} else if (step == 3) {
|
||||
// ── Restore from an existing seed phrase ────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user