mirror of
https://github.com/nab138/isideload.git
synced 2026-03-02 06:26:16 +01:00
In progress small refactor
This commit is contained in:
147
isideload/src/anisette/data.rs
Normal file
147
isideload/src/anisette/data.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
use crate::{
|
||||
anisette::{AnisetteProvider, AnisetteProviderConfig, remote_v3::state::AnisetteState},
|
||||
auth::grandslam::GrandSlam,
|
||||
};
|
||||
use plist::Dictionary;
|
||||
use plist_macro::plist;
|
||||
use reqwest::header::HeaderMap;
|
||||
use rootcause::prelude::*;
|
||||
use serde::Deserialize;
|
||||
use std::{collections::HashMap, time::SystemTime};
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct AnisetteClientInfo {
|
||||
pub client_info: String,
|
||||
pub user_agent: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AnisetteData {
|
||||
pub routing_info: String,
|
||||
pub machine_id: String,
|
||||
pub one_time_password: String,
|
||||
pub device_description: String,
|
||||
pub device_unique_identifier: String,
|
||||
pub local_user_id: String,
|
||||
pub generated_at: SystemTime,
|
||||
}
|
||||
|
||||
// Some headers don't seem to be required. I guess not including them is technically more efficient soooo
|
||||
impl AnisetteData {
|
||||
pub fn get_headers(&self) -> HashMap<String, String> {
|
||||
//let dt: DateTime<Utc> = Utc::now().round_subsecs(0);
|
||||
|
||||
HashMap::from_iter(
|
||||
[
|
||||
// (
|
||||
// "X-Apple-I-Client-Time".to_string(),
|
||||
// dt.format("%+").to_string().replace("+00:00", "Z"),
|
||||
// ),
|
||||
// ("X-Apple-I-SRL-NO".to_string(), serial),
|
||||
// ("X-Apple-I-TimeZone".to_string(), "UTC".to_string()),
|
||||
// ("X-Apple-Locale".to_string(), "en_US".to_string()),
|
||||
// ("X-Apple-I-MD-RINFO".to_string(), self.routing_info.clone()),
|
||||
// ("X-Apple-I-MD-LU".to_string(), self.local_user_id.clone()),
|
||||
(
|
||||
"X-Mme-Device-Id".to_string(),
|
||||
self.device_unique_identifier.clone(),
|
||||
),
|
||||
("X-Apple-I-MD".to_string(), self.one_time_password.clone()),
|
||||
("X-Apple-I-MD-M".to_string(), self.machine_id.clone()),
|
||||
// (
|
||||
// "X-Mme-Client-Info".to_string(),
|
||||
// self.device_description.clone(),
|
||||
// ),
|
||||
]
|
||||
.into_iter(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_header_map(&self) -> HeaderMap {
|
||||
let headers_map = self.get_headers();
|
||||
let mut header_map = HeaderMap::new();
|
||||
|
||||
for (key, value) in headers_map {
|
||||
header_map.insert(
|
||||
reqwest::header::HeaderName::from_bytes(key.as_bytes()).unwrap(),
|
||||
reqwest::header::HeaderValue::from_str(&value).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
header_map
|
||||
}
|
||||
|
||||
pub fn get_client_provided_data(&self) -> Dictionary {
|
||||
let headers = self.get_headers();
|
||||
|
||||
let mut cpd = plist!(dict {
|
||||
"bootstrap": "true",
|
||||
"icscrec": "true",
|
||||
"loc": "en_US",
|
||||
"pbe": "false",
|
||||
"prkgen": "true",
|
||||
"svct": "iCloud"
|
||||
});
|
||||
|
||||
for (key, value) in headers {
|
||||
cpd.insert(key.to_string(), plist::Value::String(value));
|
||||
}
|
||||
|
||||
cpd
|
||||
}
|
||||
|
||||
pub fn needs_refresh(&self) -> bool {
|
||||
let elapsed = self.generated_at.elapsed().unwrap();
|
||||
elapsed.as_secs() > 60
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RenewableAnisetteData {
|
||||
config: AnisetteProviderConfig,
|
||||
anisette_data: Option<AnisetteData>,
|
||||
client_info: Option<AnisetteClientInfo>,
|
||||
state: Option<AnisetteState>,
|
||||
}
|
||||
|
||||
impl RenewableAnisetteData {
|
||||
pub fn new(config: AnisetteProviderConfig) -> Self {
|
||||
RenewableAnisetteData {
|
||||
config,
|
||||
anisette_data: None,
|
||||
client_info: None,
|
||||
state: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_anisette_data(&mut self, gs: &mut GrandSlam) -> Result<&AnisetteData, Report> {
|
||||
if self
|
||||
.anisette_data
|
||||
.as_ref()
|
||||
.map_or(true, |data| data.needs_refresh())
|
||||
{
|
||||
if self.client_info.is_none() || self.state.is_none() {
|
||||
let mut provider = self.config.get_provider(self.client_info.clone());
|
||||
let client_info = provider.get_client_info().await?;
|
||||
self.client_info = Some(client_info);
|
||||
let data = provider.get_anisette_data(gs).await?;
|
||||
self.anisette_data = Some(data);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(self.anisette_data.as_ref().unwrap())
|
||||
}
|
||||
|
||||
pub async fn get_client_info(
|
||||
&mut self,
|
||||
gs: &mut GrandSlam,
|
||||
) -> Result<AnisetteClientInfo, Report> {
|
||||
self.get_anisette_data(gs).await?;
|
||||
|
||||
if let Some(client_info) = &self.client_info {
|
||||
return Ok(client_info.clone());
|
||||
} else {
|
||||
bail!("Anisette client info not available");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::{
|
||||
anisette::{AnisetteData, AnisetteProvider},
|
||||
auth::{
|
||||
@@ -28,7 +30,7 @@ use tracing::{debug, info, warn};
|
||||
pub struct AppleAccount {
|
||||
pub email: String,
|
||||
pub spd: Option<plist::Dictionary>,
|
||||
pub anisette_provider: Box<dyn AnisetteProvider>,
|
||||
pub anisette_provider: Arc<Mutex<dyn AnisetteProvider + Send>>,
|
||||
pub anisette_data: AnisetteData,
|
||||
pub grandslam_client: GrandSlam,
|
||||
login_state: LoginState,
|
||||
@@ -62,7 +64,7 @@ impl AppleAccount {
|
||||
/// - `debug`: DANGER, If true, accept invalid certificates and enable verbose connection
|
||||
pub async fn new(
|
||||
email: &str,
|
||||
mut anisette_provider: Box<dyn AnisetteProvider>,
|
||||
mut anisette_provider: Arc<Mutex<dyn AnisetteProvider + Send>>,
|
||||
debug: bool,
|
||||
) -> Result<Self, Report> {
|
||||
info!("Initializing apple account");
|
||||
@@ -71,6 +73,8 @@ impl AppleAccount {
|
||||
}
|
||||
|
||||
let client_info = anisette_provider
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_client_info()
|
||||
.await
|
||||
.context("Failed to get anisette client info")?;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use plist::Dictionary;
|
||||
use plist_macro::{plist, plist_to_xml_string};
|
||||
use rootcause::prelude::*;
|
||||
@@ -6,7 +8,7 @@ use tracing::{error, warn};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
anisette::AnisetteData,
|
||||
anisette::{AnisetteData, AnisetteProvider},
|
||||
auth::{
|
||||
apple_account::{AppToken, AppleAccount},
|
||||
grandslam::GrandSlam,
|
||||
@@ -25,7 +27,7 @@ pub struct DeveloperSession<'a> {
|
||||
token: AppToken,
|
||||
adsid: String,
|
||||
client: &'a GrandSlam,
|
||||
anisette_data: &'a AnisetteData,
|
||||
anisette_provider: Arc<Mutex<dyn AnisetteProvider + Send>>,
|
||||
}
|
||||
|
||||
impl<'a> DeveloperSession<'a> {
|
||||
@@ -33,13 +35,13 @@ impl<'a> DeveloperSession<'a> {
|
||||
token: AppToken,
|
||||
adsid: String,
|
||||
client: &'a GrandSlam,
|
||||
anisette_data: &'a AnisetteData,
|
||||
anisette_provider: Arc<Mutex<dyn AnisetteProvider + Send>>,
|
||||
) -> Self {
|
||||
DeveloperSession {
|
||||
token,
|
||||
adsid,
|
||||
client,
|
||||
anisette_data,
|
||||
anisette_provider,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user