Obtain oodle DLL automatically

This commit is contained in:
Truman Kilen 2023-04-13 02:01:19 -05:00
parent e407340525
commit ad22ba9b1a
5 changed files with 53 additions and 7 deletions

View file

@ -11,6 +11,7 @@ edition = "2021"
[workspace.dependencies] [workspace.dependencies]
aes = "0.8.2" aes = "0.8.2"
base64 = "0.21.0" base64 = "0.21.0"
hex = "0.4.3"
strum = { version = "0.24", features = ["derive"] } strum = { version = "0.24", features = ["derive"] }
# generated by 'cargo dist init' # generated by 'cargo dist init'

View file

@ -14,6 +14,10 @@ thiserror = "1.0"
sha1 = "0.10.5" sha1 = "0.10.5"
strum = { workspace = true } strum = { workspace = true }
libloading = "0.7.4" libloading = "0.7.4"
ureq = "2.6.2"
hex-literal = "0.4.1"
hex = { workspace = true }
once_cell = "1.17.1"
[dev-dependencies] [dev-dependencies]
base64 = { workspace = true } base64 = { workspace = true }

View file

@ -364,12 +364,15 @@ impl Entry {
Some(Compression::Gzip) => decompress!(flate2::read::GzDecoder<&[u8]>), Some(Compression::Gzip) => decompress!(flate2::read::GzDecoder<&[u8]>),
Some(Compression::Oodle) => { Some(Compression::Oodle) => {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
return Err(super::Error::Oodle()); return Err(super::Error::Oodle);
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
unsafe { unsafe {
let lib = libloading::Library::new("oo2core_9_win64.dll") use std::ops::Deref;
.map_err(|_| super::Error::OodleMissing())?; let lib = match OODLE.deref() {
Ok(lib) => Ok(lib),
Err(e) => Err(super::Error::Other(e.to_string())),
}?;
/* /*
let set_printf: libloading::Symbol< let set_printf: libloading::Symbol<
@ -459,6 +462,38 @@ impl Entry {
} }
} }
use once_cell::sync::Lazy;
static OODLE: Lazy<Result<libloading::Library, String>> =
Lazy::new(|| get_oodle().map_err(|e| e.to_string()));
static OODLE_HASH: [u8; 20] = hex_literal::hex!("4bcc73614cb8fd2b0bce8d0f91ee5f3202d9d624");
fn get_oodle() -> Result<libloading::Library, super::Error> {
use sha1::{Digest, Sha1};
let oodle = std::env::current_exe()?.with_file_name("oo2core_9_win64.dll");
if !oodle.exists() {
let mut data = vec![];
ureq::get("https://cdn.discordapp.com/attachments/817251677086285848/992648087371792404/oo2core_9_win64.dll")
.call().map_err(Box::new)?
.into_reader().read_to_end(&mut data)?;
std::fs::write(&oodle, data)?;
}
let mut hasher = Sha1::new();
hasher.update(std::fs::read(&oodle)?);
let hash = hasher.finalize();
(hash[..] == OODLE_HASH).then_some(()).ok_or_else(|| {
super::Error::Other(format!(
"oodle hash mismatch expected: {} got: {} ",
hex::encode(OODLE_HASH),
hex::encode(hash)
))
})?;
unsafe { libloading::Library::new(oodle) }.map_err(|_| super::Error::OodleFailed)
}
mod test { mod test {
#[test] #[test]
fn test_entry() { fn test_entry() {

View file

@ -19,6 +19,9 @@ pub enum Error {
#[error("utf16 conversion: {0}")] #[error("utf16 conversion: {0}")]
Utf16(#[from] std::string::FromUtf16Error), Utf16(#[from] std::string::FromUtf16Error),
#[error("ureq error: {0}")]
Ureq(#[from] Box<ureq::Error>), // boxed because ureq::Error is quite large
#[error("bufwriter dereference: {0}")] #[error("bufwriter dereference: {0}")]
IntoInner(#[from] std::io::IntoInnerError<std::io::BufWriter<Vec<u8>>>), IntoInner(#[from] std::io::IntoInnerError<std::io::BufWriter<Vec<u8>>>),
@ -30,10 +33,10 @@ pub enum Error {
Magic(u32), Magic(u32),
#[error("Oodle compression only supported on Windows (or WINE)")] #[error("Oodle compression only supported on Windows (or WINE)")]
Oodle(), Oodle,
#[error("Could not find oo2core_9_win64.dll for Oodle compression")] #[error("Could not load oo2core_9_win64.dll")]
OodleMissing(), OodleFailed,
#[error("No entry found at {0}")] #[error("No entry found at {0}")]
MissingEntry(String), MissingEntry(String),
@ -67,6 +70,9 @@ pub enum Error {
#[error("version unsupported or is encrypted (possibly missing --aes-key?)")] #[error("version unsupported or is encrypted (possibly missing --aes-key?)")]
UnsuportedOrEncrypted, UnsuportedOrEncrypted,
#[error("{0}")]
Other(String),
} }
impl std::fmt::Debug for Error { impl std::fmt::Debug for Error {

View file

@ -14,7 +14,7 @@ path = "src/main.rs"
aes = { workspace = true } aes = { workspace = true }
base64 = { workspace = true } base64 = { workspace = true }
clap = { version = "4.1.4", features = ["derive"] } clap = { version = "4.1.4", features = ["derive"] }
hex = "0.4.3" hex = { workspace = true }
indicatif = { version = "0.17.3", features = ["rayon"] } indicatif = { version = "0.17.3", features = ["rayon"] }
path-clean = "0.1.0" path-clean = "0.1.0"
path-slash = "0.2.1" path-slash = "0.2.1"