summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Reeder <colin@vpzom.click>2020-06-27 00:42:53 -0600
committerColin Reeder <colin@vpzom.click>2020-06-27 00:43:07 -0600
commit0402d74194a2f9df00fab82e7d4425a92c898742 (patch)
treed701791013adc7e2e3f63f00773f2f9f9651870a
parent37b2482458a5995c370fd7e59c93cd8b21fe9c1c (diff)
Add support for incoming HTML
-rw-r--r--Cargo.lock201
-rw-r--r--Cargo.toml1
-rw-r--r--src/routes/mod.rs74
3 files changed, 259 insertions, 17 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 06191e3..685d7d2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,21 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
+name = "ammonia"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89eac85170f4b3fb3dc5e442c1cfb036cb8eecf9dbbd431a161ffad15d90ea3b"
+dependencies = [
+ "html5ever",
+ "lazy_static",
+ "maplit",
+ "markup5ever_rcdom",
+ "matches",
+ "tendril",
+ "url",
+]
+
+[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -96,6 +111,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
+name = "futf"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b"
+dependencies = [
+ "mac",
+ "new_debug_unreachable",
+]
+
+[[package]]
name = "futures-channel"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -177,6 +202,7 @@ dependencies = [
name = "hitide"
version = "0.1.0"
dependencies = [
+ "ammonia",
"fallible-iterator",
"ginger",
"hyper",
@@ -191,6 +217,20 @@ dependencies = [
]
[[package]]
+name = "html5ever"
+version = "0.25.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b"
+dependencies = [
+ "log",
+ "mac",
+ "markup5ever",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "http"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -321,6 +361,47 @@ dependencies = [
]
[[package]]
+name = "mac"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
+
+[[package]]
+name = "maplit"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+
+[[package]]
+name = "markup5ever"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aae38d669396ca9b707bfc3db254bc382ddb94f57cc5c235f34623a669a01dab"
+dependencies = [
+ "log",
+ "phf",
+ "phf_codegen",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "string_cache",
+ "string_cache_codegen",
+ "tendril",
+]
+
+[[package]]
+name = "markup5ever_rcdom"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f015da43bcd8d4f144559a3423f4591d69b8ce0652c905374da7205df336ae2b"
+dependencies = [
+ "html5ever",
+ "markup5ever",
+ "tendril",
+ "xml5ever",
+]
+
+[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -393,6 +474,12 @@ dependencies = [
]
[[package]]
+name = "new_debug_unreachable"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+
+[[package]]
name = "openssl"
version = "0.10.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -432,6 +519,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
+name = "phf"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
+dependencies = [
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
name = "pin-project"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -476,6 +601,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
[[package]]
+name = "precomputed-hash"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
+
+[[package]]
name = "proc-macro2"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -504,6 +635,7 @@ dependencies = [
"rand_chacha",
"rand_core",
"rand_hc",
+ "rand_pcg",
]
[[package]]
@@ -535,6 +667,15 @@ dependencies = [
]
[[package]]
+name = "rand_pcg"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -647,6 +788,12 @@ dependencies = [
]
[[package]]
+name = "siphasher"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
+
+[[package]]
name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -671,6 +818,31 @@ dependencies = [
]
[[package]]
+name = "string_cache"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2940c75beb4e3bf3a494cef919a747a2cb81e52571e212bfbd185074add7208a"
+dependencies = [
+ "lazy_static",
+ "new_debug_unreachable",
+ "phf_shared",
+ "precomputed-hash",
+ "serde",
+]
+
+[[package]]
+name = "string_cache_codegen"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
name = "syn"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -696,6 +868,17 @@ dependencies = [
]
[[package]]
+name = "tendril"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b"
+dependencies = [
+ "futf",
+ "mac",
+ "utf-8",
+]
+
+[[package]]
name = "thiserror"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -836,6 +1019,12 @@ dependencies = [
]
[[package]]
+name = "utf-8"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
+
+[[package]]
name = "vcpkg"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -900,3 +1089,15 @@ dependencies = [
"winapi 0.2.8",
"winapi-build",
]
+
+[[package]]
+name = "xml5ever"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b1b52e6e8614d4a58b8e70cf51ec0cc21b256ad8206708bcff8139b5bbd6a59"
+dependencies = [
+ "log",
+ "mac",
+ "markup5ever",
+ "time",
+]
diff --git a/Cargo.toml b/Cargo.toml
index de43582..b851858 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,3 +19,4 @@ serde_derive = "1.0.111"
serde = "1.0.111"
fallible-iterator = "0.2.0"
ginger = "0.1.0"
+ammonia = "3.1.0"
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index f808bf1..0958813 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -113,12 +113,18 @@ struct RespMinimalAuthorInfo<'a> {
host: Cow<'a, str>,
}
+trait HavingContent {
+ fn content_text(&self) -> Option<&str>;
+ fn content_html(&self) -> Option<&str>;
+}
+
#[derive(Deserialize, Debug)]
struct RespPostListPost<'a> {
id: i64,
title: Cow<'a, str>,
href: Option<Cow<'a, str>>,
content_text: Option<Cow<'a, str>>,
+ content_html: Option<Cow<'a, str>>,
#[serde(borrow)]
author: Option<RespMinimalAuthorInfo<'a>>,
created: Cow<'a, str>,
@@ -126,17 +132,36 @@ struct RespPostListPost<'a> {
community: RespMinimalCommunityInfo<'a>,
}
+impl<'a> HavingContent for RespPostListPost<'a> {
+ fn content_text(&self) -> Option<&str> {
+ self.content_text.as_deref()
+ }
+ fn content_html(&self) -> Option<&str> {
+ self.content_html.as_deref()
+ }
+}
+
#[derive(Deserialize, Debug)]
struct RespPostCommentInfo<'a> {
id: i64,
#[serde(borrow)]
author: Option<RespMinimalAuthorInfo<'a>>,
created: Cow<'a, str>,
- content_text: Cow<'a, str>,
+ content_text: Option<Cow<'a, str>>,
+ content_html: Option<Cow<'a, str>>,
#[serde(borrow)]
replies: Option<Vec<RespPostCommentInfo<'a>>>,
}
+impl<'a> HavingContent for RespPostCommentInfo<'a> {
+ fn content_text(&self) -> Option<&str> {
+ self.content_text.as_deref()
+ }
+ fn content_html(&self) -> Option<&str> {
+ self.content_html.as_deref()
+ }
+}
+
#[derive(Deserialize, Debug)]
struct RespPostInfo<'a> {
#[serde(flatten, borrow)]
@@ -291,6 +316,33 @@ impl<'community> render::Render for CommunityLink<'community> {
}
}
+struct Content<'a, T: HavingContent + 'a> {
+ src: &'a T,
+}
+
+impl<'a, T: HavingContent + 'a> render::Render for Content<'a, T> {
+ fn render_into<W: std::fmt::Write>(self, writer: &mut W) -> std::fmt::Result {
+ match self.src.content_html() {
+ Some(html) => {
+ let cleaned = ammonia::clean(&html);
+ writer.write_str("<p>")?;
+ render::raw!(cleaned.as_ref()).render_into(writer)?;
+ writer.write_str("</p>")?;
+ }
+ None => match self.src.content_text() {
+ Some(text) => {
+ writer.write_str("<p>")?;
+ text.render_into(writer)?;
+ writer.write_str("</p>")?;
+ }
+ None => {}
+ },
+ }
+
+ Ok(())
+ }
+}
+
#[render::component]
fn Comment<'comment, 'base_data>(
comment: &'comment RespPostCommentInfo<'comment>,
@@ -299,9 +351,7 @@ fn Comment<'comment, 'base_data>(
render::rsx! {
<li>
<small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small>
- <br />
- {comment.content_text.as_ref()}
- <br />
+ <Content src={comment} />
<div class={"actionList"}>
<a href={format!("/comments/{}", comment.id)}>{"reply"}</a>
{
@@ -378,8 +428,7 @@ async fn page_comment(
<HTPage base_data={&base_data}>
<p>
<small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small>
- <br />
- {comment.content_text.as_ref()}
+ <Content src={&comment} />
</p>
<form method={"POST"} action={format!("/comments/{}/submit_reply", comment.id)}>
<div>
@@ -423,7 +472,7 @@ async fn page_comment_delete(
<p>
<small><cite><UserLink user={comment.author.as_ref()} /></cite>{":"}</small>
<br />
- {comment.content_text.as_ref()}
+ <Content src={&comment} />
</p>
<div id={"delete"}>
<h2>{"Delete this comment?"}</h2>
@@ -714,16 +763,7 @@ async fn page_post(
}
}
}
- {
- match &post.as_ref().content_text {
- None => None,
- Some(content_text) => {
- Some(render::rsx! {
- <p>{content_text.as_ref()}</p>
- })
- }
- }
- }
+ <Content src={post.as_ref()} />
{
if author_is_me(&post.as_ref().author, &base_data.login) {
Some(render::rsx! {