[fractal] room-history: Fix parsing of matrix.to URIs that are not percent-encoded
- From: Kévin Commaille <kcommaille src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] room-history: Fix parsing of matrix.to URIs that are not percent-encoded
- Date: Fri, 7 Oct 2022 18:40:59 +0000 (UTC)
commit 23691dbf87fec516f3db2989b7230b339e40bbc6
Author: Kévin Commaille <zecakeh tedomum fr>
Date: Tue Sep 27 20:02:03 2022 +0200
room-history: Fix parsing of matrix.to URIs that are not percent-encoded
.../content/room_history/message_row/text.rs | 8 +--
src/utils.rs | 78 +++++++++++++++++++++-
2 files changed, 80 insertions(+), 6 deletions(-)
---
diff --git a/src/session/content/room_history/message_row/text.rs
b/src/session/content/room_history/message_row/text.rs
index c94c8bb24..879862093 100644
--- a/src/session/content/room_history/message_row/text.rs
+++ b/src/session/content/room_history/message_row/text.rs
@@ -10,7 +10,7 @@ use log::warn;
use matrix_sdk::ruma::{
events::room::message::{FormattedBody, MessageFormat},
matrix_uri::MatrixId,
- MatrixToUri, MatrixUri,
+ MatrixUri,
};
use sourceview::prelude::*;
@@ -18,7 +18,7 @@ use super::ContentFormat;
use crate::{
components::{LabelWithWidgets, Pill, DEFAULT_PLACEHOLDER},
session::{room::Member, Room, UserExt},
- utils::EMOJI_REGEX,
+ utils::{parse_matrix_to_uri, EMOJI_REGEX},
};
enum WithMentions<'a> {
@@ -375,8 +375,8 @@ fn extract_mentions(s: &str, room: &Room) -> (String, Vec<Pill>) {
let id = if let Ok(mx_uri) = MatrixUri::parse(uri) {
mx_uri.id().to_owned()
- } else if let Ok(mx_to_uri) = MatrixToUri::parse(uri) {
- mx_to_uri.id().to_owned()
+ } else if let Ok((id, _)) = parse_matrix_to_uri(uri) {
+ id
} else {
continue;
};
diff --git a/src/utils.rs b/src/utils.rs
index 8b33a623e..b765bdbcd 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -166,7 +166,7 @@ macro_rules! _add_toast {
}};
}
-use std::{path::PathBuf, str::FromStr};
+use std::{collections::HashMap, convert::TryInto, path::PathBuf, str::FromStr};
use gettextrs::gettext;
use gtk::{
@@ -174,7 +174,10 @@ use gtk::{
glib::{self, closure, Object},
};
use matrix_sdk::ruma::{
- events::room::MediaSource, EventId, OwnedEventId, OwnedTransactionId, TransactionId, UInt,
+ events::room::MediaSource, exports::percent_encoding::percent_decode_str, matrix_uri::MatrixId,
+ serde::urlencoded, EventId, IdParseError, MatrixIdError, MatrixToError, OwnedEventId,
+ OwnedServerName, OwnedTransactionId, RoomAliasId, RoomId, ServerName, TransactionId, UInt,
+ UserId,
};
use mime::Mime;
use once_cell::sync::Lazy;
@@ -478,3 +481,74 @@ pub static EMOJI_REGEX: Lazy<Regex> = Lazy::new(|| {
)
.unwrap()
});
+
+const MATRIX_TO_BASE_URL: &str = "https://matrix.to/#/";
+
+/// Parse a matrix.to URI.
+///
+/// Ruma's parsing fails with non-percent-encoded identifiers, which is the
+/// format of permalinks provided by Element Web.
+pub fn parse_matrix_to_uri(uri: &str) -> Result<(MatrixId, Vec<OwnedServerName>), IdParseError> {
+ let s = uri
+ .strip_prefix(MATRIX_TO_BASE_URL)
+ .ok_or(MatrixToError::WrongBaseUrl)?;
+ let s = s.strip_suffix('/').unwrap_or(s);
+
+ let mut parts = s.split('?');
+ let ids_part = parts.next().ok_or(MatrixIdError::NoIdentifier)?;
+ let mut ids = ids_part.split('/');
+
+ let first = ids.next().ok_or(MatrixIdError::NoIdentifier)?;
+ let first_id = percent_decode_str(first).decode_utf8()?;
+
+ let id: MatrixId = match first_id.as_bytes()[0] {
+ b'!' => {
+ let room_id = RoomId::parse(&first_id)?;
+
+ if let Some(second) = ids.next() {
+ let second_id = percent_decode_str(second).decode_utf8()?;
+ let event_id = EventId::parse(&second_id)?;
+ (room_id, event_id).into()
+ } else {
+ room_id.into()
+ }
+ }
+ b'#' => {
+ let room_id = RoomAliasId::parse(&first_id)?;
+
+ if let Some(second) = ids.next() {
+ let second_id = percent_decode_str(second).decode_utf8()?;
+ let event_id = EventId::parse(&second_id)?;
+ (room_id, event_id).into()
+ } else {
+ room_id.into()
+ }
+ }
+ b'@' => UserId::parse(&first_id)?.into(),
+ b'$' => return Err(MatrixIdError::MissingRoom.into()),
+ _ => return Err(MatrixIdError::UnknownIdentifier.into()),
+ };
+
+ if ids.next().is_some() {
+ return Err(MatrixIdError::TooManyIdentifiers.into());
+ }
+
+ let via = parts
+ .next()
+ .map(|query| {
+ let query_parts = urlencoded::from_str::<HashMap<String, String>>(query)
+ .or(Err(MatrixToError::InvalidUrl))?;
+ query_parts
+ .into_iter()
+ .filter_map(|(key, value)| (key == "via").then(|| ServerName::parse(&value)))
+ .collect::<Result<Vec<_>, _>>()
+ })
+ .transpose()?
+ .unwrap_or_default();
+
+ if parts.next().is_some() {
+ return Err(MatrixToError::InvalidUrl.into());
+ }
+
+ Ok((id, via))
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]