+36 -12 +/-4 browse
1 | diff --git a/core/src/lib.rs b/core/src/lib.rs |
2 | index 4f30b93..e56a80a 100644 |
3 | --- a/core/src/lib.rs |
4 | +++ b/core/src/lib.rs |
5 | @@ -221,6 +221,33 @@ impl StripCarets for &str { |
6 | } |
7 | } |
8 | |
9 | + /// Trait for stripping carets ('<','>') from Message IDs inplace. |
10 | + pub trait StripCaretsInplace { |
11 | + /// If `self` is surrounded by carets, strip them. |
12 | + fn strip_carets_inplace(self) -> Self; |
13 | + } |
14 | + |
15 | + impl StripCaretsInplace for &str { |
16 | + fn strip_carets_inplace(self) -> Self { |
17 | + let mut self_ref = self.trim(); |
18 | + if self_ref.starts_with('<') && self_ref.ends_with('>') { |
19 | + self_ref = &self_ref[1..self_ref.len().saturating_sub(1)]; |
20 | + } |
21 | + self_ref |
22 | + } |
23 | + } |
24 | + |
25 | + impl StripCaretsInplace for String { |
26 | + fn strip_carets_inplace(mut self) -> Self { |
27 | + if self.starts_with('<') && self.ends_with('>') { |
28 | + self.drain(0..1); |
29 | + let len = self.len(); |
30 | + self.drain(len.saturating_sub(1)..len); |
31 | + } |
32 | + self |
33 | + } |
34 | + } |
35 | + |
36 | use percent_encoding::CONTROLS; |
37 | pub use percent_encoding::{utf8_percent_encode, AsciiSet}; |
38 | |
39 | diff --git a/core/src/posts.rs b/core/src/posts.rs |
40 | index 259afb8..d3525dd 100644 |
41 | --- a/core/src/posts.rs |
42 | +++ b/core/src/posts.rs |
43 | @@ -658,7 +658,7 @@ impl Connection { |
44 | ) -> Result<Option<DbVal<Post>>> { |
45 | let mut stmt = self.connection.prepare( |
46 | "SELECT *, strftime('%Y-%m', CAST(timestamp AS INTEGER), 'unixepoch') AS month_year \ |
47 | - FROM post WHERE list = ? AND message_id = ?;", |
48 | + FROM post WHERE list = ?1 AND (message_id = ?2 OR concat('<', ?2, '>') = message_id);", |
49 | )?; |
50 | let ret = stmt |
51 | .query_row(rusqlite::params![&list_pk, &message_id], |row| { |
52 | diff --git a/web/src/lists.rs b/web/src/lists.rs |
53 | index 82b3bba..f9d130e 100644 |
54 | --- a/web/src/lists.rs |
55 | +++ b/web/src/lists.rs |
56 | @@ -19,7 +19,7 @@ |
57 | |
58 | use chrono::TimeZone; |
59 | use indexmap::IndexMap; |
60 | - use mailpot::models::Post; |
61 | + use mailpot::{models::Post, StripCarets, StripCaretsInplace}; |
62 | |
63 | use super::*; |
64 | |
65 | @@ -228,7 +228,7 @@ pub async fn list_post( |
66 | list_obj.set_safety(list_owners.as_slice(), &state.conf.administrators); |
67 | |
68 | let context = minijinja::context! { |
69 | - canonical_url => ListPostPath(ListPathIdentifier::from(list.id.clone()), msg_id.to_string()).to_crumb(), |
70 | + canonical_url => ListPostPath(ListPathIdentifier::from(list.id.clone()), msg_id.to_string().strip_carets_inplace()).to_crumb(), |
71 | page_title => subject_ref, |
72 | description => &list.description, |
73 | list => Value::from_object(list_obj), |
74 | @@ -239,8 +239,8 @@ pub async fn list_post( |
75 | to => &envelope.field_to_to_string(), |
76 | subject => &envelope.subject(), |
77 | trimmed_subject => subject_ref, |
78 | - in_reply_to => &envelope.in_reply_to_display().map(|r| r.to_string().as_str().strip_carets().to_string()), |
79 | - references => &envelope.references().into_iter().map(|m| m.to_string().as_str().strip_carets().to_string()).collect::<Vec<String>>(), |
80 | + in_reply_to => &envelope.in_reply_to_display().map(|r| r.to_string().strip_carets_inplace()), |
81 | + references => &envelope.references().into_iter().map(|m| m.to_string().strip_carets_inplace()).collect::<Vec<String>>(), |
82 | message_id => msg_id, |
83 | message => post.message, |
84 | timestamp => post.timestamp, |
85 | diff --git a/web/src/typed_paths.rs b/web/src/typed_paths.rs |
86 | index c21656d..6e0b3de 100644 |
87 | --- a/web/src/typed_paths.rs |
88 | +++ b/web/src/typed_paths.rs |
89 | @@ -177,13 +177,10 @@ macro_rules! list_post_impl { |
90 | msg_id: Value, |
91 | ) -> std::result::Result<Value, Error> { |
92 | urlize(state, { |
93 | - let Some(msg_id) = msg_id.as_str().map(|s| { |
94 | - if s.starts_with('<') && s.ends_with('>') { |
95 | - s.to_string() |
96 | - } else { |
97 | - format!("<{s}>") |
98 | - } |
99 | - }) else { |
100 | + let Some(msg_id) = msg_id |
101 | + .as_str() |
102 | + .map(|s| s.to_string().strip_carets_inplace()) |
103 | + else { |
104 | return Err(Error::new( |
105 | minijinja::ErrorKind::UnknownMethod, |
106 | "Second argument of list_post_path must be a string.", |