From e731a5f94e1062cb62c2f8e9e123aee528b322ac Mon Sep 17 00:00:00 2001
From: Martin Fischer <martin@push-f.com>
Date: Sun, 18 Apr 2021 10:42:14 +0200
Subject: add html_escape method

---
 src/lib.rs | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/lib.rs b/src/lib.rs
index 034a21b..b32957d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,6 +3,8 @@
 
 #![cfg_attr(docsrs, feature(doc_cfg))]
 
+use std::borrow::Cow;
+
 pub use mime;
 pub use httpdate;
 
@@ -20,4 +22,34 @@ pub mod hyper_body;
 #[cfg(not(feature="hyper_body"))]
 use http;
 #[cfg(feature="hyper_body")]
-use hyper::http;
\ No newline at end of file
+use hyper::http;
+
+/// HTML escapes the given string.
+///
+/// The following characters are escaped: `<`, `>`, `&`, `"`, `'`.
+/// To mitigate the risks of forgetting to HTML escape something,
+/// it is recommended to additionally set a strict [Content Security
+/// Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
+pub fn html_escape<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
+    let input = input.into();
+    fn is_trouble(c: char) -> bool {
+        c == '<' || c == '>' || c == '&' || c == '"' || c == '\''
+    }
+
+    if input.contains(is_trouble) {
+        let mut output = String::with_capacity(input.len());
+        for c in input.chars() {
+            match c {
+                '<' => output.push_str("&lt;"),
+                '>' => output.push_str("&gt;"),
+                '&' => output.push_str("&amp;"),
+                '"' => output.push_str("&quot;"),
+                '\'' => output.push_str("&#x27;"),
+                _ => output.push(c),
+            }
+        }
+        Cow::Owned(output)
+    } else {
+        input
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3