mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-21 19:35:49 +08:00
refactor: enhance XML handling in safeGetXML and integrate mobile gestalt query
This commit is contained in:
@@ -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) {
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user