extern crate hyper;
extern crate iron;
extern crate mount;
extern crate percent_encoding;
extern crate router;
use crate::noclobber::*;
use iron::request::Request;
use iron::response::Response;
use iron::{status, IronResult};
use percent_encoding::percent_decode_str;
use std::path::Path;
static DEFAULT_UPLOAD_FILENAME: &'static str = "received_file";
pub fn upload_receive_handler(request: &mut Request) -> IronResult<Response> {
let target_filename =
trusted_upload_filename_for(request).unwrap_or(DEFAULT_UPLOAD_FILENAME.to_string());
let create_ret = create_and_adapt_filename_if_exists(&target_filename);
match create_ret {
Err(_) => Ok(Response::with((
status::InternalServerError,
"Error creating file",
))),
Ok(mut file) => {
let copy_ret = std::io::copy(&mut request.body, &mut file);
match copy_ret {
Err(_) => Ok(Response::with((
status::InternalServerError,
"Error writing file",
))),
Ok(_) => Ok(Response::with((status::Ok, "ok"))),
}
}
}
}
fn trusted_upload_filename_for(request: &Request) -> Option<String> {
let untrusted_path_encoded_parts = request.url.path();
let untrusted_path_encoded = untrusted_path_encoded_parts.last()?;
let untrusted_path_cow = percent_decode_str(untrusted_path_encoded)
.decode_utf8()
.ok()?;
let untrusted_path = Path::new(untrusted_path_cow.as_ref());
let potentially_dotfilename = untrusted_path.file_name()?.to_str()?;
let trusted_path = if potentially_dotfilename.starts_with(".") {
"_".to_owned() + potentially_dotfilename
} else {
potentially_dotfilename.to_string()
};
Some(trusted_path)
}