2026-06-19 17:51:51 -07:00
|
|
|
#ifdef WITH_GUI
|
|
|
|
|
|
|
|
|
|
#include "RecoveryPanel.hpp"
|
|
|
|
|
|
|
|
|
|
#include <wx/wx.h>
|
2026-07-06 04:05:57 -07:00
|
|
|
#include <wx/mstream.h>
|
|
|
|
|
#include <wx/image.h>
|
|
|
|
|
#include <wx/bitmap.h>
|
|
|
|
|
#include <wx/statline.h>
|
2026-06-19 17:51:51 -07:00
|
|
|
|
2026-06-28 16:37:05 -07:00
|
|
|
#include <thread>
|
|
|
|
|
|
2026-06-19 17:51:51 -07:00
|
|
|
#include "AppFrame.hpp"
|
|
|
|
|
#include "DevicePanel.hpp"
|
2026-06-28 16:37:05 -07:00
|
|
|
|
2026-07-06 04:05:57 -07:00
|
|
|
#include "../event.hpp"
|
2026-06-28 16:37:05 -07:00
|
|
|
#include "../utils.h"
|
|
|
|
|
#include "../globals.h"
|
|
|
|
|
#include "../paleinfo.h"
|
2026-07-06 04:05:57 -07:00
|
|
|
#include "../gen/images/logo.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)
|
|
|
|
|
{
|
2026-06-28 16:37:05 -07:00
|
|
|
Bind(wxEVT_SHOW, &RecoveryPanel::OnShow, this);
|
2026-07-06 04:05:57 -07:00
|
|
|
auto* root = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
|
auto* left = new wxBoxSizer(wxVERTICAL);
|
|
|
|
|
wxMemoryInputStream stream(images_logo_png, images_logo_png_len);
|
|
|
|
|
wxImage img(stream, wxBITMAP_TYPE_PNG);
|
|
|
|
|
wxBitmap bmp(img);
|
|
|
|
|
auto* logo = new wxStaticBitmap(this, wxID_ANY, bmp);
|
|
|
|
|
auto* logoText = new wxStaticText(this, wxID_ANY, "Recovery");
|
|
|
|
|
auto* right = new wxBoxSizer(wxVERTICAL);
|
2026-06-19 17:51:51 -07:00
|
|
|
|
|
|
|
|
m_statusText = new wxStaticText(this, wxID_ANY, "");
|
|
|
|
|
m_backButton = new wxButton(this, wxID_ANY, "Back");
|
|
|
|
|
m_nextButton = new wxButton(this, wxID_ANY, "Next");
|
2026-07-06 04:05:57 -07:00
|
|
|
|
2026-06-19 17:51:51 -07:00
|
|
|
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("");
|
|
|
|
|
});
|
|
|
|
|
|
2026-07-06 04:05:57 -07:00
|
|
|
left->Add(
|
|
|
|
|
new wxStaticText(this, wxID_ANY,
|
|
|
|
|
"The device needs to be put into DFU mode to apply the jailbreak. This is a manual process and we will guide you through it.",
|
|
|
|
|
wxDefaultPosition,
|
|
|
|
|
wxDefaultSize,
|
|
|
|
|
wxST_WRAP
|
|
|
|
|
), 0, wxALL, 10);
|
|
|
|
|
left->Add(m_statusText, 0, wxALL, 10);
|
2026-06-19 17:51:51 -07:00
|
|
|
|
2026-07-06 04:05:57 -07:00
|
|
|
right->Add(logo, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP | wxLEFT | wxRIGHT, 10);
|
|
|
|
|
right->Add(logoText, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, 5);
|
|
|
|
|
right->AddStretchSpacer();
|
|
|
|
|
right->Add(m_backButton, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
|
|
|
|
|
right->Add(m_nextButton, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
|
|
|
|
|
|
|
|
|
|
root->Add(left, 1, wxEXPAND);
|
|
|
|
|
root->Add(new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL), 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
|
|
|
|
|
root->Add(right, 0, wxEXPAND);
|
2026-06-19 17:51:51 -07:00
|
|
|
|
|
|
|
|
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;
|
2026-07-06 04:05:57 -07:00
|
|
|
m_statusText->SetLabel("Hmm... It seems like the device didn't enter recovery mode.");
|
2026-06-19 17:51:51 -07:00
|
|
|
m_backButton->Enable();
|
|
|
|
|
m_nextButton->Enable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!m_isEnteringRecovery && state.mode == DeviceMode::None)
|
|
|
|
|
{
|
|
|
|
|
m_backButton->Enable();
|
|
|
|
|
m_nextButton->Enable();
|
|
|
|
|
GetMainFrame()->ShowMain();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 16:37:05 -07:00
|
|
|
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()
|
|
|
|
|
{
|
2026-06-28 16:37:05 -07:00
|
|
|
std::thread([this]()
|
|
|
|
|
{
|
|
|
|
|
const auto deviceState = GetDeviceState();
|
|
|
|
|
if (!deviceState.connected)
|
|
|
|
|
return;
|
2026-06-19 17:51:51 -07:00
|
|
|
|
2026-06-28 16:37:05 -07:00
|
|
|
idevice_t device = nullptr;
|
|
|
|
|
lockdownd_client_t client = nullptr;
|
2026-06-19 17:51:51 -07:00
|
|
|
|
2026-06-28 16:37:05 -07:00
|
|
|
if (idevice_new(&device, deviceState.udid.c_str()) != IDEVICE_E_SUCCESS)
|
|
|
|
|
return;
|
2026-06-19 17:51:51 -07:00
|
|
|
|
2026-06-28 16:37:05 -07:00
|
|
|
if (lockdownd_client_new_with_handshake(
|
2026-06-19 17:51:51 -07:00
|
|
|
device,
|
|
|
|
|
&client,
|
|
|
|
|
"palera1n") != LOCKDOWN_E_SUCCESS)
|
2026-06-28 16:37:05 -07:00
|
|
|
{
|
|
|
|
|
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);
|
2026-06-28 16:37:05 -07:00
|
|
|
}).detach();
|
2026-06-19 17:51:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RecoveryPanel::SetStatusText(const wxString& text)
|
|
|
|
|
{
|
|
|
|
|
m_statusText->SetLabel(text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|