web: don't use carets (<,>) in URLs
Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>main
parent
4bc606236f
commit
acb26c52da
|
@ -221,6 +221,33 @@ impl StripCarets for &str {
|
|||
}
|
||||
}
|
||||
|
||||
/// Trait for stripping carets ('<','>') from Message IDs inplace.
|
||||
pub trait StripCaretsInplace {
|
||||
/// If `self` is surrounded by carets, strip them.
|
||||
fn strip_carets_inplace(self) -> Self;
|
||||
}
|
||||
|
||||
impl StripCaretsInplace for &str {
|
||||
fn strip_carets_inplace(self) -> Self {
|
||||
let mut self_ref = self.trim();
|
||||
if self_ref.starts_with('<') && self_ref.ends_with('>') {
|
||||
self_ref = &self_ref[1..self_ref.len().saturating_sub(1)];
|
||||
}
|
||||
self_ref
|
||||
}
|
||||
}
|
||||
|
||||
impl StripCaretsInplace for String {
|
||||
fn strip_carets_inplace(mut self) -> Self {
|
||||
if self.starts_with('<') && self.ends_with('>') {
|
||||
self.drain(0..1);
|
||||
let len = self.len();
|
||||
self.drain(len.saturating_sub(1)..len);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
use percent_encoding::CONTROLS;
|
||||
pub use percent_encoding::{utf8_percent_encode, AsciiSet};
|
||||
|
||||
|
|
|
@ -658,7 +658,7 @@ impl Connection {
|
|||
) -> Result<Option<DbVal<Post>>> {
|
||||
let mut stmt = self.connection.prepare(
|
||||
"SELECT *, strftime('%Y-%m', CAST(timestamp AS INTEGER), 'unixepoch') AS month_year \
|
||||
FROM post WHERE list = ? AND message_id = ?;",
|
||||
FROM post WHERE list = ?1 AND (message_id = ?2 OR concat('<', ?2, '>') = message_id);",
|
||||
)?;
|
||||
let ret = stmt
|
||||
.query_row(rusqlite::params![&list_pk, &message_id], |row| {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
use chrono::TimeZone;
|
||||
use indexmap::IndexMap;
|
||||
use mailpot::models::Post;
|
||||
use mailpot::{models::Post, StripCarets, StripCaretsInplace};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -228,7 +228,7 @@ pub async fn list_post(
|
|||
list_obj.set_safety(list_owners.as_slice(), &state.conf.administrators);
|
||||
|
||||
let context = minijinja::context! {
|
||||
canonical_url => ListPostPath(ListPathIdentifier::from(list.id.clone()), msg_id.to_string()).to_crumb(),
|
||||
canonical_url => ListPostPath(ListPathIdentifier::from(list.id.clone()), msg_id.to_string().strip_carets_inplace()).to_crumb(),
|
||||
page_title => subject_ref,
|
||||
description => &list.description,
|
||||
list => Value::from_object(list_obj),
|
||||
|
@ -239,8 +239,8 @@ pub async fn list_post(
|
|||
to => &envelope.field_to_to_string(),
|
||||
subject => &envelope.subject(),
|
||||
trimmed_subject => subject_ref,
|
||||
in_reply_to => &envelope.in_reply_to_display().map(|r| r.to_string().as_str().strip_carets().to_string()),
|
||||
references => &envelope.references().into_iter().map(|m| m.to_string().as_str().strip_carets().to_string()).collect::<Vec<String>>(),
|
||||
in_reply_to => &envelope.in_reply_to_display().map(|r| r.to_string().strip_carets_inplace()),
|
||||
references => &envelope.references().into_iter().map(|m| m.to_string().strip_carets_inplace()).collect::<Vec<String>>(),
|
||||
message_id => msg_id,
|
||||
message => post.message,
|
||||
timestamp => post.timestamp,
|
||||
|
|
|
@ -177,13 +177,10 @@ macro_rules! list_post_impl {
|
|||
msg_id: Value,
|
||||
) -> std::result::Result<Value, Error> {
|
||||
urlize(state, {
|
||||
let Some(msg_id) = msg_id.as_str().map(|s| {
|
||||
if s.starts_with('<') && s.ends_with('>') {
|
||||
s.to_string()
|
||||
} else {
|
||||
format!("<{s}>")
|
||||
}
|
||||
}) else {
|
||||
let Some(msg_id) = msg_id
|
||||
.as_str()
|
||||
.map(|s| s.to_string().strip_carets_inplace())
|
||||
else {
|
||||
return Err(Error::new(
|
||||
minijinja::ErrorKind::UnknownMethod,
|
||||
"Second argument of list_post_path must be a string.",
|
||||
|
|
Loading…
Reference in New Issue