diff --git a/crates/ruma-common/CHANGELOG.md b/crates/ruma-common/CHANGELOG.md index 9cba7252..3e96cea2 100644 --- a/crates/ruma-common/CHANGELOG.md +++ b/crates/ruma-common/CHANGELOG.md @@ -18,6 +18,7 @@ Improvements: - Add `AsRef<[u8]>` implementations for identifier types - Add `InitialStateEvent::{new, to_raw, to_raw_any}` - Add a convenience method to construct `RoomEncryptionEventContent` with the recommended defaults. +- `PushCondition::EventMatch` and `FlattenedJson` now use escaped dotted paths, according to MSC3873 # 0.11.3 diff --git a/crates/ruma-common/src/push/condition.rs b/crates/ruma-common/src/push/condition.rs index a2449fd2..11fde7b3 100644 --- a/crates/ruma-common/src/push/condition.rs +++ b/crates/ruma-common/src/push/condition.rs @@ -63,7 +63,10 @@ impl RoomVersionFeature { pub enum PushCondition { /// A glob pattern match on a field of the event. EventMatch { - /// The dot-separated field of the event to match. + /// The dot-separated path of the property of the event to match. See [MSC3873] for its + /// format. + /// + /// [MSC3873]: https://github.com/matrix-org/matrix-spec-proposals/pull/3873 key: String, /// The glob-style pattern to match against. @@ -428,6 +431,7 @@ impl FlattenedJson { match value { JsonValue::Object(fields) => { for (key, value) in fields { + let key = escape_key(&key); let path = if path.is_empty() { key } else { format!("{path}.{key}") }; self.flatten_value(value, path); } @@ -447,6 +451,13 @@ impl FlattenedJson { } } +/// Escape a key for path matching. +/// +/// This escapes the dots (`.`) and backslashes (`\`) in the key with a backslash. +fn escape_key(key: &str) -> String { + key.replace('\\', r"\\").replace('.', r"\.") +} + #[cfg(test)] mod tests { use std::collections::BTreeMap; @@ -808,10 +819,13 @@ mod tests { let raw = serde_json::from_str::>( r#"{ "desc": "Level 0", + "desc.bis": "Level 0 bis", "up": { "desc": "Level 1", + "desc.bis": "Level 1 bis", "up": { - "desc": "Level 2" + "desc": "Level 2", + "desc\\bis": "Level 2 bis" } } }"#, @@ -823,8 +837,11 @@ mod tests { flattened.map, btreemap! { "desc".into() => "Level 0".into(), + r"desc\.bis".into() => "Level 0 bis".into(), "up.desc".into() => "Level 1".into(), + r"up.desc\.bis".into() => "Level 1 bis".into(), "up.up.desc".into() => "Level 2".into(), + r"up.up.desc\\bis".into() => "Level 2 bis".into(), }, ); }