hand

finger proxy server
Log | Files | Refs | README

commit 74e8d39d4ce976ada2b38737ab24a9d2062b6823
parent b7181e0ad7ed38fb9e4a305815520f5109c58ab8
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Thu,  2 Dec 2021 19:18:11 -0800

Add html escape, URI link

Diffstat:
Msrc/main.rs | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 79 insertions(+), 6 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -1,4 +1,5 @@ use fingers; +use std::fmt; use vial::prelude::*; routes! { @@ -6,7 +7,22 @@ routes! { POST "/" => post; } -const form: &str = r#"<style> +const form: &str = r#" +<!DOCTYPE html> +<head> +<meta charset="utf-8" /> +<title>finger.flounder.online</title> +<meta name="description" content="finger proxy server"> +<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>👆</text></svg>"> +<meta name="viewport" content="width=device-width" /> +<html lang="en"> +<style> + +@media only screen and (max-width: 600px) { + body { + font-size: 16px + } +} body { background-color: #f7ffd6; } @@ -27,6 +43,8 @@ pre { background-color: #e3fffd; } </style> +</head> +<body> <main> <h1>👐finger.flounder.online👐</h1> <form method='POST'> @@ -34,16 +52,19 @@ pre { <input type='submit'/> </form>"#; -fn index(_: Request) -> &'static str { +fn index(req: Request) -> &'static str { + // req.path + // if path != /, interpret as url form } // TODO: escape HTML // TODO: error handling -// TODO: add permalink / url params +// TODO: add permalink +// TODO: url parameters // add finger URI at bottom fn post(req: Request) -> String { - let query = req.form("query").unwrap(); + let query = req.form("query").unwrap_or(""); let user: &str; let host: &str; let params: Vec<&str> = query.split("@").collect(); @@ -54,14 +75,66 @@ fn post(req: Request) -> String { user = params[0]; host = params[1]; } + let finger_url = format!("finger://{}/{}", host, user); let response = fingers::finger(user, host) .timeout(10) .max_response_len(1024 * 10) .send() - .unwrap(); - format!("{}\n<pre class='response'>{}</pre></main>", form, response) + .unwrap_or("![Error reaching server]".to_owned()); + format!( + "{}\n<br>proxying <a href='{url}'>{url}</a><pre class='response'>{}</pre></main>", + form, + EscapedHTML(&response), + url = EscapedHTML(&finger_url) + ) +} + +// Derived from https://github.com/raphlinus/pulldown-cmark/blob/master/src/escape.rs +// Don't use single quotes (') in any of your attributes + +const fn create_html_escape_table() -> [u8; 256] { + let mut table = [0; 256]; + table[b'"' as usize] = 1; + table[b'&' as usize] = 2; + table[b'<' as usize] = 3; + table[b'>' as usize] = 4; + table } +static HTML_ESCAPE_TABLE: [u8; 256] = create_html_escape_table(); + +static HTML_ESCAPES: [&str; 5] = ["", "&quot;", "&amp;", "&lt;", "&gt;"]; + +pub struct EscapedHTML<'a>(pub &'a str); + +impl fmt::Display for EscapedHTML<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = self.0; + let bytes = s.as_bytes(); + let mut mark = 0; + let mut i = 0; + while i < s.len() { + match bytes[i..] + .iter() + .position(|&c| HTML_ESCAPE_TABLE[c as usize] != 0) + { + Some(pos) => { + i += pos; + } + None => break, + } + let c = bytes[i]; + let escape = HTML_ESCAPE_TABLE[c as usize]; + let escape_seq = HTML_ESCAPES[escape as usize]; + f.write_str(&s[mark..i])?; + f.write_str(escape_seq)?; + i += 1; + mark = i; // all escaped characters are ASCII + } + f.write_str(&s[mark..])?; + Ok(()) + } +} fn main() { vial::run!().unwrap(); }