diff --git a/server/texture-sync-server/Cargo.toml b/server/texture-sync-server/Cargo.toml index a0f5ebd..7b9dcec 100644 --- a/server/texture-sync-server/Cargo.toml +++ b/server/texture-sync-server/Cargo.toml @@ -8,4 +8,5 @@ edition = "2018" image = "0.21.1" serde = { version = "1.0.90", features = ["derive"] } serde_json = "1.0.39" -lovecraft = "0.2.0" \ No newline at end of file +sha2 = "0.8.0" +lovecraft = "0.2.0" diff --git a/server/texture-sync-server/src/main.rs b/server/texture-sync-server/src/main.rs index 8938488..098566f 100644 --- a/server/texture-sync-server/src/main.rs +++ b/server/texture-sync-server/src/main.rs @@ -11,6 +11,8 @@ extern crate serde_json; extern crate image; extern crate lovecraft; +extern crate sha2; + pub mod model; pub mod persistency; pub mod protocol; diff --git a/server/texture-sync-server/src/persistency/collection_file.rs b/server/texture-sync-server/src/persistency/collection_file.rs index 960cf80..2277153 100644 --- a/server/texture-sync-server/src/persistency/collection_file.rs +++ b/server/texture-sync-server/src/persistency/collection_file.rs @@ -10,9 +10,29 @@ struct CollectionFile { } pub fn load_collection_file(path: &Path) -> io::Result> { - let file = fs::File::open(path)?; - let buf_reader = io::BufReader::new(file); + match fs::File::open(path) { + Ok(file) => { + let buf_reader = io::BufReader::new(file); - let collection: CollectionFile = serde_json::from_reader(buf_reader)?; - Ok(collection.textures) + let collection: CollectionFile = serde_json::from_reader(buf_reader)?; + Ok(collection.textures) + } + Err(e) => { + if e.kind() == io::ErrorKind::NotFound { + // File has not been created yet. + Ok(Vec::new()) + } else { + Err(e) + } + } + } +} + +pub fn store_collection_file(path: &Path, content: &Vec) -> io::Result<()> { + let collection_file = CollectionFile { + textures: content.clone(), + }; + let file = fs::File::create(path)?; + serde_json::to_writer(file, &collection_file)?; + Ok(()) } diff --git a/server/texture-sync-server/src/persistency/mod.rs b/server/texture-sync-server/src/persistency/mod.rs index 6d430b4..81108f7 100644 --- a/server/texture-sync-server/src/persistency/mod.rs +++ b/server/texture-sync-server/src/persistency/mod.rs @@ -11,6 +11,8 @@ use std::io; use std::path::{Path, PathBuf}; use std::sync::Arc; +use sha2::{self, Digest}; + pub use self::search::Query; mod collection_file; mod image_convert; @@ -31,6 +33,18 @@ pub struct DataStore { preview_cache: HashMap<(TextureFormat, Sha256), Arc>>, } +fn sha256(data: &[u8]) -> Sha256 { + let mut hasher = sha2::Sha256::new(); + hasher.input(data); + let hash_result = hasher.result(); + let hash_slice = hash_result.as_slice(); + let mut hash_arr = [0u8; 32]; + for i in 0..32 { + hash_arr[i] = hash_slice[i]; + } + Sha256(hash_arr) +} + impl DataStore { pub fn new(path: &Path) -> io::Result { let base_path = path.to_path_buf(); @@ -100,6 +114,11 @@ impl DataStore { match data { None => Ok(ReplaceTextureStatus::NeedTextureData(tex.texture_hash)), Some(blob) => { + if sha256(&blob) != tex.texture_hash { + return Err(ProtocolError::BadRequest( + "The texture does not have the given hash value.".to_string(), + )); + } let mut tmp_image_path = self.data_dir.clone(); tmp_image_path.push("textures"); tmp_image_path.push(format!( @@ -182,4 +201,13 @@ impl DataStore { pub fn get_texture_preview(&mut self, hash: &Sha256) -> TextureFileResult { unimplemented!(); } + + fn store_metadata(&self) -> io::Result<()> { + let mut tmp_path = self.data_dir.clone(); + tmp_path.push("collection_new.json"); + collection_file::store_collection_file(&tmp_path, &self.texture)?; + let mut final_path = self.data_dir.clone(); + final_path.push("collection.json"); + fs::rename(tmp_path, final_path) + } }