about summary refs log tree commit diff
path: root/corgi/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'corgi/src/main.rs')
-rw-r--r--corgi/src/main.rs49
1 files changed, 47 insertions, 2 deletions
diff --git a/corgi/src/main.rs b/corgi/src/main.rs
index b8b23de..ba7195b 100644
--- a/corgi/src/main.rs
+++ b/corgi/src/main.rs
@@ -147,8 +147,8 @@ impl Svc {
 		// Collect things we need from the request before we eat it's body
 		let method = req.method().as_str().to_ascii_uppercase();
 		let version = req.version();
-		let path = req.uri().path().to_owned();
-		let query = req.uri().query().unwrap_or_default().to_owned();
+		let path = url_decode(req.uri().path().to_owned(), false).unwrap();
+		let query = url_decode(req.uri().query().unwrap_or_default().to_owned(), false).unwrap();
 		let headers = req.headers().clone();
 
 		let body = req.into_body().collect().await.unwrap().to_bytes().to_vec();
@@ -280,3 +280,48 @@ impl Svc {
 		ret
 	}
 }
+
+// Ripped and modified from gennyble/mavourings query.rs
+fn url_decode<S: AsRef<str>>(urlencoded: S, plus_as_space: bool) -> Option<String> {
+	let urlencoded = urlencoded.as_ref();
+	let mut uncoded: Vec<u8> = Vec::with_capacity(urlencoded.len());
+
+	let mut chars = urlencoded.chars().peekable();
+	loop {
+		let mut utf8_bytes = [0; 4];
+		match chars.next() {
+			Some('+') => match plus_as_space {
+				true => uncoded.push(b' '),
+				false => uncoded.push(b'+'),
+			},
+			Some('%') => match chars.peek() {
+				Some(c) if c.is_ascii_hexdigit() => {
+					let upper = chars.next().unwrap();
+
+					if let Some(lower) = chars.peek() {
+						if lower.is_ascii_hexdigit() {
+							let upper = upper.to_digit(16).unwrap();
+							let lower = chars.next().unwrap().to_digit(16).unwrap();
+
+							uncoded.push(upper as u8 * 16 + lower as u8);
+							continue;
+						}
+					}
+
+					uncoded.push(b'%');
+					uncoded.extend_from_slice(upper.encode_utf8(&mut utf8_bytes).as_bytes());
+				}
+				_ => {
+					uncoded.push(b'%');
+				}
+			},
+			Some(c) => {
+				uncoded.extend_from_slice(c.encode_utf8(&mut utf8_bytes).as_bytes());
+			}
+			None => {
+				uncoded.shrink_to_fit();
+				return String::from_utf8(uncoded).ok();
+			}
+		}
+	}
+}