Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl NodeFilter {
node.tag == self.tag.as_str()
&& self.attrs.iter().all(|(k, v)| {
node.get_attr(k.as_str())
.is_some_and(|attr| attr.as_str() == v.as_str())
.is_some_and(|attr| attr == v.as_str())
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/notification/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(crate) async fn handle_encrypt_notification(client: &Arc<Client>, nr: &NodeR
handle_identity_change(client, nr).await;
} else if nr
.get_attr("from")
.is_some_and(|v| v.as_str() == wacore_binary::SERVER_JID)
.is_some_and(|v| v == wacore_binary::SERVER_JID)
{
let first_child_tag = nr
.children()
Expand Down
5 changes: 1 addition & 4 deletions src/pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ impl Client {
)]
pub async fn handle_iq(client: &Arc<Client>, node: &NodeRef<'_>) -> bool {
// Server JID is "s.whatsapp.net" (no @ prefix for server-only JIDs)
if node
.get_attr("from")
.is_none_or(|v| v.as_str() != SERVER_JID)
{
if node.get_attr("from").is_none_or(|v| v != SERVER_JID) {
return false;
}

Expand Down
12 changes: 2 additions & 10 deletions src/passkey/flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,11 +482,7 @@ impl Client {
/// auto-drive it if an authenticator is registered).
pub(crate) async fn handle_passkey_notification(client: &Arc<Client>, node: Arc<OwnedNodeRef>) {
// The staged rotation is security-sensitive: only honor a server request.
if node
.get()
.get_attr("from")
.is_none_or(|v| v.as_str() != SERVER_JID)
{
if node.get().get_attr("from").is_none_or(|v| v != SERVER_JID) {
warn!("ignoring passkey notification from a non-server JID");
return;
}
Expand Down Expand Up @@ -575,11 +571,7 @@ async fn auto_drive_response(
/// Handle a `crsc_continuation` notification. Spawned: it awaits an IQ round-trip
/// and must not block the receive loop.
pub(crate) async fn handle_passkey_continuation(client: &Arc<Client>, node: Arc<OwnedNodeRef>) {
if node
.get()
.get_attr("from")
.is_none_or(|v| v.as_str() != SERVER_JID)
{
if node.get().get_attr("from").is_none_or(|v| v != SERVER_JID) {
warn!("ignoring passkey continuation from a non-server JID");
return;
}
Expand Down
71 changes: 71 additions & 0 deletions wacore/binary/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,77 @@ impl OwnedNodeRef {
}
}

#[cfg(test)]
mod value_ref_compare_tests {
use super::*;
use crate::jid::Server;
use std::str::FromStr;

/// Callers compare a `ValueRef` against a literal to decide whether a
/// stanza came from the server, so `v == needle` has to answer exactly what
/// `v.as_str() == needle` answered — including for the server-only shape
/// (`s.whatsapp.net`, no user), which is the one those checks actually use.
#[test]
fn comparing_a_jid_value_matches_comparing_its_rendered_form() {
let jids = [
"s.whatsapp.net",
"5511999998888@s.whatsapp.net",
"5511999998888:7@s.whatsapp.net",
"5511999998888.2@s.whatsapp.net",
"120363012345678901@g.us",
"123456789012345@lid",
"123456789012345:9@lid",
"123456789.4:17@interop",
"status@broadcast",
"12345.6@hosted.lid",
];
let needles = [
"s.whatsapp.net",
"5511999998888@s.whatsapp.net",
"5511999998888:7@s.whatsapp.net",
"123456789012345@lid",
"",
"not-a-jid",
];

for raw in jids {
let owned = Jid::from_str(raw).unwrap_or_else(|e| panic!("{raw}: {e}"));
let borrowed = ValueRef::Jid(JidRef {
user: NodeStr::Borrowed(&owned.user),
server: owned.server,
agent: owned.agent,
device: owned.device,
integrator: owned.integrator,
});
let as_string = ValueRef::String(NodeStr::Borrowed(raw));

for needle in needles {
assert_eq!(
borrowed.as_str() == needle,
borrowed == needle,
"jid value {raw:?} vs {needle:?}"
);
assert_eq!(
as_string.as_str() == needle,
as_string == needle,
"string value {raw:?} vs {needle:?}"
);
}
}

// The server-only shape is the one the server checks compare against.
let server_only = ValueRef::Jid(JidRef {
user: NodeStr::Borrowed(""),
server: Server::Pn,
agent: 0,
device: 0,
integrator: 0,
});
assert!(server_only == "s.whatsapp.net");
assert!(server_only != "5511999998888@s.whatsapp.net");
}
}

#[cfg(test)]
mod owned_node_ref_tests {
use super::*;
Expand Down
Loading