use std::path::{Path, PathBuf}; const DATA_PATH: &str = "/var/lib/voter"; fn validate_path(path: &str) -> Result { let invalid_path = || cgi::text_response(404, "Invalid path"); if path == "/" { return Err(cgi::text_response(404, "(This is the voting place. You should have been given a more specific URL for the specific thing you've been invited to vote on.)")); } if path.contains("..") || !path.starts_with("/") { return Err(invalid_path()); } let dir = Path::new(&format!("{DATA_PATH}{path}")).to_path_buf(); if !dir .canonicalize() .map_err(|_| invalid_path())? .starts_with(DATA_PATH) { return Err(invalid_path()); } if !dir.is_dir() { return Err(invalid_path()); } Ok(dir) } fn prompt_for_vote(dir: PathBuf, request: cgi::Request) -> Result { Err(cgi::text_response(503, "Not Implemented")) } fn record_vote(dir: PathBuf, request: cgi::Request) -> Result { Err(cgi::text_response(503, "Not Implemented")) } fn respond(request: cgi::Request) -> Result { let dir = validate_path(request.uri().path())?; match request.method() { &cgi::http::Method::GET => prompt_for_vote(dir, request), &cgi::http::Method::POST => record_vote(dir, request), _ => Err(cgi::text_response(405, "Huh?")), } } fn respond_or_report_error(request: cgi::Request) -> cgi::Response { match respond(request) { Ok(result) => result, Err(error) => error, } } cgi::cgi_main! { respond_or_report_error }