From bb1442db8a6c65f7cbab3517e684c0505af6df24 Mon Sep 17 00:00:00 2001 From: Trinity Pointard Date: Mon, 11 Jun 2018 11:43:27 +0200 Subject: [PATCH] create new type SafeString to sanitise and store unsafe html --- src/main.rs | 1 + src/safe_string.rs | 103 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/safe_string.rs diff --git a/src/main.rs b/src/main.rs index ba8ddfe7..0780c07d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,6 +42,7 @@ mod models; mod schema; mod routes; mod utils; +mod safe_string; lazy_static! { pub static ref BASE_URL: String = env::var("BASE_URL") diff --git a/src/safe_string.rs b/src/safe_string.rs new file mode 100644 index 00000000..3b17a6ea --- /dev/null +++ b/src/safe_string.rs @@ -0,0 +1,103 @@ +use ammonia::clean; +use serde::{self, Serialize, Deserialize, + Serializer, Deserializer, de::Visitor}; +use std::{fmt::{self, Display}, + borrow::Borrow, io::Write, + ops::Deref}; +use diesel::{self, deserialize::Queryable, + types::ToSql, + sql_types::Text, + serialize::{self, Output}}; + +#[derive(Debug,Clone,AsExpression,FromSqlRow)] +#[sql_type = "Text"] +pub struct SafeString{ + value: String, +} + +impl SafeString{ +pub fn new(value: &str) -> Self { + SafeString{ + value: clean(&value), + } + } + pub fn set(&mut self, value: &str) { + self.value = clean(value); + } + pub fn get(&self) -> &String { + &self.value + } +} + +impl Serialize for SafeString { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, { + serializer.serialize_str(&self.value) + } +} + +struct SafeStringVisitor; + +impl<'de> Visitor<'de> for SafeStringVisitor { + type Value = SafeString; + + fn expecting(&self, formatter:&mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string") + } + + fn visit_str(self, value: &str) -> Result + where E: serde::de::Error{ + Ok(SafeString::new(value)) + } +} + +impl<'de> Deserialize<'de> for SafeString { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de>, { + Ok( + deserializer.deserialize_string(SafeStringVisitor)? + ) + } +} + +impl Queryable for SafeString { + type Row = String; + fn build(value: Self::Row) -> Self { + SafeString::new(&value) + } +} + +impl ToSql for SafeString +where + DB: diesel::backend::Backend, + str: ToSql, { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + str::to_sql(&self.value, out) + } +} + + +impl Borrow for SafeString { + fn borrow(&self) -> &str { + &self.value + } +} + +impl Display for SafeString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} + +impl Deref for SafeString { + type Target = str; + fn deref(&self) -> &str { + &self.value + } +} + +impl AsRef for SafeString { + fn as_ref(&self) -> &str { + &self.value + } +}