mirror of
https://github.com/jkcoxson/idevice.git
synced 2026-03-02 06:26:15 +01:00
Port some services to plist macro
This commit is contained in:
@@ -52,6 +52,23 @@
|
|||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! plist {
|
macro_rules! plist {
|
||||||
|
// Force: dictionary out
|
||||||
|
(dict { $($tt:tt)+ }) => {{
|
||||||
|
let mut object = plist::Dictionary::new();
|
||||||
|
$crate::plist_internal!(@object object () ($($tt)+) ($($tt)+));
|
||||||
|
object
|
||||||
|
}};
|
||||||
|
|
||||||
|
// Force: value out (explicit, though default already does this)
|
||||||
|
(value { $($tt:tt)+ }) => {
|
||||||
|
$crate::plist_internal!({ $($tt)+ })
|
||||||
|
};
|
||||||
|
|
||||||
|
// Force: raw vec of plist::Value out
|
||||||
|
(array [ $($tt:tt)+ ]) => {
|
||||||
|
$crate::plist_internal!(@array [] $($tt)+)
|
||||||
|
};
|
||||||
|
|
||||||
// Hide distracting implementation details from the generated rustdoc.
|
// Hide distracting implementation details from the generated rustdoc.
|
||||||
($($plist:tt)+) => {
|
($($plist:tt)+) => {
|
||||||
$crate::plist_internal!($($plist)+)
|
$crate::plist_internal!($($plist)+)
|
||||||
|
|||||||
@@ -143,12 +143,13 @@ impl<R: ReadWrite> AppServiceClient<R> {
|
|||||||
internal_apps: bool,
|
internal_apps: bool,
|
||||||
default_apps: bool,
|
default_apps: bool,
|
||||||
) -> Result<Vec<AppListEntry>, IdeviceError> {
|
) -> Result<Vec<AppListEntry>, IdeviceError> {
|
||||||
let mut options = plist::Dictionary::new();
|
let options = crate::plist!(dict {
|
||||||
options.insert("includeAppClips".into(), app_clips.into());
|
"includeAppClips": app_clips,
|
||||||
options.insert("includeRemovableApps".into(), removable_apps.into());
|
"includeRemovableApps": removable_apps,
|
||||||
options.insert("includeHiddenApps".into(), hidden_apps.into());
|
"includeHiddenApps": hidden_apps,
|
||||||
options.insert("includeInternalApps".into(), internal_apps.into());
|
"includeInternalApps": internal_apps,
|
||||||
options.insert("includeDefaultApps".into(), default_apps.into());
|
"includeDefaultApps": default_apps,
|
||||||
|
});
|
||||||
let res = self
|
let res = self
|
||||||
.inner
|
.inner
|
||||||
.invoke("com.apple.coredevice.feature.listapps", Some(options))
|
.invoke("com.apple.coredevice.feature.listapps", Some(options))
|
||||||
|
|||||||
@@ -98,9 +98,10 @@ impl<'a, R: ReadWrite> ProcessControlClient<'a, R> {
|
|||||||
"launchSuspendedProcessWithDevicePath:bundleIdentifier:environment:arguments:options:"
|
"launchSuspendedProcessWithDevicePath:bundleIdentifier:environment:arguments:options:"
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
let mut options = Dictionary::new();
|
let options = crate::plist!(dict {
|
||||||
options.insert("StartSuspendedKey".into(), start_suspended.into());
|
"StartSuspendedKey": start_suspended,
|
||||||
options.insert("KillExisting".into(), kill_existing.into());
|
"KillExisting": kill_existing
|
||||||
|
});
|
||||||
|
|
||||||
let env_vars = match env_vars {
|
let env_vars = match env_vars {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
|
|||||||
@@ -90,11 +90,10 @@ impl HeartbeatClient {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns `IdeviceError` if the message fails to send
|
/// Returns `IdeviceError` if the message fails to send
|
||||||
pub async fn send_polo(&mut self) -> Result<(), IdeviceError> {
|
pub async fn send_polo(&mut self) -> Result<(), IdeviceError> {
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "Polo".into());
|
"Command": "Polo"
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req.clone()))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,22 +70,15 @@ impl InstallationProxyClient {
|
|||||||
bundle_identifiers: Option<Vec<String>>,
|
bundle_identifiers: Option<Vec<String>>,
|
||||||
) -> Result<HashMap<String, plist::Value>, IdeviceError> {
|
) -> Result<HashMap<String, plist::Value>, IdeviceError> {
|
||||||
let application_type = application_type.unwrap_or("Any");
|
let application_type = application_type.unwrap_or("Any");
|
||||||
let mut options = plist::Dictionary::new();
|
|
||||||
if let Some(ids) = bundle_identifiers {
|
|
||||||
let ids = ids
|
|
||||||
.into_iter()
|
|
||||||
.map(plist::Value::String)
|
|
||||||
.collect::<Vec<plist::Value>>();
|
|
||||||
options.insert("BundleIDs".into(), ids.into());
|
|
||||||
}
|
|
||||||
options.insert("ApplicationType".into(), application_type.into());
|
|
||||||
|
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "Lookup".into());
|
"Command": "Lookup",
|
||||||
req.insert("ClientOptions".into(), plist::Value::Dictionary(options));
|
"ClientOptions": {
|
||||||
self.idevice
|
"ApplicationType": application_type,
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
"BundleIDs":? bundle_identifiers,
|
||||||
.await?;
|
}
|
||||||
|
});
|
||||||
|
self.idevice.send_plist(req).await?;
|
||||||
|
|
||||||
let mut res = self.idevice.read_plist().await?;
|
let mut res = self.idevice.read_plist().await?;
|
||||||
match res.remove("LookupResult") {
|
match res.remove("LookupResult") {
|
||||||
@@ -155,14 +148,13 @@ impl InstallationProxyClient {
|
|||||||
let package_path = package_path.into();
|
let package_path = package_path.into();
|
||||||
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
||||||
|
|
||||||
let mut command = Dictionary::new();
|
let command = crate::plist!({
|
||||||
command.insert("Command".into(), "Install".into());
|
"Command": "Install",
|
||||||
command.insert("ClientOptions".into(), options);
|
"ClientOptions": options,
|
||||||
command.insert("PackagePath".into(), package_path.into());
|
"PackagePath": package_path,
|
||||||
|
});
|
||||||
|
|
||||||
self.idevice
|
self.idevice.send_plist(command).await?;
|
||||||
.send_plist(plist::Value::Dictionary(command))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.watch_completion(callback, state).await
|
self.watch_completion(callback, state).await
|
||||||
}
|
}
|
||||||
@@ -220,14 +212,13 @@ impl InstallationProxyClient {
|
|||||||
let package_path = package_path.into();
|
let package_path = package_path.into();
|
||||||
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
||||||
|
|
||||||
let mut command = Dictionary::new();
|
let command = crate::plist!({
|
||||||
command.insert("Command".into(), "Upgrade".into());
|
"Command": "Upgrade",
|
||||||
command.insert("ClientOptions".into(), options);
|
"ClientOptions": options,
|
||||||
command.insert("PackagePath".into(), package_path.into());
|
"PackagePath": package_path,
|
||||||
|
});
|
||||||
|
|
||||||
self.idevice
|
self.idevice.send_plist(command).await?;
|
||||||
.send_plist(plist::Value::Dictionary(command))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.watch_completion(callback, state).await
|
self.watch_completion(callback, state).await
|
||||||
}
|
}
|
||||||
@@ -285,14 +276,13 @@ impl InstallationProxyClient {
|
|||||||
let bundle_id = bundle_id.into();
|
let bundle_id = bundle_id.into();
|
||||||
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
||||||
|
|
||||||
let mut command = Dictionary::new();
|
let command = crate::plist!({
|
||||||
command.insert("Command".into(), "Uninstall".into());
|
"Command": "Uninstall",
|
||||||
command.insert("ApplicationIdentifier".into(), bundle_id.into());
|
"ApplicationIdentifier": bundle_id,
|
||||||
command.insert("ClientOptions".into(), options);
|
"ClientOptions": options,
|
||||||
|
});
|
||||||
|
|
||||||
self.idevice
|
self.idevice.send_plist(command).await?;
|
||||||
.send_plist(plist::Value::Dictionary(command))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
self.watch_completion(callback, state).await
|
self.watch_completion(callback, state).await
|
||||||
}
|
}
|
||||||
@@ -317,14 +307,13 @@ impl InstallationProxyClient {
|
|||||||
) -> Result<bool, IdeviceError> {
|
) -> Result<bool, IdeviceError> {
|
||||||
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
||||||
|
|
||||||
let mut command = Dictionary::new();
|
let command = crate::plist!({
|
||||||
command.insert("Command".into(), "CheckCapabilitiesMatch".into());
|
"Command": "CheckCapabilitiesMatch",
|
||||||
command.insert("ClientOptions".into(), options);
|
"ClientOptions": options,
|
||||||
command.insert("Capabilities".into(), capabilities.into());
|
"Capabilities": capabilities
|
||||||
|
});
|
||||||
|
|
||||||
self.idevice
|
self.idevice.send_plist(command).await?;
|
||||||
.send_plist(plist::Value::Dictionary(command))
|
|
||||||
.await?;
|
|
||||||
let mut res = self.idevice.read_plist().await?;
|
let mut res = self.idevice.read_plist().await?;
|
||||||
|
|
||||||
if let Some(caps) = res.remove("LookupResult").and_then(|x| x.as_boolean()) {
|
if let Some(caps) = res.remove("LookupResult").and_then(|x| x.as_boolean()) {
|
||||||
@@ -355,13 +344,12 @@ impl InstallationProxyClient {
|
|||||||
) -> Result<Vec<plist::Value>, IdeviceError> {
|
) -> Result<Vec<plist::Value>, IdeviceError> {
|
||||||
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
let options = options.unwrap_or(plist::Value::Dictionary(Dictionary::new()));
|
||||||
|
|
||||||
let mut command = Dictionary::new();
|
let command = crate::plist!({
|
||||||
command.insert("Command".into(), "Browse".into());
|
"Command": "Browse",
|
||||||
command.insert("ClientOptions".into(), options);
|
"ClientOptions": options,
|
||||||
|
});
|
||||||
|
|
||||||
self.idevice
|
self.idevice.send_plist(command).await?;
|
||||||
.send_plist(plist::Value::Dictionary(command))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let mut values = Vec::new();
|
let mut values = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@@ -93,20 +93,13 @@ impl LockdownClient {
|
|||||||
key: Option<&str>,
|
key: Option<&str>,
|
||||||
domain: Option<&str>,
|
domain: Option<&str>,
|
||||||
) -> Result<Value, IdeviceError> {
|
) -> Result<Value, IdeviceError> {
|
||||||
let mut request = plist::Dictionary::new();
|
let request = crate::plist!({
|
||||||
request.insert("Label".into(), self.idevice.label.clone().into());
|
"Label": self.idevice.label.clone(),
|
||||||
request.insert("Request".into(), "GetValue".into());
|
"Request": "GetValue",
|
||||||
|
"Key":? key,
|
||||||
if let Some(key) = key {
|
"Domain":? domain
|
||||||
request.insert("Key".into(), key.into());
|
});
|
||||||
}
|
self.idevice.send_plist(request).await?;
|
||||||
if let Some(domain) = domain {
|
|
||||||
request.insert("Domain".into(), domain.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.idevice
|
|
||||||
.send_plist(plist::Value::Dictionary(request))
|
|
||||||
.await?;
|
|
||||||
let message: plist::Dictionary = self.idevice.read_plist().await?;
|
let message: plist::Dictionary = self.idevice.read_plist().await?;
|
||||||
match message.get("Value") {
|
match message.get("Value") {
|
||||||
Some(m) => Ok(m.to_owned()),
|
Some(m) => Ok(m.to_owned()),
|
||||||
@@ -138,19 +131,15 @@ impl LockdownClient {
|
|||||||
) -> Result<(), IdeviceError> {
|
) -> Result<(), IdeviceError> {
|
||||||
let key = key.into();
|
let key = key.into();
|
||||||
|
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Label".into(), self.idevice.label.clone().into());
|
"Label": self.idevice.label.clone(),
|
||||||
req.insert("Request".into(), "SetValue".into());
|
"Request": "SetValue",
|
||||||
req.insert("Key".into(), key.into());
|
"Key": key,
|
||||||
req.insert("Value".into(), value);
|
"Value": value,
|
||||||
|
"Domain":? domain
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(domain) = domain {
|
self.idevice.send_plist(req).await?;
|
||||||
req.insert("Domain".into(), domain.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.idevice
|
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
|
||||||
.await?;
|
|
||||||
self.idevice.read_plist().await?;
|
self.idevice.read_plist().await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -177,28 +166,14 @@ impl LockdownClient {
|
|||||||
return Err(IdeviceError::NoEstablishedConnection);
|
return Err(IdeviceError::NoEstablishedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut request = plist::Dictionary::new();
|
let request = crate::plist!({
|
||||||
request.insert(
|
"Label": self.idevice.label.clone(),
|
||||||
"Label".to_string(),
|
"Request": "StartSession",
|
||||||
plist::Value::String(self.idevice.label.clone()),
|
"HostID": pairing_file.host_id.clone(),
|
||||||
);
|
"SystemBUID": pairing_file.system_buid.clone()
|
||||||
|
|
||||||
request.insert(
|
});
|
||||||
"Request".to_string(),
|
self.idevice.send_plist(request).await?;
|
||||||
plist::Value::String("StartSession".to_string()),
|
|
||||||
);
|
|
||||||
request.insert(
|
|
||||||
"HostID".to_string(),
|
|
||||||
plist::Value::String(pairing_file.host_id.clone()),
|
|
||||||
);
|
|
||||||
request.insert(
|
|
||||||
"SystemBUID".to_string(),
|
|
||||||
plist::Value::String(pairing_file.system_buid.clone()),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.idevice
|
|
||||||
.send_plist(plist::Value::Dictionary(request))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let response = self.idevice.read_plist().await?;
|
let response = self.idevice.read_plist().await?;
|
||||||
match response.get("EnableSessionSSL") {
|
match response.get("EnableSessionSSL") {
|
||||||
@@ -236,12 +211,11 @@ impl LockdownClient {
|
|||||||
identifier: impl Into<String>,
|
identifier: impl Into<String>,
|
||||||
) -> Result<(u16, bool), IdeviceError> {
|
) -> Result<(u16, bool), IdeviceError> {
|
||||||
let identifier = identifier.into();
|
let identifier = identifier.into();
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Request".into(), "StartService".into());
|
"Request": "StartService",
|
||||||
req.insert("Service".into(), identifier.into());
|
"Service": identifier,
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
let response = self.idevice.read_plist().await?;
|
let response = self.idevice.read_plist().await?;
|
||||||
|
|
||||||
let ssl = match response.get("EnableServiceSSL") {
|
let ssl = match response.get("EnableServiceSSL") {
|
||||||
@@ -307,37 +281,29 @@ impl LockdownClient {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let ca = crate::ca::generate_certificates(&pub_key, None).unwrap();
|
let ca = crate::ca::generate_certificates(&pub_key, None).unwrap();
|
||||||
let mut pair_record = plist::Dictionary::new();
|
let mut pair_record = crate::plist!(dict {
|
||||||
pair_record.insert("DevicePublicKey".into(), plist::Value::Data(pub_key));
|
"DevicePublicKey": pub_key,
|
||||||
pair_record.insert("DeviceCertificate".into(), plist::Value::Data(ca.dev_cert));
|
"DeviceCertificate": ca.dev_cert,
|
||||||
pair_record.insert(
|
"HostCertificate": ca.host_cert.clone(),
|
||||||
"HostCertificate".into(),
|
"HostID": host_id,
|
||||||
plist::Value::Data(ca.host_cert.clone()),
|
"RootCertificate": ca.host_cert,
|
||||||
);
|
"RootPrivateKey": ca.private_key.clone(),
|
||||||
pair_record.insert("HostID".into(), host_id.into());
|
"WiFiMACAddress": wifi_mac,
|
||||||
pair_record.insert("RootCertificate".into(), plist::Value::Data(ca.host_cert));
|
"SystemBUID": system_buid,
|
||||||
pair_record.insert(
|
});
|
||||||
"RootPrivateKey".into(),
|
|
||||||
plist::Value::Data(ca.private_key.clone()),
|
|
||||||
);
|
|
||||||
pair_record.insert("WiFiMACAddress".into(), wifi_mac.into());
|
|
||||||
pair_record.insert("SystemBUID".into(), system_buid.into());
|
|
||||||
|
|
||||||
let mut options = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
options.insert("ExtendedPairingErrors".into(), true.into());
|
"Label": self.idevice.label.clone(),
|
||||||
|
"Request": "Pair",
|
||||||
let mut req = plist::Dictionary::new();
|
"PairRecord": pair_record.clone(),
|
||||||
req.insert("Label".into(), self.idevice.label.clone().into());
|
"ProtocolVersion": "2",
|
||||||
req.insert("Request".into(), "Pair".into());
|
"PairingOptions": {
|
||||||
req.insert(
|
"ExtendedPairingErrors": true
|
||||||
"PairRecord".into(),
|
}
|
||||||
plist::Value::Dictionary(pair_record.clone()),
|
});
|
||||||
);
|
|
||||||
req.insert("ProtocolVersion".into(), "2".into());
|
|
||||||
req.insert("PairingOptions".into(), plist::Value::Dictionary(options));
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
self.idevice.send_plist(req.clone().into()).await?;
|
self.idevice.send_plist(req.clone()).await?;
|
||||||
match self.idevice.read_plist().await {
|
match self.idevice.read_plist().await {
|
||||||
Ok(escrow) => {
|
Ok(escrow) => {
|
||||||
pair_record.insert("HostPrivateKey".into(), plist::Value::Data(ca.private_key));
|
pair_record.insert("HostPrivateKey".into(), plist::Value::Data(ca.private_key));
|
||||||
|
|||||||
@@ -55,11 +55,10 @@ impl ImageMounter {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns `IdeviceError` if communication fails or response is malformed
|
/// Returns `IdeviceError` if communication fails or response is malformed
|
||||||
pub async fn copy_devices(&mut self) -> Result<Vec<plist::Value>, IdeviceError> {
|
pub async fn copy_devices(&mut self) -> Result<Vec<plist::Value>, IdeviceError> {
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "CopyDevices".into());
|
"Command": "CopyDevices"
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
let mut res = self.idevice.read_plist().await?;
|
let mut res = self.idevice.read_plist().await?;
|
||||||
|
|
||||||
match res.remove("EntryList") {
|
match res.remove("EntryList") {
|
||||||
@@ -83,12 +82,11 @@ impl ImageMounter {
|
|||||||
image_type: impl Into<&str>,
|
image_type: impl Into<&str>,
|
||||||
) -> Result<Vec<u8>, IdeviceError> {
|
) -> Result<Vec<u8>, IdeviceError> {
|
||||||
let image_type = image_type.into();
|
let image_type = image_type.into();
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "LookupImage".into());
|
"Command": "LookupImage",
|
||||||
req.insert("ImageType".into(), image_type.into());
|
"ImageType": image_type
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.idevice.read_plist().await?;
|
let res = self.idevice.read_plist().await?;
|
||||||
match res.get("ImageSignature") {
|
match res.get("ImageSignature") {
|
||||||
@@ -152,14 +150,13 @@ impl ImageMounter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "ReceiveBytes".into());
|
"Command": "ReceiveBytes",
|
||||||
req.insert("ImageType".into(), image_type.into());
|
"ImageType": image_type,
|
||||||
req.insert("ImageSize".into(), image_size.into());
|
"ImageSize": image_size,
|
||||||
req.insert("ImageSignature".into(), plist::Value::Data(signature));
|
"ImageSignature": signature,
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.idevice.read_plist().await?;
|
let res = self.idevice.read_plist().await?;
|
||||||
match res.get("Status") {
|
match res.get("Status") {
|
||||||
@@ -210,19 +207,14 @@ impl ImageMounter {
|
|||||||
) -> Result<(), IdeviceError> {
|
) -> Result<(), IdeviceError> {
|
||||||
let image_type = image_type.into();
|
let image_type = image_type.into();
|
||||||
|
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "MountImage".into());
|
"Command": "MountImage",
|
||||||
req.insert("ImageType".into(), image_type.into());
|
"ImageType": image_type,
|
||||||
req.insert("ImageSignature".into(), plist::Value::Data(signature));
|
"ImageSignature": signature,
|
||||||
if let Some(trust_cache) = trust_cache {
|
"ImageTrustCache":? trust_cache,
|
||||||
req.insert("ImageTrustCache".into(), plist::Value::Data(trust_cache));
|
"ImageInfoPlist":? info_plist,
|
||||||
}
|
});
|
||||||
if let Some(info_plist) = info_plist {
|
self.idevice.send_plist(req).await?;
|
||||||
req.insert("ImageInfoPlist".into(), info_plist);
|
|
||||||
}
|
|
||||||
self.idevice
|
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.idevice.read_plist().await?;
|
let res = self.idevice.read_plist().await?;
|
||||||
|
|
||||||
@@ -253,12 +245,11 @@ impl ImageMounter {
|
|||||||
mount_path: impl Into<String>,
|
mount_path: impl Into<String>,
|
||||||
) -> Result<(), IdeviceError> {
|
) -> Result<(), IdeviceError> {
|
||||||
let mount_path = mount_path.into();
|
let mount_path = mount_path.into();
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "UnmountImage".into());
|
"Command": "UnmountImage",
|
||||||
req.insert("MountPath".into(), mount_path.into());
|
"MountPath": mount_path,
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.idevice.read_plist().await?;
|
let res = self.idevice.read_plist().await?;
|
||||||
match res.get("Status") {
|
match res.get("Status") {
|
||||||
@@ -288,14 +279,13 @@ impl ImageMounter {
|
|||||||
) -> Result<Vec<u8>, IdeviceError> {
|
) -> Result<Vec<u8>, IdeviceError> {
|
||||||
let image_type = image_type.into();
|
let image_type = image_type.into();
|
||||||
|
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "QueryPersonalizationManifest".into());
|
"Command": "QueryPersonalizationManifest",
|
||||||
req.insert("PersonalizedImageType".into(), image_type.clone().into());
|
"PersonalizedImageType": image_type.clone(),
|
||||||
req.insert("ImageType".into(), image_type.into());
|
"ImageType": image_type,
|
||||||
req.insert("ImageSignature".into(), plist::Value::Data(signature));
|
"ImageSignature": signature
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
let mut res = self.idevice.read_plist().await?;
|
let mut res = self.idevice.read_plist().await?;
|
||||||
match res.remove("ImageSignature") {
|
match res.remove("ImageSignature") {
|
||||||
@@ -312,11 +302,10 @@ impl ImageMounter {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns `IdeviceError` if query fails
|
/// Returns `IdeviceError` if query fails
|
||||||
pub async fn query_developer_mode_status(&mut self) -> Result<bool, IdeviceError> {
|
pub async fn query_developer_mode_status(&mut self) -> Result<bool, IdeviceError> {
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "QueryDeveloperModeStatus".into());
|
"Command": "QueryDeveloperModeStatus"
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.idevice.read_plist().await?;
|
let res = self.idevice.read_plist().await?;
|
||||||
match res.get("DeveloperModeStatus") {
|
match res.get("DeveloperModeStatus") {
|
||||||
@@ -339,14 +328,11 @@ impl ImageMounter {
|
|||||||
&mut self,
|
&mut self,
|
||||||
personalized_image_type: Option<&str>,
|
personalized_image_type: Option<&str>,
|
||||||
) -> Result<Vec<u8>, IdeviceError> {
|
) -> Result<Vec<u8>, IdeviceError> {
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "QueryNonce".into());
|
"Command": "QueryNonce",
|
||||||
if let Some(image_type) = personalized_image_type {
|
"PersonalizedImageType":? personalized_image_type,
|
||||||
req.insert("PersonalizedImageType".into(), image_type.into());
|
});
|
||||||
}
|
self.idevice.send_plist(req).await?;
|
||||||
self.idevice
|
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.idevice.read_plist().await?;
|
let res = self.idevice.read_plist().await?;
|
||||||
match res.get("PersonalizationNonce") {
|
match res.get("PersonalizationNonce") {
|
||||||
@@ -369,14 +355,11 @@ impl ImageMounter {
|
|||||||
&mut self,
|
&mut self,
|
||||||
image_type: Option<&str>,
|
image_type: Option<&str>,
|
||||||
) -> Result<plist::Dictionary, IdeviceError> {
|
) -> Result<plist::Dictionary, IdeviceError> {
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "QueryPersonalizationIdentifiers".into());
|
"Command": "QueryPersonalizationIdentifiers",
|
||||||
if let Some(image_type) = image_type {
|
"PersonalizedImageType":? image_type,
|
||||||
req.insert("PersonalizedImageType".into(), image_type.into());
|
});
|
||||||
}
|
self.idevice.send_plist(req).await?;
|
||||||
self.idevice
|
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.idevice.read_plist().await?;
|
let res = self.idevice.read_plist().await?;
|
||||||
match res.get("PersonalizationIdentifiers") {
|
match res.get("PersonalizationIdentifiers") {
|
||||||
@@ -390,11 +373,10 @@ impl ImageMounter {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns `IdeviceError` if operation fails
|
/// Returns `IdeviceError` if operation fails
|
||||||
pub async fn roll_personalization_nonce(&mut self) -> Result<(), IdeviceError> {
|
pub async fn roll_personalization_nonce(&mut self) -> Result<(), IdeviceError> {
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "RollPersonalizationNonce".into());
|
"Command": "RollPersonalizationNonce"
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -404,11 +386,10 @@ impl ImageMounter {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns `IdeviceError` if operation fails
|
/// Returns `IdeviceError` if operation fails
|
||||||
pub async fn roll_cryptex_nonce(&mut self) -> Result<(), IdeviceError> {
|
pub async fn roll_cryptex_nonce(&mut self) -> Result<(), IdeviceError> {
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Command".into(), "RollCryptexNonce".into());
|
"Command": "RollCryptexNonce"
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -669,11 +650,12 @@ impl ImageMounter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut parameters = plist::Dictionary::new();
|
let parameters = crate::plist!(dict {
|
||||||
parameters.insert("ApProductionMode".into(), true.into());
|
"ApProductionMode": true,
|
||||||
parameters.insert("ApSecurityDomain".into(), 1.into());
|
"ApSecurityMode": 1,
|
||||||
parameters.insert("ApSecurityMode".into(), true.into());
|
"ApSecurityMode": true,
|
||||||
parameters.insert("ApSupportsImg4".into(), true.into());
|
"ApSupportsImg4": true
|
||||||
|
});
|
||||||
|
|
||||||
for (key, manifest_item) in manifest {
|
for (key, manifest_item) in manifest {
|
||||||
println!("{key}, {manifest_item:?}");
|
println!("{key}, {manifest_item:?}");
|
||||||
|
|||||||
@@ -185,31 +185,14 @@ impl RestoreOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_plist(&self) -> Dictionary {
|
pub fn to_plist(&self) -> Dictionary {
|
||||||
let mut opts = Dictionary::new();
|
crate::plist!(dict {
|
||||||
opts.insert(
|
"RestoreShouldReboot": self.reboot,
|
||||||
"RestoreShouldReboot".into(),
|
"RestoreDontCopyBackup": !self.copy,
|
||||||
plist::Value::Boolean(self.reboot),
|
"RestorePreserveSettings": self.preserve_settings,
|
||||||
);
|
"RestoreSystemFiles": self.system_files,
|
||||||
opts.insert(
|
"RemoveItemsNotRestored": self.remove_items_not_restored,
|
||||||
"RestoreDontCopyBackup".into(),
|
"Password":? self.password.clone()
|
||||||
plist::Value::Boolean(!self.copy),
|
})
|
||||||
);
|
|
||||||
opts.insert(
|
|
||||||
"RestorePreserveSettings".into(),
|
|
||||||
plist::Value::Boolean(self.preserve_settings),
|
|
||||||
);
|
|
||||||
opts.insert(
|
|
||||||
"RestoreSystemFiles".into(),
|
|
||||||
plist::Value::Boolean(self.system_files),
|
|
||||||
);
|
|
||||||
opts.insert(
|
|
||||||
"RemoveItemsNotRestored".into(),
|
|
||||||
plist::Value::Boolean(self.remove_items_not_restored),
|
|
||||||
);
|
|
||||||
if let Some(pw) = &self.password {
|
|
||||||
opts.insert("Password".into(), plist::Value::String(pw.clone()));
|
|
||||||
}
|
|
||||||
opts
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,12 +280,11 @@ impl MobileBackup2Client {
|
|||||||
debug!("Starting mobilebackup2 version exchange");
|
debug!("Starting mobilebackup2 version exchange");
|
||||||
|
|
||||||
// Send supported protocol versions (matching libimobiledevice)
|
// Send supported protocol versions (matching libimobiledevice)
|
||||||
let mut hello_dict = Dictionary::new();
|
let hello_dict = crate::plist!(dict {
|
||||||
let versions = vec![plist::Value::Real(2.0), plist::Value::Real(2.1)];
|
"SupportedProtocolVersions": [
|
||||||
hello_dict.insert(
|
2.0, 2.1
|
||||||
"SupportedProtocolVersions".into(),
|
]
|
||||||
plist::Value::Array(versions),
|
});
|
||||||
);
|
|
||||||
|
|
||||||
self.send_device_link_message("Hello", Some(hello_dict))
|
self.send_device_link_message("Hello", Some(hello_dict))
|
||||||
.await?;
|
.await?;
|
||||||
@@ -349,25 +331,15 @@ impl MobileBackup2Client {
|
|||||||
message_name: &str,
|
message_name: &str,
|
||||||
options: Option<Dictionary>,
|
options: Option<Dictionary>,
|
||||||
) -> Result<(), IdeviceError> {
|
) -> Result<(), IdeviceError> {
|
||||||
// Create DLMessageProcessMessage array format
|
|
||||||
let mut message_array = Vec::new();
|
|
||||||
message_array.push(plist::Value::String("DLMessageProcessMessage".into()));
|
|
||||||
|
|
||||||
// Create the actual message dictionary
|
// Create the actual message dictionary
|
||||||
let mut message_dict = Dictionary::new();
|
let message_dict = crate::plist!(dict {
|
||||||
message_dict.insert("MessageName".into(), message_name.into());
|
"MessageName": message_name,
|
||||||
|
:<? options,
|
||||||
if let Some(opts) = options {
|
});
|
||||||
for (key, value) in opts {
|
|
||||||
message_dict.insert(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message_array.push(plist::Value::Dictionary(message_dict));
|
|
||||||
|
|
||||||
debug!("Sending device link message: {message_name}");
|
debug!("Sending device link message: {message_name}");
|
||||||
self.idevice
|
self.idevice
|
||||||
.send_bplist(plist::Value::Array(message_array))
|
.send_bplist(crate::plist!(["DLMessageProcessMessage", message_dict]))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,17 +425,12 @@ impl MobileBackup2Client {
|
|||||||
source_identifier: Option<&str>,
|
source_identifier: Option<&str>,
|
||||||
options: Option<Dictionary>,
|
options: Option<Dictionary>,
|
||||||
) -> Result<(), IdeviceError> {
|
) -> Result<(), IdeviceError> {
|
||||||
let mut dict = Dictionary::new();
|
let dict = crate::plist!(dict {
|
||||||
if let Some(t) = target_identifier {
|
"TargetIdentifier":? target_identifier,
|
||||||
dict.insert("TargetIdentifier".into(), t.into());
|
"SourceIdentifier":? source_identifier,
|
||||||
}
|
"Options":? options,
|
||||||
if let Some(s) = source_identifier {
|
|
||||||
dict.insert("SourceIdentifier".into(), s.into());
|
|
||||||
}
|
|
||||||
if let Some(opts) = options {
|
|
||||||
dict.insert("Options".into(), plist::Value::Dictionary(opts));
|
|
||||||
// Special cases like Unback/EnableCloudBackup are handled by caller if needed
|
// Special cases like Unback/EnableCloudBackup are handled by caller if needed
|
||||||
}
|
});
|
||||||
self.send_device_link_message(request, Some(dict)).await
|
self.send_device_link_message(request, Some(dict)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1090,17 +1057,10 @@ impl MobileBackup2Client {
|
|||||||
.ok_or(IdeviceError::InvalidHostID)?;
|
.ok_or(IdeviceError::InvalidHostID)?;
|
||||||
self.assert_backup_exists(backup_root, source)?;
|
self.assert_backup_exists(backup_root, source)?;
|
||||||
|
|
||||||
let mut dict = Dictionary::new();
|
let dict = crate::plist!(dict {
|
||||||
dict.insert(
|
"TargetIdentifier": target_udid.unwrap(),
|
||||||
"TargetIdentifier".into(),
|
"SourceIdentifier":? source_identifier,
|
||||||
plist::Value::String(target_udid.unwrap().to_string()),
|
});
|
||||||
);
|
|
||||||
if let Some(src) = source_identifier {
|
|
||||||
dict.insert(
|
|
||||||
"SourceIdentifier".into(),
|
|
||||||
plist::Value::String(src.to_string()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
self.send_device_link_message("Info", Some(dict)).await?;
|
self.send_device_link_message("Info", Some(dict)).await?;
|
||||||
|
|
||||||
match self.process_restore_dl_loop(backup_root).await? {
|
match self.process_restore_dl_loop(backup_root).await? {
|
||||||
@@ -1121,16 +1081,11 @@ impl MobileBackup2Client {
|
|||||||
.ok_or(IdeviceError::InvalidHostID)?;
|
.ok_or(IdeviceError::InvalidHostID)?;
|
||||||
self.assert_backup_exists(backup_root, source)?;
|
self.assert_backup_exists(backup_root, source)?;
|
||||||
|
|
||||||
let mut dict = Dictionary::new();
|
let dict = crate::plist!(dict {
|
||||||
dict.insert("MessageName".into(), plist::Value::String("List".into()));
|
"MessageName": "List",
|
||||||
dict.insert(
|
"TargetIdentifier": target_udid.unwrap(),
|
||||||
"TargetIdentifier".into(),
|
"SourceIdentifier": source,
|
||||||
plist::Value::String(target_udid.unwrap().to_string()),
|
});
|
||||||
);
|
|
||||||
dict.insert(
|
|
||||||
"SourceIdentifier".into(),
|
|
||||||
plist::Value::String(source.to_string()),
|
|
||||||
);
|
|
||||||
self.send_device_link_message("List", Some(dict)).await?;
|
self.send_device_link_message("List", Some(dict)).await?;
|
||||||
|
|
||||||
match self.process_restore_dl_loop(backup_root).await? {
|
match self.process_restore_dl_loop(backup_root).await? {
|
||||||
@@ -1151,20 +1106,12 @@ impl MobileBackup2Client {
|
|||||||
.or(target_udid)
|
.or(target_udid)
|
||||||
.ok_or(IdeviceError::InvalidHostID)?;
|
.ok_or(IdeviceError::InvalidHostID)?;
|
||||||
self.assert_backup_exists(backup_root, source)?;
|
self.assert_backup_exists(backup_root, source)?;
|
||||||
|
let dict = crate::plist!(dict {
|
||||||
let mut dict = Dictionary::new();
|
"TargetIdentifier": target_udid.unwrap(),
|
||||||
dict.insert(
|
"MessageName": "Unback",
|
||||||
"TargetIdentifier".into(),
|
"SourceIdentifier": source,
|
||||||
plist::Value::String(target_udid.unwrap().to_string()),
|
"Password":? password
|
||||||
);
|
});
|
||||||
dict.insert("MessageName".into(), plist::Value::String("Unback".into()));
|
|
||||||
dict.insert(
|
|
||||||
"SourceIdentifier".into(),
|
|
||||||
plist::Value::String(source.to_string()),
|
|
||||||
);
|
|
||||||
if let Some(pw) = password {
|
|
||||||
dict.insert("Password".into(), plist::Value::String(pw.to_string()));
|
|
||||||
}
|
|
||||||
self.send_device_link_message("Unback", Some(dict)).await?;
|
self.send_device_link_message("Unback", Some(dict)).await?;
|
||||||
let _ = self.process_restore_dl_loop(backup_root).await?;
|
let _ = self.process_restore_dl_loop(backup_root).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1184,28 +1131,14 @@ impl MobileBackup2Client {
|
|||||||
.or(target_udid)
|
.or(target_udid)
|
||||||
.ok_or(IdeviceError::InvalidHostID)?;
|
.ok_or(IdeviceError::InvalidHostID)?;
|
||||||
self.assert_backup_exists(backup_root, source)?;
|
self.assert_backup_exists(backup_root, source)?;
|
||||||
|
let dict = crate::plist!(dict {
|
||||||
let mut dict = Dictionary::new();
|
"MessageName": "Extract",
|
||||||
dict.insert("MessageName".into(), plist::Value::String("Extract".into()));
|
"TargetIdentifier": target_udid.unwrap(),
|
||||||
dict.insert(
|
"DomainName": domain_name,
|
||||||
"TargetIdentifier".into(),
|
"RelativePath": relative_path,
|
||||||
plist::Value::String(target_udid.unwrap().to_string()),
|
"SourceIdentifier": source,
|
||||||
);
|
"Password":? password,
|
||||||
dict.insert(
|
});
|
||||||
"DomainName".into(),
|
|
||||||
plist::Value::String(domain_name.to_string()),
|
|
||||||
);
|
|
||||||
dict.insert(
|
|
||||||
"RelativePath".into(),
|
|
||||||
plist::Value::String(relative_path.to_string()),
|
|
||||||
);
|
|
||||||
dict.insert(
|
|
||||||
"SourceIdentifier".into(),
|
|
||||||
plist::Value::String(source.to_string()),
|
|
||||||
);
|
|
||||||
if let Some(pw) = password {
|
|
||||||
dict.insert("Password".into(), plist::Value::String(pw.to_string()));
|
|
||||||
}
|
|
||||||
self.send_device_link_message("Extract", Some(dict)).await?;
|
self.send_device_link_message("Extract", Some(dict)).await?;
|
||||||
let _ = self.process_restore_dl_loop(backup_root).await?;
|
let _ = self.process_restore_dl_loop(backup_root).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1219,21 +1152,12 @@ impl MobileBackup2Client {
|
|||||||
new: Option<&str>,
|
new: Option<&str>,
|
||||||
) -> Result<(), IdeviceError> {
|
) -> Result<(), IdeviceError> {
|
||||||
let target_udid = self.idevice.udid();
|
let target_udid = self.idevice.udid();
|
||||||
let mut dict = Dictionary::new();
|
let dict = crate::plist!(dict {
|
||||||
dict.insert(
|
"MessageName": "ChangePassword",
|
||||||
"MessageName".into(),
|
"TargetIdentifier": target_udid.ok_or(IdeviceError::InvalidHostID)?,
|
||||||
plist::Value::String("ChangePassword".into()),
|
"OldPassword":? old,
|
||||||
);
|
"NewPassword":? new
|
||||||
dict.insert(
|
});
|
||||||
"TargetIdentifier".into(),
|
|
||||||
plist::Value::String(target_udid.ok_or(IdeviceError::InvalidHostID)?.to_string()),
|
|
||||||
);
|
|
||||||
if let Some(o) = old {
|
|
||||||
dict.insert("OldPassword".into(), plist::Value::String(o.to_string()));
|
|
||||||
}
|
|
||||||
if let Some(n) = new {
|
|
||||||
dict.insert("NewPassword".into(), plist::Value::String(n.to_string()));
|
|
||||||
}
|
|
||||||
self.send_device_link_message("ChangePassword", Some(dict))
|
self.send_device_link_message("ChangePassword", Some(dict))
|
||||||
.await?;
|
.await?;
|
||||||
let _ = self.process_restore_dl_loop(backup_root).await?;
|
let _ = self.process_restore_dl_loop(backup_root).await?;
|
||||||
@@ -1243,15 +1167,10 @@ impl MobileBackup2Client {
|
|||||||
/// Erase device via mobilebackup2
|
/// Erase device via mobilebackup2
|
||||||
pub async fn erase_device_from_path(&mut self, backup_root: &Path) -> Result<(), IdeviceError> {
|
pub async fn erase_device_from_path(&mut self, backup_root: &Path) -> Result<(), IdeviceError> {
|
||||||
let target_udid = self.idevice.udid();
|
let target_udid = self.idevice.udid();
|
||||||
let mut dict = Dictionary::new();
|
let dict = crate::plist!(dict {
|
||||||
dict.insert(
|
"MessageName": "EraseDevice",
|
||||||
"MessageName".into(),
|
"TargetIdentifier": target_udid.ok_or(IdeviceError::InvalidHostID)?
|
||||||
plist::Value::String("EraseDevice".into()),
|
});
|
||||||
);
|
|
||||||
dict.insert(
|
|
||||||
"TargetIdentifier".into(),
|
|
||||||
plist::Value::String(target_udid.ok_or(IdeviceError::InvalidHostID)?.to_string()),
|
|
||||||
);
|
|
||||||
self.send_device_link_message("EraseDevice", Some(dict))
|
self.send_device_link_message("EraseDevice", Some(dict))
|
||||||
.await?;
|
.await?;
|
||||||
let _ = self.process_restore_dl_loop(backup_root).await?;
|
let _ = self.process_restore_dl_loop(backup_root).await?;
|
||||||
@@ -1291,10 +1210,10 @@ impl MobileBackup2Client {
|
|||||||
/// Returns `IdeviceError` if disconnection fails
|
/// Returns `IdeviceError` if disconnection fails
|
||||||
pub async fn disconnect(&mut self) -> Result<(), IdeviceError> {
|
pub async fn disconnect(&mut self) -> Result<(), IdeviceError> {
|
||||||
// Send DLMessageDisconnect array per DeviceLink protocol
|
// Send DLMessageDisconnect array per DeviceLink protocol
|
||||||
let arr = vec![
|
let arr = crate::plist!(array [
|
||||||
plist::Value::String("DLMessageDisconnect".into()),
|
"DLMessageDisconnect",
|
||||||
plist::Value::String("___EmptyParameterString___".into()),
|
"___EmptyParameterString___"
|
||||||
];
|
]);
|
||||||
self.send_dl_array(arr).await?;
|
self.send_dl_array(arr).await?;
|
||||||
debug!("Disconnected from backup service");
|
debug!("Disconnected from backup service");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
//! https://github.com/doronz88/pymobiledevice3/blob/master/pymobiledevice3/services/os_trace.py
|
//! https://github.com/doronz88/pymobiledevice3/blob/master/pymobiledevice3/services/os_trace.py
|
||||||
|
|
||||||
use chrono::{DateTime, NaiveDateTime};
|
use chrono::{DateTime, NaiveDateTime};
|
||||||
use plist::Dictionary;
|
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
use crate::{Idevice, IdeviceError, IdeviceService, obf};
|
use crate::{Idevice, IdeviceError, IdeviceService, obf};
|
||||||
@@ -70,15 +69,14 @@ impl OsTraceRelayClient {
|
|||||||
Some(p) => p as i64,
|
Some(p) => p as i64,
|
||||||
None => -1,
|
None => -1,
|
||||||
};
|
};
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Request".into(), "StartActivity".into());
|
"Request": "StartActivity",
|
||||||
req.insert("Pid".into(), Into::into(pid));
|
"Pid": pid,
|
||||||
req.insert("MessageFilter".into(), Into::into(65_535));
|
"MessageFilter": 65_535,
|
||||||
req.insert("StreamFlags".into(), Into::into(60));
|
"StreamFlags": 60
|
||||||
|
});
|
||||||
|
|
||||||
self.idevice
|
self.idevice.send_bplist(req).await?;
|
||||||
.send_bplist(plist::Value::Dictionary(req))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Read a single byte
|
// Read a single byte
|
||||||
self.idevice.read_raw(1).await?;
|
self.idevice.read_raw(1).await?;
|
||||||
@@ -100,12 +98,11 @@ impl OsTraceRelayClient {
|
|||||||
|
|
||||||
/// Get the list of available PIDs
|
/// Get the list of available PIDs
|
||||||
pub async fn get_pid_list(&mut self) -> Result<Vec<u64>, IdeviceError> {
|
pub async fn get_pid_list(&mut self) -> Result<Vec<u64>, IdeviceError> {
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Request".into(), "PidList".into());
|
"Request": "PidList"
|
||||||
|
});
|
||||||
|
|
||||||
self.idevice
|
self.idevice.send_bplist(req).await?;
|
||||||
.send_bplist(plist::Value::Dictionary(req))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Read a single byte
|
// Read a single byte
|
||||||
self.idevice.read_raw(1).await?;
|
self.idevice.read_raw(1).await?;
|
||||||
@@ -133,24 +130,14 @@ impl OsTraceRelayClient {
|
|||||||
age_limit: Option<u64>,
|
age_limit: Option<u64>,
|
||||||
start_time: Option<u64>,
|
start_time: Option<u64>,
|
||||||
) -> Result<(), IdeviceError> {
|
) -> Result<(), IdeviceError> {
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("Request".into(), "CreateArchive".into());
|
"Request": "CreateArchive",
|
||||||
|
"SizeLimit":? size_limit,
|
||||||
|
"AgeLimit":? age_limit,
|
||||||
|
"StartTime":? start_time,
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(size) = size_limit {
|
self.idevice.send_bplist(req).await?;
|
||||||
req.insert("SizeLimit".into(), size.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(age) = age_limit {
|
|
||||||
req.insert("AgeLimit".into(), age.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(time) = start_time {
|
|
||||||
req.insert("StartTime".into(), time.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.idevice
|
|
||||||
.send_bplist(plist::Value::Dictionary(req))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Read a single byte
|
// Read a single byte
|
||||||
if self.idevice.read_raw(1).await?[0] != 1 {
|
if self.idevice.read_raw(1).await?[0] != 1 {
|
||||||
|
|||||||
@@ -35,12 +35,11 @@ impl RestoreServiceClient {
|
|||||||
|
|
||||||
/// Enter recovery
|
/// Enter recovery
|
||||||
pub async fn enter_recovery(&mut self) -> Result<(), IdeviceError> {
|
pub async fn enter_recovery(&mut self) -> Result<(), IdeviceError> {
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("command".into(), "recovery".into());
|
"command": "recovery"
|
||||||
|
});
|
||||||
|
|
||||||
self.stream
|
self.stream.send_object(req, true).await?;
|
||||||
.send_object(plist::Value::Dictionary(req), true)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.stream.recv().await?;
|
let res = self.stream.recv().await?;
|
||||||
let mut res = match res {
|
let mut res = match res {
|
||||||
@@ -69,12 +68,10 @@ impl RestoreServiceClient {
|
|||||||
|
|
||||||
/// Reboot
|
/// Reboot
|
||||||
pub async fn reboot(&mut self) -> Result<(), IdeviceError> {
|
pub async fn reboot(&mut self) -> Result<(), IdeviceError> {
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("command".into(), "reboot".into());
|
"command": "reboot"
|
||||||
|
});
|
||||||
self.stream
|
self.stream.send_object(req, true).await?;
|
||||||
.send_object(plist::Value::Dictionary(req), true)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.stream.recv().await?;
|
let res = self.stream.recv().await?;
|
||||||
let mut res = match res {
|
let mut res = match res {
|
||||||
@@ -103,12 +100,10 @@ impl RestoreServiceClient {
|
|||||||
|
|
||||||
/// Get preflightinfo
|
/// Get preflightinfo
|
||||||
pub async fn get_preflightinfo(&mut self) -> Result<Dictionary, IdeviceError> {
|
pub async fn get_preflightinfo(&mut self) -> Result<Dictionary, IdeviceError> {
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("command".into(), "getpreflightinfo".into());
|
"command": "getpreflightinfo"
|
||||||
|
});
|
||||||
self.stream
|
self.stream.send_object(req, true).await?;
|
||||||
.send_object(plist::Value::Dictionary(req), true)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.stream.recv().await?;
|
let res = self.stream.recv().await?;
|
||||||
let mut res = match res {
|
let mut res = match res {
|
||||||
@@ -133,12 +128,10 @@ impl RestoreServiceClient {
|
|||||||
/// Get nonces
|
/// Get nonces
|
||||||
/// Doesn't seem to work
|
/// Doesn't seem to work
|
||||||
pub async fn get_nonces(&mut self) -> Result<Dictionary, IdeviceError> {
|
pub async fn get_nonces(&mut self) -> Result<Dictionary, IdeviceError> {
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("command".into(), "getnonces".into());
|
"command": "getnonces"
|
||||||
|
});
|
||||||
self.stream
|
self.stream.send_object(req, true).await?;
|
||||||
.send_object(plist::Value::Dictionary(req), true)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.stream.recv().await?;
|
let res = self.stream.recv().await?;
|
||||||
let mut res = match res {
|
let mut res = match res {
|
||||||
@@ -163,12 +156,10 @@ impl RestoreServiceClient {
|
|||||||
/// Get app parameters
|
/// Get app parameters
|
||||||
/// Doesn't seem to work
|
/// Doesn't seem to work
|
||||||
pub async fn get_app_parameters(&mut self) -> Result<Dictionary, IdeviceError> {
|
pub async fn get_app_parameters(&mut self) -> Result<Dictionary, IdeviceError> {
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("command".into(), "getappparameters".into());
|
"command": "getappparameters"
|
||||||
|
});
|
||||||
self.stream
|
self.stream.send_object(req, true).await?;
|
||||||
.send_object(plist::Value::Dictionary(req), true)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.stream.recv().await?;
|
let res = self.stream.recv().await?;
|
||||||
let mut res = match res {
|
let mut res = match res {
|
||||||
@@ -195,13 +186,11 @@ impl RestoreServiceClient {
|
|||||||
pub async fn restore_lang(&mut self, language: impl Into<String>) -> Result<(), IdeviceError> {
|
pub async fn restore_lang(&mut self, language: impl Into<String>) -> Result<(), IdeviceError> {
|
||||||
let language = language.into();
|
let language = language.into();
|
||||||
|
|
||||||
let mut req = Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("command".into(), "restorelang".into());
|
"command": "restorelang",
|
||||||
req.insert("argument".into(), language.into());
|
"argument": language,
|
||||||
|
});
|
||||||
self.stream
|
self.stream.send_object(req, true).await?;
|
||||||
.send_object(plist::Value::Dictionary(req), true)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let res = self.stream.recv().await?;
|
let res = self.stream.recv().await?;
|
||||||
let mut res = match res {
|
let mut res = match res {
|
||||||
|
|||||||
@@ -57,12 +57,11 @@ impl SpringBoardServicesClient {
|
|||||||
&mut self,
|
&mut self,
|
||||||
bundle_identifier: String,
|
bundle_identifier: String,
|
||||||
) -> Result<Vec<u8>, IdeviceError> {
|
) -> Result<Vec<u8>, IdeviceError> {
|
||||||
let mut req = plist::Dictionary::new();
|
let req = crate::plist!({
|
||||||
req.insert("command".into(), "getIconPNGData".into());
|
"command": "getIconPNGData",
|
||||||
req.insert("bundleId".into(), bundle_identifier.into());
|
"bundleId": bundle_identifier,
|
||||||
self.idevice
|
});
|
||||||
.send_plist(plist::Value::Dictionary(req))
|
self.idevice.send_plist(req).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
let mut res = self.idevice.read_plist().await?;
|
let mut res = self.idevice.read_plist().await?;
|
||||||
match res.remove("pngData") {
|
match res.remove("pngData") {
|
||||||
|
|||||||
Reference in New Issue
Block a user