Files
palera1n/src/wx/RecoveryPanel.cpp
T

155 lines
4.0 KiB
C++
Raw Normal View History

2026-06-19 17:51:51 -07:00
#ifdef WITH_GUI
#include "RecoveryPanel.hpp"
#include <wx/wx.h>
#include <thread>
2026-06-19 17:51:51 -07:00
#include "AppFrame.hpp"
#include "DevicePanel.hpp"
2026-06-19 17:51:51 -07:00
#include "../state.hpp"
#include "../utils.h"
#include "../globals.h"
#include "../paleinfo.h"
2026-06-19 17:51:51 -07:00
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <libirecovery.h>
RecoveryPanel::RecoveryPanel(MainFrame* frame, wxWindow* parent)
: DevicePanel(frame, parent)
{
Bind(wxEVT_SHOW, &RecoveryPanel::OnShow, this);
2026-06-19 17:51:51 -07:00
auto* root = new wxBoxSizer(wxVERTICAL);
root->Add(new wxStaticText(this, wxID_ANY,
"The device needs to be put into DFU mode to apply the jailbreak. This is a\n"
"manual process and we will guide you through it.\n\n"
"In order to prevent filesystem corruption through hard reset, the device will\n"
"be put into recovery mode first. Click next when you are ready."), 0, wxALL, 10);
m_statusText = new wxStaticText(this, wxID_ANY, "");
root->Add(m_statusText, 0, wxALL, 10);
m_backButton = new wxButton(this, wxID_ANY, "Back");
m_nextButton = new wxButton(this, wxID_ANY, "Next");
m_backButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
{
frame->ShowMain();
});
m_nextButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent&)
{
m_statusText->SetLabel("Entering recovery mode...");
m_backButton->Disable();
m_nextButton->Disable();
EnterRecoveryMode();
});
m_timer.Bind(wxEVT_TIMER, [this](wxTimerEvent&)
{
m_backButton->Enable();
m_nextButton->Enable();
m_isEnteringRecovery = false;
GetMainFrame()->ShowDfu();
m_statusText->SetLabel("");
});
auto* bottomRow = new wxBoxSizer(wxHORIZONTAL);
bottomRow->AddStretchSpacer();
bottomRow->Add(m_backButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 12);
bottomRow->Add(m_nextButton, 0, wxRIGHT | wxLEFT | wxBOTTOM, 12);
2026-06-19 17:51:51 -07:00
root->AddStretchSpacer();
root->Add(bottomRow, 0, wxEXPAND);
SetSizer(root);
}
void RecoveryPanel::SetDeviceState(const DeviceState& state)
{
DevicePanel::SetDeviceState(state);
if (!(this->IsShown()))
return;
if (m_isEnteringRecovery && state.mode == DeviceMode::Recovery)
{
m_statusText->SetLabel("Device is now in recovery mode.");
m_timer.StartOnce(3000);
}
if (m_isEnteringRecovery && state.mode == DeviceMode::Normal)
{
m_isEnteringRecovery = false;
m_statusText->SetLabel("Hmm... It seems like the device didn't enter recovery mode. Please try again.");
m_backButton->Enable();
m_nextButton->Enable();
}
if (!m_isEnteringRecovery && state.mode == DeviceMode::None)
{
m_backButton->Enable();
m_nextButton->Enable();
GetMainFrame()->ShowMain();
}
}
void RecoveryPanel::OnShow(wxShowEvent& event)
{
if (event.IsShown())
{
if (palerain_flags & palerain_option_quick)
{
m_statusText->SetLabel("Entering recovery mode...");
m_backButton->Disable();
m_nextButton->Disable();
EnterRecoveryMode();
}
}
DevicePanel::OnShow(event);
}
2026-06-19 17:51:51 -07:00
void RecoveryPanel::EnterRecoveryMode()
{
std::thread([this]()
{
const auto deviceState = GetDeviceState();
if (!deviceState.connected)
return;
2026-06-19 17:51:51 -07:00
idevice_t device = nullptr;
lockdownd_client_t client = nullptr;
2026-06-19 17:51:51 -07:00
if (idevice_new(&device, deviceState.udid.c_str()) != IDEVICE_E_SUCCESS)
return;
2026-06-19 17:51:51 -07:00
if (lockdownd_client_new_with_handshake(
2026-06-19 17:51:51 -07:00
device,
&client,
"palera1n") != LOCKDOWN_E_SUCCESS)
{
idevice_free(device);
return;
}
m_isEnteringRecovery = true;
lockdownd_enter_recovery(client);
lockdownd_client_free(client);
2026-06-19 17:51:51 -07:00
idevice_free(device);
}).detach();
2026-06-19 17:51:51 -07:00
}
void RecoveryPanel::SetStatusText(const wxString& text)
{
m_statusText->SetLabel(text);
}
#endif