refactor: enhance XML handling in safeGetXML and integrate mobile gestalt query

This commit is contained in:
uncor3
2025-09-14 00:34:35 +00:00
parent 6997ccf2dc
commit 9fbe1b5f45
4 changed files with 104 additions and 26 deletions
+21 -7
View File
@@ -4,21 +4,35 @@
#include <libimobiledevice/diagnostics_relay.h>
#include <libimobiledevice/libimobiledevice.h>
#include <libimobiledevice/lockdown.h>
#include <pugixml.hpp>
std::string safeGet(const char *key, pugi::xml_node dict)
std::string safeGetXML(const char *key, pugi::xml_node dict)
{
for (pugi::xml_node child = dict.first_child(); child;
child = child.next_sibling()) {
if (strcmp(child.name(), "key") == 0 &&
strcmp(child.text().as_string(), key) == 0) {
pugi::xml_node value = child.next_sibling();
if (value)
return value.text().as_string();
if (value) {
// Handle different XML element types
if (strcmp(value.name(), "true") == 0) {
return "true";
} else if (strcmp(value.name(), "false") == 0) {
return "false";
} else if (strcmp(value.name(), "integer") == 0) {
return value.text().as_string();
} else if (strcmp(value.name(), "string") == 0) {
return value.text().as_string();
} else if (strcmp(value.name(), "real") == 0) {
return value.text().as_string();
} else {
// For any other type, try to get the text content
return value.text().as_string();
}
}
}
}
return "";
};
}
// TODO: return tyype
DeviceInfo fullDeviceInfo(const pugi::xml_document &doc,
@@ -220,10 +234,10 @@ IDescriptorInitDeviceResult init_idescriptor_device(const char *udid)
plist_t diagnostics = nullptr;
std::string productType =
safeGet("ProductType", infoXml.child("plist").child("dict"));
safeGetXML("ProductType", infoXml.child("plist").child("dict"));
bool is_iphone =
safeGet("DeviceClass", infoXml.child("plist").child("dict")) ==
safeGetXML("DeviceClass", infoXml.child("plist").child("dict")) ==
"iPhone";
if (is_iphone) {
+51
View File
@@ -0,0 +1,51 @@
#include "../../iDescriptor.h"
#include "libimobiledevice/diagnostics_relay.h"
#include <QDebug>
#include <plist/plist.h>
bool query_mobile_gestalt(iDescriptorDevice *id_device, const QStringList &keys,
uint32_t &xml_size, char *&xml_data)
{
if (!id_device) {
qDebug() << "Invalid device";
return false;
}
diagnostics_relay_client_t diagnostics_client = nullptr;
if (diagnostics_relay_client_start_service(id_device->device,
&diagnostics_client, nullptr) !=
DIAGNOSTICS_RELAY_E_SUCCESS) {
qDebug() << "Failed to start diagnostics service";
return false;
}
plist_t result = nullptr;
plist_t keys_array = plist_new_array();
for (const QString &key : keys) {
plist_t key_node = plist_new_string(key.toStdString().c_str());
plist_array_append_item(keys_array, key_node);
}
diagnostics_relay_error_t err = diagnostics_relay_query_mobilegestalt(
diagnostics_client, keys_array, &result);
plist_free(keys_array); // Free the keys array
if (err != DIAGNOSTICS_RELAY_E_SUCCESS) {
qDebug() << "Failed to query mobile gestalt";
diagnostics_relay_client_free(diagnostics_client);
return false;
}
if (!result) {
qDebug() << "No result from mobile gestalt query";
diagnostics_relay_client_free(diagnostics_client);
return false;
}
plist_to_xml(result, &xml_data, &xml_size);
plist_free(result); // Free the result plist
diagnostics_relay_client_free(diagnostics_client);
return true;
}
+28 -18
View File
@@ -3,9 +3,11 @@
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <sstream>
QueryMobileGestaltWidget::QueryMobileGestaltWidget(QWidget *parent)
: QWidget(parent)
QueryMobileGestaltWidget::QueryMobileGestaltWidget(iDescriptorDevice *device,
QWidget *parent)
: QWidget(parent), m_device(device)
{
setupUI();
populateKeys();
@@ -1137,28 +1139,36 @@ void QueryMobileGestaltWidget::displayResults(
QMap<QString, QVariant>
QueryMobileGestaltWidget::queryMobileGestalt(const QStringList &keys)
{
char *xml = nullptr;
uint32_t xmlLength = 0;
bool res = query_mobile_gestalt(m_device, keys, xmlLength, xml);
if (!res) {
qDebug() << "MobileGestalt query failed.";
return {};
}
// This is a mock implementation
// Replace this with your actual query function that takes a plist dict
pugi::xml_document infoXml;
pugi::xml_parse_result result = infoXml.load_string(xml);
if (xml)
free(xml);
if (!result) {
qDebug() << "Failed to parse XML:" << result.description();
return {};
}
pugi::xml_node dictNode =
infoXml.child("plist").child("dict").child("key").next_sibling("dict");
if (!dictNode) {
qDebug() << "No MobileGestalt <dict> node found in XML.";
return {};
}
QMap<QString, QVariant> results;
// Example mock data
QMap<QString, QVariant> mockData = {
{"DeviceName", "iPhone"}, {"ProductType", "iPhone14,2"},
{"ProductVersion", "17.1.1"}, {"64-bit", true},
{"DeviceSupportsCamera", true}, {"DeviceSupportsWiFi", true},
{"DeviceClass", "iPhone"}, {"SerialNumber", "MOCK123456"},
{"ModelNumber", "MLPG3"}, {"RegionCode", "US"},
{"BuildVersion", "21B101"}};
// Return only the requested keys
for (const QString &key : keys) {
if (mockData.contains(key)) {
results[key] = mockData[key];
} else {
results[key] = "Not available";
std::string value = safeGetXML(key.toStdString().c_str(), dictNode);
if (!value.empty()) {
results.insert(key, QString::fromStdString(value));
}
}
return results;
}
+4 -1
View File
@@ -1,6 +1,7 @@
#ifndef QUERYMOBILEGESTALTWIDGET_H
#define QUERYMOBILEGESTALTWIDGET_H
#include "iDescriptor.h"
#include <QCheckBox>
#include <QComboBox>
#include <QGroupBox>
@@ -21,7 +22,8 @@ class QueryMobileGestaltWidget : public QWidget
Q_OBJECT
public:
QueryMobileGestaltWidget(QWidget *parent = nullptr);
QueryMobileGestaltWidget(iDescriptorDevice *device,
QWidget *parent = nullptr);
private slots:
void onQueryButtonClicked();
@@ -46,6 +48,7 @@ private:
QPushButton *queryButton;
QTextEdit *outputTextEdit;
QLabel *statusLabel;
iDescriptorDevice *m_device;
// Data
QStringList mobileGestaltKeys;