/* * palera1n - https://palera.in * * Copyright (C) 2026 palera1n team * * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * */ #ifdef WITH_TUI #include "TuiExploitPanel.hpp" #include #include #include #include #include #include #include "Tui.hpp" #include "TuiText.hpp" #include "../exploit.h" static const char *buttons[] = { "Back" }; static constexpr int kExploitContentX = 2; static constexpr int kExploitContentWidth = 60; TuiExploitPanel::TuiExploitPanel(TuiFrame* frame) : TuiPanel(frame) {} const char** TuiExploitPanel::get_buttons() const { return buttons; } void TuiExploitPanel::draw(int sy, int sx, int selected) { (void)selected; const int content_x = sx + kExploitContentX; tui_text::draw_wrapped_text( sy + 2, content_x, kExploitContentWidth, "Installing jailbreak, this will take a moment. If the device asks for a passcode please enter it. Do not disconnect the device until finished.", 3 ); std::string status_text; int progress = 0; { std::lock_guard lock(m_status_mutex); status_text = m_status_text; progress = m_progress; } mvprintw(sy + 8, content_x, "%.*s", kExploitContentWidth, status_text.empty() ? stage_to_string(STAGE_RESET) : status_text.c_str()); const int bar_width = 50; const int filled = (std::clamp(progress, 0, 100) * bar_width) / 100; std::string bar(static_cast(bar_width), '-'); for (int i = 0; i < filled; ++i) { bar[static_cast(i)] = '#'; } mvprintw(sy + 10, sx + 2, "[%s] %3d%%", bar.c_str(), std::clamp(progress, 0, 100)); } void TuiExploitPanel::handle_enter(int selected, int sy, int sx) { if (selected == 0) { GetFrame()->ShowMain(1); } } void TuiExploitPanel::handle_device_update(const DeviceState& state) { (void)state; } void TuiExploitPanel::on_show() { exploit(); } bool TuiExploitPanel::is_button_enabled(int btn_idx) const { (void)btn_idx; return !m_is_exploiting; } void TuiExploitPanel::set_status(const std::string& status, int progress) { std::lock_guard lock(m_status_mutex); m_status_text = status; m_progress = std::clamp(progress, 0, 100); } void TuiExploitPanel::exploit() { if (m_is_exploiting) { return; } else { m_is_exploiting = true; } std::thread([this]() { const DeviceState deviceState = GetFrame()->GetDeviceState(); if (!deviceState.connected || deviceState.mode != DeviceMode::DFU) { m_is_exploiting = false; return; } auto stage = std::make_shared>(STAGE_RESET); std::thread worker([stage]() { ::exploit(reinterpret_cast(stage.get())); stage->store(STAGE_DONE); }); for (;;) { int currentStage = stage->load(); int progress = stage_to_progress(currentStage); set_status(stage_to_string(currentStage), progress); if (currentStage == STAGE_DONE) break; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } if (worker.joinable()) worker.join(); m_is_exploiting = false; }).detach(); } #endif // WITH_TUI