Skip to content

Commit 5485396

Browse files
committed
Fix text forwarding
1 parent 8e8bb5b commit 5485396

File tree

4 files changed

+86
-26
lines changed

4 files changed

+86
-26
lines changed

src/ids/identity_manager.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::fmt::Debug;
1818

1919
use crate::{aps::{get_message, APSConnection, APSInterestToken}, ids::{user::IDSIdentity, MessageBody}, register, util::{base64_decode, base64_encode, bin_deserialize, bin_deserialize_sha, bin_serialize, duration_since_epoch, encode_hex, plist_to_bin, plist_to_string, ungzip, Resource, ResourceManager}, APSConnectionResource, APSMessage, IDSUser, MessageInst, OSConfig, PushError};
2020

21-
use super::{user::{IDSDeliveryData, IDSNGMIdentity, IDSPublicIdentity, IDSService, IDSUserIdentity, PrivateDeviceInfo, QueryOptions, ReportMessage}, CertifiedContext, IDSRecvMessage};
21+
use super::{user::{IDSDeliveryData, IDSNGMIdentity, IDSPublicIdentity, IDSService, IDSUserIdentity, IDSUserType, PrivateDeviceInfo, QueryOptions, ReportMessage}, CertifiedContext, IDSRecvMessage};
2222

2323
const EMPTY_REFRESH: Duration = Duration::from_secs(3600); // one hour
2424

