diff --git a/Cargo.lock b/Cargo.lock index 1f035a9..36bf3f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,6 +447,7 @@ dependencies = [ "console_error_panic_hook", "getrandom", "umc_kuwo", + "umc_ncm", "umc_qmc", "wasm-bindgen", "wasm-bindgen-test", diff --git a/um_wasm/Cargo.toml b/um_wasm/Cargo.toml index a3982ad..120da76 100644 --- a/um_wasm/Cargo.toml +++ b/um_wasm/Cargo.toml @@ -24,6 +24,7 @@ getrandom = { version = "0.2", features = ["js"] } # code size when deploying. console_error_panic_hook = { version = "0.1.7", optional = true } umc_kuwo = { path = "../um_crypto/kuwo" } +umc_ncm = { path = "../um_crypto/ncm" } umc_qmc = { path = "../um_crypto/qmc" } [dev-dependencies] diff --git a/um_wasm/src/exports/mod.rs b/um_wasm/src/exports/mod.rs index a789c2f..c9f50b9 100644 --- a/um_wasm/src/exports/mod.rs +++ b/um_wasm/src/exports/mod.rs @@ -1,2 +1,3 @@ pub mod kuwo; +pub mod ncm; pub mod qmc; diff --git a/um_wasm/src/exports/ncm.rs b/um_wasm/src/exports/ncm.rs new file mode 100644 index 0000000..031f577 --- /dev/null +++ b/um_wasm/src/exports/ncm.rs @@ -0,0 +1,62 @@ +use umc_ncm::header::NCMFile; +use umc_ncm::NetEaseCryptoError; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsError; + +/// QMC Footer. +#[wasm_bindgen(js_name=NCMFile)] +pub struct JsNCMFile { + ncm: Option, +} + +#[wasm_bindgen(js_class=NCMFile)] +impl JsNCMFile { + /// Open NCM file. + /// If everything is ok, return `0`. + /// + /// # Arguments + /// + /// * `header`: Header bytes of NCM file. + /// + /// returns: Result + /// + /// If it needs more bytes, the new header size will be returned. + /// If the header was large enough, it will return 0. + pub fn open(&mut self, header: &[u8]) -> Result { + match NCMFile::new(header) { + Ok(ncm) => { + self.ncm = Some(ncm); + Ok(0) + } + Err(NetEaseCryptoError::HeaderTooSmall(n)) => Ok(n), + Err(err) => Err(JsError::new(err.to_string().as_str())), + } + } + + /// Decrypt buffer. + /// + /// # Arguments + /// + /// * `buffer`: Buffer to decrypt. + /// * `offset`: Offset (start from 0, of encrypted binary data) + /// + /// returns: Result<(), JsError> + pub fn decrypt(&self, buffer: &mut [u8], offset: usize) -> Result<(), JsError> { + if let Some(ncm) = &self.ncm { + ncm.decrypt(buffer, offset); + Ok(()) + } else { + Err(JsError::new("NCMFile not initialized.")) + } + } + + /// Get audio data offset. + #[wasm_bindgen(getter, js_name=audioOffset)] + pub fn get_audio_offset(&self) -> Result { + if let Some(ncm) = &self.ncm { + Ok(ncm.audio_data_offset) + } else { + Err(JsError::new("NCMFile not initialized.")) + } + } +}