diff --git a/src/api/client_server/media.rs b/src/api/client_server/media.rs index 3897d83d..0b529851 100644 --- a/src/api/client_server/media.rs +++ b/src/api/client_server/media.rs @@ -242,37 +242,29 @@ async fn get_url_preview(url: &Url) -> Result { } } +/// Verify that the given URL's host is in the allow list. fn url_preview_allowed(url: &Url) -> bool { - const DEFAULT_ALLOWLIST: &[&str] = &[ - "matrix.org", - "mastodon.social", - "youtube.com", - "wikipedia.org", - ]; + // host's existence is already verified in get_media_preview_route, unwrap is safe + let host = url.host_str().unwrap().to_lowercase(); + let host_parts_iter = host + .char_indices() + .filter_map(|(i, c)| { + if i == 0 { + Some(host.as_str()) + } + else if c == '.' { + Some(&host[i+1..]) + } + else { + None + } + }) + .rev().skip(1); // don't match TLDs - let mut host = match url.host_str() { - None => return false, - Some(h) => h.to_lowercase(), - }; - - let allowlist = services().globals.url_preview_allowlist(); - if allowlist.contains(&"*".to_owned()) { - return true; - } - while !host.is_empty() { - if allowlist.contains(&host) { - return true; - } - if allowlist.contains(&"default".to_owned()) && DEFAULT_ALLOWLIST.contains(&host.as_str()) { - return true; - } - /* also check higher level domains, so that e.g. `en.m.wikipedia.org` is matched by `wikipedia.org` on allowlist. */ - host = match host.split_once('.') { - None => return false, - Some((_, domain)) => domain.to_owned(), - } - } - false + let ret = ["*"].into_iter().chain(host_parts_iter).any(|nld| { + services().globals.url_preview_allowlist().any(|a| a == nld) + }); + ret // temp variable to avoid returning from the closure } /// # `GET /_matrix/media/r0/preview_url` diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 134b797b..98c01902 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -324,8 +324,8 @@ impl Service { self.config.allow_federation } - pub fn url_preview_allowlist(&self) -> &Vec { - &self.config.url_preview_allowlist + pub fn url_preview_allowlist(&self) -> impl Iterator { + self.config.url_preview_allowlist.iter().map(|x| x.as_str()) } pub fn allow_room_creation(&self) -> bool {