diff --git a/filed/src/files/lookup.rs b/filed/src/files/lookup.rs index 13649df..c5270b7 100644 --- a/filed/src/files/lookup.rs +++ b/filed/src/files/lookup.rs @@ -40,6 +40,7 @@ impl FileManager { } fn save_int(self: &Self, file: &File, key: String) -> Result<(), Box> { + log::debug!("Saving a file with key: {key}"); let mut conn = self.conn.get_connection()?; conn.set(key, serde_json::to_string(&file)?)?; Ok(()) diff --git a/filed/src/files/mod.rs b/filed/src/files/mod.rs index 00994d1..cb89bde 100644 --- a/filed/src/files/mod.rs +++ b/filed/src/files/mod.rs @@ -3,7 +3,6 @@ use std::{sync::Arc, error::Error, ops::Add}; use chrono::{DateTime, Local}; -use num::BigUint; use sha2::{Sha512, Digest, digest::FixedOutput}; use serde::{Serialize, Deserialize}; use tokio::fs; @@ -15,7 +14,7 @@ pub mod lookup; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct File { pub path: String, - pub size: BigUint, + pub size: usize, pub name: Option, pub mime: String, pub delete_at: DateTime, @@ -31,6 +30,32 @@ impl File { self.sha512.clone() } + pub async fn read(self: &Self) -> Result, Box> { + let data = self.read_unchecked().await?; + let hash = hex::encode(Sha512::digest(data.as_slice())); + if self.hash() != hash { + return Err("File is corrupted".into()); + } + Ok(data) + } + + pub async fn read_unchecked(self: &Self) -> Result, Box> { + let data = fs::read(self.path.clone()).await?; + if self.size == data.len() { + return Ok(data); + } + + let mut ndata = Vec::::new(); + for byte in data.iter() { + ndata.push(byte.clone()); + if ndata.len() == self.size { + break; + } + } + + Ok(ndata) + } + pub async fn create(data: Vec, mime: String, name: Option, env: Env) -> Result> { let mut filename = String::new(); @@ -54,7 +79,7 @@ impl File { Ok( File { path: path.display().to_string(), - size: BigUint::from(data.len()), + size: data.len(), name: Some(filename), mime, delete_at: expires, diff --git a/filed/src/web/uploaded.rs b/filed/src/web/uploaded.rs index a6ced15..094b8a4 100644 --- a/filed/src/web/uploaded.rs +++ b/filed/src/web/uploaded.rs @@ -1,9 +1,32 @@ use warp::{Filter, reply::{Reply, html}, reject::Rejection}; -use super::state::SharedState; +use super::{state::SharedState, rejection::HttpReject}; pub async fn uploaded((file, _state): (String, SharedState)) -> Result, Rejection> { - Ok(Box::new(html(file))) + + let mut file_res = _state.file_mgr.find_by_hash(file.clone()) + .map_err(|x| warp::reject::custom(HttpReject::StringError(x.to_string())))?; + + if file_res.is_none() { + file_res = _state.file_mgr.find_by_name(file.clone()) + .map_err(|x| warp::reject::custom(HttpReject::StringError(x.to_string())))?; + } + + if file_res.is_none() { + return Ok( + Box::new(warp::reply::with_status("Not found", warp::http::StatusCode::NOT_FOUND)) + ) + } + let file_res = file_res.unwrap(); + + Ok( + Box::new( + warp::reply::with_header( + file_res.read_unchecked().await.unwrap(), + "Content-Type", file_res.mime + ) + ) + ) } pub fn get_uploaded(state: SharedState) -> impl Filter + Clone {