ruma_identifiers_validation/
mxc_uri.rs

1use std::num::NonZeroU8;
2
3use crate::{error::MxcUriError, server_name};
4
5const PROTOCOL: &str = "mxc://";
6
7pub fn validate(uri: &str) -> Result<NonZeroU8, MxcUriError> {
8    let uri = match uri.strip_prefix(PROTOCOL) {
9        Some(uri) => uri,
10        None => return Err(MxcUriError::WrongSchema),
11    };
12
13    let index = match uri.find('/') {
14        Some(index) => index,
15        None => return Err(MxcUriError::MissingSlash),
16    };
17
18    let server_name = &uri[..index];
19    let media_id = &uri[index + 1..];
20    // See: https://spec.matrix.org/v1.14/client-server-api/#security-considerations-5
21    let media_id_is_valid = media_id
22        .bytes()
23        .all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' | b'-' | b'_' ));
24
25    if !media_id_is_valid {
26        Err(MxcUriError::MediaIdMalformed)
27    } else if server_name::validate(server_name).is_err() {
28        Err(MxcUriError::ServerNameMalformed)
29    } else {
30        Ok(NonZeroU8::new((index + 6) as u8).unwrap())
31    }
32}