use std::env;
use std::fs::File;
use std::error::Error;
use std::path::PathBuf;
use std::io::prelude::*;
use response::{ToOutput, Response};
use request::Request;
pub fn make_response<T: ToOutput>(body: T, c_type: &str, code: u16) -> Response {
let mut res = Response::new();
res.set_code(code);
res.set_content_type(c_type);
res.append(body);
res
}
pub fn replace_escape(path: &str) -> String {
let mut fixed = String::from(path);
let replaces: [(&str, &str); 22] = [
("%20", " "),
("%3C", "<"),
("%3E", ">"),
("%23", "#"),
("%25", "%"),
("%7B", "["),
("%7D", ")"),
("%7C", "|"),
("%5C", "\\"),
("%5E", "^"),
("%7E", "~"),
("%5B", "["),
("%5D", ")"),
("%60", "`"),
("%3B", ";"),
("%2F", "/"),
("%3F", "?"),
("%3A", ":"),
("%40", "@"),
("%3D", "="),
("%26", "&"),
("%24", "$"),
];
for &(from, to) in replaces.iter() {
fixed = fixed.replace(from, to);
}
fixed
}
fn err_body(message: &str, path: &str) -> String {
format!("<html><head>\
<style>body {{ font-family: helvetica, sans-serif; }} p {{ font-size: 14 }}</style>\
</head><body><h3>Your request failed</h3><p>{}: {}</p></body></html>", message, path)
}
pub fn err_403(req: &Request) -> Response {
make_response(err_body("forbidden", &req.path), "text/html", 403)
}
pub fn err_404(req: &Request) -> Response {
make_response(err_body("not found", &req.path), "text/html", 404)
}
pub fn err_500(req: &Request) -> Response {
make_response(err_body("internal server error", &req.path), "text/html", 500)
}
pub fn static_file(req: &Request) -> Response {
let mut res = Response::new();
let cwd = env::current_dir().unwrap();
let clean = replace_escape(&req.path);
let mut fpath = PathBuf::from(&cwd);
let mut fbuf: Vec<u8> = Vec::new();
for chunk in clean.split('/') {
if chunk == "" || chunk == "." || chunk == ".." {
continue;
}
fpath.push(&chunk);
}
let file = File::open(&fpath);
match file {
Ok(mut f) => {
match f.read_to_end(&mut fbuf) {
Ok(_) => {
res.set_code(200);
res.set_content_type("text/plain");
res.append(fbuf);
},
Err(e) => {
return make_response(err_body("internal server error", e.description()), "text/html", 500);
},
}
},
Err(_) => {
return err_404(&req);
}
}
res
}