@@ -255,6 +255,10 @@ impl KeyCache {
255255
let target_tokens = keys_for.iter().map(|i| Ok(match i {
256256
MessageTarget::Token(token) => token,
257257
MessageTarget::Uuid(uuid) => {
258+
// the handle cache is madrid-only, TODO maybe fix if we ever need to
259+
let Some(handle_cache) = self.cache.get("com.apple.madrid").and_then(|a| a.get(handle)) else {
260+
return Err(PushError::KeyNotFound(handle.to_string()))
261+
};
258262
let Some(saved) = handle_cache.private_data.iter().find(|p| p.uuid.as_ref() == Some(uuid)) else {
259263
return Err(PushError::KeyNotFound(uuid.to_string()))
260264
};
@@ -585,6 +589,12 @@ impl IdentityResource {
585589
Ok(private_self.clone())
586590
}
587591

592+
// gets phone handles *REGISTERED BY THIS DEVICE*
593+
pub async fn get_my_phone_handles(&self) -> Vec<String> {
594+
let user_lock = self.users.read().await;
595+
user_lock.iter().filter(|user| user.user_type == IDSUserType::Phone).flat_map(|user| user.registration["com.apple.madrid"].handles.clone()).collect()
596+
}
597+
588598
pub async fn token_to_uuid(&self, handle: &str, token: &[u8]) -> Result<String, PushError> {
589599
let mut cache_lock = self.cache.lock().await;
590600
let private_self = &cache_lock.cache["com.apple.madrid"].get(handle).unwrap().private_data;
@@ -940,7 +950,7 @@ pub struct SendMessage {
940950
pub encryption: Option<String>,
941951
#[serde(rename = "ua")]
942952
pub user_agent: String,
943-
pub v: Option<u8>,
953+
pub v: Option<u32>,
944954
#[serde(rename = "i")]
945955
pub message_id: u32,
946956
#[serde(rename = "U")]
@@ -1050,7 +1060,7 @@ impl InnerSendJob {
10501060
command: message.command,
10511061
encryption: if !matches!(message.raw, Raw::None) { Some("pair".to_string()) } else { None },
10521062
user_agent: self.user_agent.clone(),
1053-
v: if !is_relay_message { Some(8) } else { None },
1063+
v: if !is_relay_message { Some(if self.topic == "com.apple.private.alloy.sms" { 1850 } else { 8 }) } else { None },
10541064
message_id: msg_id,
10551065
uuid: uuid.clone().into(),
10561066
payloads: group,

src/imessage/messages.rs

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,8 @@ impl MessageParts {
307307
msg
308308
}
309309

310-
fn to_sms(&self, using_number: &str, mms: bool) -> (String, Vec<RawSmsIncomingMessageData>) {
311-
let mut parts = vec![format!("s:{}", using_number)];
310+
fn to_sms(&self, from_handle: &str, mms: bool) -> (String, Vec<RawSmsIncomingMessageData>) {
311+
let mut parts = vec![format!("s:{}", from_handle)];
312312
let mut out = vec![];
313313
if !mms {
314314
parts.push("(null)(0)".to_string());
@@ -360,13 +360,7 @@ impl MessageParts {
360360
}
361361

362362
fn parse_sms(raw: &RawSmsIncomingMessage) -> MessageParts {
363-
MessageParts(raw.format.split("|").skip(1).enumerate().map(|(idx, part)| {
364-
let corresponding = if part.starts_with("(null)") {
365-
raw.content.iter().find(|i| i.content_id.is_none()).unwrap()
366-
} else {
367-
let filename = part.split("(").next().unwrap();
368-
raw.content.iter().find(|i| i.content_location.as_ref().map(|i| i.as_str()) == Some(filename)).unwrap()
369-
};
363+
fn parse_data(idx: usize, corresponding: &RawSmsIncomingMessageData) -> IndexedMessagePart {
370364
let typ = if corresponding.mime_type == "text/plain" {
371365
MessagePart::Text(String::from_utf8(corresponding.data.clone().into()).unwrap(), Default::default())
372366
} else {
@@ -384,7 +378,21 @@ impl MessageParts {
384378
idx: None,
385379
ext: None
386380
}
387-
}).collect())
381+
}
382+
383+
if raw.format.starts_with("s:") {
384+
MessageParts(raw.format.split("|").skip(1).enumerate().map(|(idx, part)| {
385+
let corresponding = if part.starts_with("(null)") {
386+
raw.content.iter().find(|i| i.content_id.is_none()).unwrap()
387+
} else {
388+
let filename = part.split("(").next().unwrap();
389+
raw.content.iter().find(|i| i.content_location.as_ref().map(|i| i.as_str()) == Some(filename)).unwrap()
390+
};
391+
parse_data(idx, corresponding)
392+
}).collect())
393+
} else {
394+
MessageParts(raw.content.iter().enumerate().map(|(idx, part)| parse_data(idx, part)).collect())
395+
}
388396
}
389397

390398
// parse XML parts
@@ -1539,13 +1547,23 @@ impl Message {
15391547
pub fn get_c(&self) -> u8 {
15401548
match self {
15411549
Self::Message(msg) => {
1542-
match msg.service {
1550+
match &msg.service {
15431551
MessageType::IMessage => 100,
1544-
MessageType::SMS { is_phone: _, using_number: _, from_handle: _ } => {
1545-
if msg.parts.has_attachments() {
1546-
144
1552+
MessageType::SMS { is_phone: _, using_number: _, from_handle } => {
1553+
if let Some(_) = from_handle {
1554+
// forwarded message
1555+
if msg.parts.has_attachments() {
1556+
141
1557+
} else {
1558+
140
1559+
}
15471560
} else {
1548-
143
1561+
// non-forwarded message
1562+
if msg.parts.has_attachments() {
1563+
144
1564+
} else {
1565+
143
1566+
}
15491567
}
15501568
}
15511569
}
@@ -1621,6 +1639,9 @@ impl Message {
16211639
("gC", Value::Integer(70000.into())),
16221640
("pID", Value::Dictionary(Dictionary::new())),
16231641
]),
1642+
Message::Message(NormalMessage { service: MessageType::SMS { .. }, .. }) => Dictionary::from_iter([
1643+
("htu", Value::Boolean(true)),
1644+
]),
16241645
_ => Default::default(),
16251646
}
16261647
}
@@ -2179,7 +2200,7 @@ impl MessageInst {
21792200
.filter(|p| *p != self.sender.as_ref().unwrap() && *p != from_handle)
21802201
.map(|p| p.replace("tel:", "")).collect();
21812202
let is_mms = my_participants.len() > 1 || normal.parts.has_attachments();
2182-
let (format, content) = normal.parts.to_sms(&using_number, is_mms);
2203+
let (format, content) = normal.parts.to_sms(&from_handle, is_mms);
21832204
let raw = RawSmsIncomingMessage {
21842205
participants: if is_mms { my_participants } else { vec![] },
21852206
sender: from_handle.replace("tel:", ""),
@@ -2610,7 +2631,12 @@ impl MessageInst {
26102631
let mut msg = wrapper.to_message(
26112632
Some(ConversationData {
26122633
participants: if loaded.participants.len() > 0 {
2613-
loaded.participants.iter().chain(std::iter::once(&loaded.sender)).map(|p| format!("tel:{p}")).collect()
2634+
let mut participants = loaded.participants.clone();
2635+
// duplicates cause chat matching in dart to fail (it is duplicate for RCS)
2636+
if !participants.contains(&loaded.sender) {
2637+
participants.push(loaded.sender.clone());
2638+
}
2639+
participants.iter().map(|p| format!("tel:{p}")).collect()
26142640
} else {
26152641
vec![format!("tel:{}", loaded.sender), format!("tel:{}", loaded.recieved_number)]
26162642
},
@@ -2637,6 +2663,7 @@ impl MessageInst {
26372663
})
26382664
)?;
26392665
msg.sent_timestamp = system_recv.duration_since(UNIX_EPOCH).unwrap().as_millis() as u64;
2666+
return Ok(msg);
26402667
}
26412668
if let Ok(loaded) = plist::from_value::<RawSmsOutgoingMessage>(&value) {
26422669
let parts = loaded.message.xhtml.as_ref().map_or_else(|| {

src/imessage/rawmessages.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,14 @@ struct RawSmsActivateMessage {
226226
ar: bool,
227227
}
228228

229+
#[derive(Serialize, Deserialize)]
230+
struct RawSmsStatusMessage {
231+
#[serde(rename = "g")]
232+
guid: String,
233+
#[serde(rename = "e")]
234+
date_read: Date,
235+
}
236+
229237
#[derive(Serialize, Deserialize)]
230238
struct RawSmsDeactivateMessage {
231239
ue: bool,
@@ -244,7 +252,7 @@ struct RawSmsParticipant {
244252
#[derive(Serialize, Deserialize)]
245253
struct RawSmsOutgoingInnerMessage {
246254
handle: Option<String>, // only for single SMS
247-
service: String, // always SMS, even for MMS chats
255+
service: String, // always SMS, even for MMS chats (RCS for rcs)
248256
#[serde(rename = "sV")]
249257
version: String, // always 1
250258
guid: String, // same as outside encryption
@@ -259,7 +267,7 @@ struct RawSmsOutgoingInnerMessage {
259267
struct RawSmsOutgoingMessage {
260268
#[serde(rename = "re")]
261269
participants: Vec<RawSmsParticipant>,
262-
ic: u32, // always seems to be 1
270+
ic: u32, // always seems to be 1, 2 for rcs
263271
#[serde(rename = "fR")]
264272
already_sent: Option<bool>,
265273
#[serde(rename = "chat-style")]

src/relay.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,22 +168,37 @@ impl OSConfig for RelayConfig {
168168
fn get_private_data(&self) -> Dictionary {
169169
let apple_epoch = SystemTime::UNIX_EPOCH + Duration::from_secs(978307200);
170170
Dictionary::from_iter([
171-
("ap", Value::String("0".to_string())), // 1 for ios
171+
// apple pay
172+
("ap", Value::String("0".to_string())),
172173

173174
("d", Value::String(format!("{:.6}", apple_epoch.elapsed().unwrap().as_secs_f64()))),
175+
// device type
174176
("dt", Value::Integer(1.into())),
177+
// green tea - ??
175178
("gt", Value::String("0".to_string())),
179+
// supports handoff
176180
("h", Value::String("1".to_string())),
177-
("m", Value::String("0".to_string())),
181+
// supports phone calls
178182
("p", Value::String("0".to_string())),
179183

180184
("pb", Value::String(self.version.software_build_id.clone())),
181185
("pn", Value::String(if self.version.software_name == "MacOS" { "macOS".to_string() } else { self.version.software_name.clone() })),
182186
("pv", Value::String(self.version.software_version.clone())),
183-
184-
("s", Value::String("0".to_string())),
187+
188+
// mms router support
189+
("m", Value::String("1".to_string())),
190+
// sms router support
191+
("s", Value::String("1".to_string())),
192+
193+
// tethering support
194+
// ec = enclosure color
195+
// c = data color
196+
// ss = service signatures
197+
// ktf = key transparency flags
198+
// ktv = key transparency version
185199
("t", Value::String("0".to_string())),
186200
("u", Value::String(self.dev_uuid.clone().to_uppercase())),
201+
// version
187202
("v", Value::String("1".to_string())),
188203
])
189204
}

0 commit comments

Comments
 (0)