Skip to content

Commit

Permalink
refactor(report): Clarified checksum handling
Browse files Browse the repository at this point in the history
letsssss goooooo oooooo simon
  • Loading branch information
onkoe committed May 4, 2024
1 parent 473101c commit 8dc8db3
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 45 deletions.
76 changes: 51 additions & 25 deletions src/file_integrity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ use std::{
};
use thiserror::Error;

use crate::{config::Config, report::Report};
use crate::{config::Config, report::ChecksumReport};

/// TODO: how to retrieve the actual pure checksum (reference value)
/// Fictional struct for the moment / prob use an external library
#[derive(Clone, Debug, PartialEq, PartialOrd, Hash)]
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct Checksum {
value: Vec<u8>,
}

impl Checksum {
/// A checksum with no stored data.
pub const UNIT_CHECKSUM: Checksum = Checksum { value: vec![] };
}

impl std::fmt::Display for Checksum {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", hex::encode(&self.value))
Expand All @@ -27,35 +32,57 @@ impl std::fmt::Display for Checksum {
struct GameFile {
path: PathBuf,
expected_checksum: Checksum,
computed_checksum: Checksum,
}

impl GameFile {
pub fn compute_real_checksum(&self) -> Checksum {
pub fn compute_real_checksum(&mut self) -> Checksum {
let mut hasher = Sha256::new();
let bytes = match fs::read(&self.path) {
Ok(bytes) => bytes,
Err(_) => return Checksum { value: vec![] },
Err(_) => return Checksum::UNIT_CHECKSUM,
};

hasher.update(&bytes);

let res = hasher.finalize();
// the checksum we get from the file
let checksum_bytes = hasher.finalize();

// dbg variables
let hex_to_str: String = res.to_vec().iter().fold(String::new(), |mut out, b| {
write!(out, "{:02x}", b).expect("Checksum hex string");
out
});
let hex_to_str: String =
checksum_bytes
.to_vec()
.iter()
.fold(String::new(), |mut out, b| {
write!(out, "{:02x}", b).expect("Checksum hex string");
out
});
dbg!(&self.path, hex_to_str);
// end of dbg

self.computed_checksum = Checksum {
value: checksum_bytes.to_vec(),
};

Checksum {
value: res.to_vec(),
value: checksum_bytes.to_vec(),
}
}

pub fn checksums_match(&self) -> bool {
self.expected_checksum == self.compute_real_checksum()
/// Makes a `ChecksumReport` for this GameFile.
pub fn get_report(&mut self) -> ChecksumReport {
// make the report
ChecksumReport {
file_path: self.path.clone(),
is_matching: self.checksums_match(),
got: self.computed_checksum.clone(),
}
}

/// Checks if the checksums are equal + compute the checksum of the file
pub fn checksums_match(&mut self) -> bool {
let real_checksum = self.compute_real_checksum();
self.expected_checksum == real_checksum
}
}

Expand Down Expand Up @@ -93,7 +120,8 @@ impl FileIntegrity {
} else {
let g_file: GameFile = GameFile {
path: p.to_path_buf(),
expected_checksum: Checksum { value: vec![] }, // Placeholder
expected_checksum: Checksum::UNIT_CHECKSUM, // Placeholder
computed_checksum: Checksum::UNIT_CHECKSUM, // Placeholder
};
game_files.push(g_file);
}
Expand All @@ -106,22 +134,20 @@ impl FileIntegrity {
}

/// Checking if EVERY file is actully matching the expected checksum
pub fn check(&self, report: &mut Report) -> bool {
let mut res = true;
pub fn check(&mut self) -> Result<(), Vec<ChecksumReport>> {
let mut failed_files = vec![];

for f in self.game_files.iter() {
for f in self.game_files.iter_mut() {
if !f.checksums_match() {
report.set_file_checksum(
f.path.to_str().unwrap().to_string(),
false,
f.compute_real_checksum().to_string(), // wouldn't it be better to change
// return type instead of calling twice this fn?
);
res = false;
return res; // to be removed later, this is to stop the loop
failed_files.push(f.get_report());
}
}
res

if failed_files.is_empty() {
Ok(()) // no failures :3
} else {
Err(failed_files)
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ fn main() -> anyhow::Result<()> {
.init();

match FileIntegrity::new(&Config::new()?) {
Ok(app) => {
let mut report = Report::new();
let _res = app.check(&mut report);
Ok(mut app) => {
let report = Report::new();
let _res = app.check();
// println!("File check result: {}", res);

report.generate_report()?;
Expand Down
29 changes: 12 additions & 17 deletions src/report.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,35 @@
use std::{collections::HashSet, io::Write};
use std::{collections::HashSet, io::Write, path::PathBuf};

use anyhow::Result;
use thiserror::Error;
use time::OffsetDateTime;

use crate::file_integrity::Checksum;

/// A specific report of a file's checksum results.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ChecksumReport {
file_path: String,
matching: bool,
got: String,
pub file_path: PathBuf,
/// Whether or not the checksums are matching. If false, assume the user is a cheating loser.
pub is_matching: bool,
pub got: Checksum,
}

/// A report of all the tool's analysis results.
/// TODO: Add PC specs, connected hardware, PID of opened programs, etc.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Report {
files_checksums: HashSet<ChecksumReport>,
incorrect_file_checksums: HashSet<ChecksumReport>,
}

impl Report {
/// Creates an empty report.
pub fn new() -> Self {
Self {
files_checksums: HashSet::new(),
incorrect_file_checksums: HashSet::new(),
}
}

/// Adds a file's checksum results to the report.
pub fn set_file_checksum(&mut self, file_path: String, matching: bool, got: String) {
self.files_checksums.insert(ChecksumReport {
file_path,
matching,
got,
});
}

/// Writes the report to disk.
pub fn generate_report(&self) -> Result<(), ReportError> {
const REPORT_FOLDER: &str = "./results/";
Expand Down Expand Up @@ -65,11 +59,12 @@ impl Report {

writeln!(file, "Report generated on: {}\n\n## Checksums", utc_date)?;

for checksum_report in &self.files_checksums {
for checksum_report in &self.incorrect_file_checksums {
writeln!(
file,
"[incorrect] --> {}: {}",
checksum_report.file_path, checksum_report.got
checksum_report.file_path.to_string_lossy(),
checksum_report.got
)?;
}

Expand Down

0 comments on commit 8dc8db3

Please sign in to comment.