Compare commits
No commits in common. "b1605f65bacee24495216943713d23513e1f6db9" and "687885b88d6a58fa2f2769ce30f7b445e62d374d" have entirely different histories.
b1605f65ba
...
687885b88d
@ -13,7 +13,6 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/um_crypto/kgm/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/um_crypto/kgm/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/um_crypto/joox/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/um_crypto/joox/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/um_crypto/xmly/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/um_crypto/xmly/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/um_crypto/xiami/src" isTestSource="false" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/um_wasm_loader/dist" />
|
<excludeFolder url="file://$MODULE_DIR$/um_wasm_loader/dist" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/um_wasm_loader/pkg" />
|
<excludeFolder url="file://$MODULE_DIR$/um_wasm_loader/pkg" />
|
||||||
|
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -528,7 +528,6 @@ dependencies = [
|
|||||||
"umc_ncm",
|
"umc_ncm",
|
||||||
"umc_qmc",
|
"umc_qmc",
|
||||||
"umc_utils",
|
"umc_utils",
|
||||||
"umc_xiami",
|
|
||||||
"umc_xmly",
|
"umc_xmly",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -545,7 +544,6 @@ dependencies = [
|
|||||||
"umc_kuwo",
|
"umc_kuwo",
|
||||||
"umc_ncm",
|
"umc_ncm",
|
||||||
"umc_qmc",
|
"umc_qmc",
|
||||||
"umc_xiami",
|
|
||||||
"umc_xmly",
|
"umc_xmly",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-test",
|
"wasm-bindgen-test",
|
||||||
@ -625,13 +623,6 @@ dependencies = [
|
|||||||
"md-5",
|
"md-5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "umc_xiami"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "umc_xmly"
|
name = "umc_xmly"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -11,6 +11,5 @@ umc_kgm = { path = "../um_crypto/kgm" }
|
|||||||
umc_kuwo = { path = "../um_crypto/kuwo" }
|
umc_kuwo = { path = "../um_crypto/kuwo" }
|
||||||
umc_ncm = { path = "../um_crypto/ncm" }
|
umc_ncm = { path = "../um_crypto/ncm" }
|
||||||
umc_qmc = { path = "../um_crypto/qmc" }
|
umc_qmc = { path = "../um_crypto/qmc" }
|
||||||
umc_xiami = { path = "../um_crypto/xiami" }
|
|
||||||
umc_xmly = { path = "../um_crypto/xmly" }
|
umc_xmly = { path = "../um_crypto/xmly" }
|
||||||
umc_utils = { path = "../um_crypto/utils" }
|
umc_utils = { path = "../um_crypto/utils" }
|
||||||
|
@ -5,7 +5,6 @@ pub mod kgm;
|
|||||||
pub mod ncm;
|
pub mod ncm;
|
||||||
pub mod qmc1;
|
pub mod qmc1;
|
||||||
pub mod qmc2;
|
pub mod qmc2;
|
||||||
pub mod xiami;
|
|
||||||
pub mod xmly;
|
pub mod xmly;
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
@ -22,6 +21,4 @@ pub enum Commands {
|
|||||||
JOOX(joox::ArgsJoox),
|
JOOX(joox::ArgsJoox),
|
||||||
#[command(name = "xmly")]
|
#[command(name = "xmly")]
|
||||||
XMLY(xmly::ArgsXimalaya),
|
XMLY(xmly::ArgsXimalaya),
|
||||||
#[command(name = "xiami")]
|
|
||||||
Xiami(xiami::ArgsXiami),
|
|
||||||
}
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
use crate::Cli;
|
|
||||||
use anyhow::Result;
|
|
||||||
use clap::Args;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io;
|
|
||||||
use std::io::{BufReader, BufWriter, Read, Write};
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
/// Decrypt a XM file (Xiami)
|
|
||||||
#[derive(Args)]
|
|
||||||
pub struct ArgsXiami {
|
|
||||||
/// Path to output file, e.g. /export/Music/song.flac
|
|
||||||
#[clap(short, long)]
|
|
||||||
output: PathBuf,
|
|
||||||
|
|
||||||
/// Path to input file, e.g. /export/Music/song.xm
|
|
||||||
#[arg(name = "input")]
|
|
||||||
input: PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ArgsXiami {
|
|
||||||
pub fn run(&self, cli: &Cli) -> Result<i32> {
|
|
||||||
let mut reader = BufReader::with_capacity(cli.buffer_size, File::open(&self.input)?);
|
|
||||||
let mut writer = BufWriter::with_capacity(cli.buffer_size, File::create(&self.output)?);
|
|
||||||
|
|
||||||
let mut header = [0u8; 0x10];
|
|
||||||
reader.read_exact(&mut header)?;
|
|
||||||
let xm = umc_xiami::XiamiFile::from_header(&header)?;
|
|
||||||
let mut copy_reader = (&mut reader).take(xm.copy_len as u64);
|
|
||||||
io::copy(&mut copy_reader, &mut writer)?;
|
|
||||||
|
|
||||||
let mut buffer = vec![0u8; cli.buffer_size];
|
|
||||||
loop {
|
|
||||||
let n = reader.read(&mut buffer[..])?;
|
|
||||||
if n == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
xm.decrypt(&mut buffer[..n]);
|
|
||||||
writer.write_all(&buffer[..n])?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
}
|
|
@ -33,7 +33,6 @@ fn run_command(cli: &Cli) -> Result<i32> {
|
|||||||
Some(Commands::KGM(cmd)) => cmd.run(&cli),
|
Some(Commands::KGM(cmd)) => cmd.run(&cli),
|
||||||
Some(Commands::JOOX(cmd)) => cmd.run(&cli),
|
Some(Commands::JOOX(cmd)) => cmd.run(&cli),
|
||||||
Some(Commands::XMLY(cmd)) => cmd.run(&cli),
|
Some(Commands::XMLY(cmd)) => cmd.run(&cli),
|
||||||
Some(Commands::Xiami(cmd)) => cmd.run(&cli),
|
|
||||||
None => {
|
None => {
|
||||||
// https://github.com/clap-rs/clap/issues/3857#issuecomment-1161796261
|
// https://github.com/clap-rs/clap/issues/3857#issuecomment-1161796261
|
||||||
todo!("implement a sensible default command, similar to um/cli");
|
todo!("implement a sensible default command, similar to um/cli");
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "umc_xiami"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
thiserror = "1.0.63"
|
|
@ -1,45 +0,0 @@
|
|||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum XiamiError {
|
|
||||||
#[error("header too small, require at least {0} bytes")]
|
|
||||||
HeaderTooSmall(usize),
|
|
||||||
|
|
||||||
#[error("not a xiami file")]
|
|
||||||
NotXiamiFile,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct XiamiFile {
|
|
||||||
pub copy_len: usize,
|
|
||||||
pub format: [u8; 4],
|
|
||||||
key: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl XiamiFile {
|
|
||||||
pub fn from_header(buffer: &[u8]) -> Result<Self, XiamiError> {
|
|
||||||
if buffer.len() < 0x10 {
|
|
||||||
Err(XiamiError::HeaderTooSmall(0x10))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (format, copy_len, key) = match buffer[..0x10] {
|
|
||||||
[b'i', b'f', b'm', b't', f1, f2, f3, f4, 0xfe, 0xfe, 0xfe, 0xfe, a, b, c, key] => {
|
|
||||||
let copy_len = (a as usize) | ((b as usize) << 8) | ((c as usize) << 16);
|
|
||||||
let format = [f1, f2, f3, f4];
|
|
||||||
(format, copy_len, key.wrapping_sub(1))
|
|
||||||
}
|
|
||||||
_ => Err(XiamiError::NotXiamiFile)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
copy_len,
|
|
||||||
format,
|
|
||||||
key,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decrypt(&self, buffer: &mut [u8]) {
|
|
||||||
for b in buffer.iter_mut() {
|
|
||||||
*b = self.key.wrapping_sub(*b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,7 +28,6 @@ umc_kgm = { path = "../um_crypto/kgm" }
|
|||||||
umc_kuwo = { path = "../um_crypto/kuwo" }
|
umc_kuwo = { path = "../um_crypto/kuwo" }
|
||||||
umc_ncm = { path = "../um_crypto/ncm" }
|
umc_ncm = { path = "../um_crypto/ncm" }
|
||||||
umc_qmc = { path = "../um_crypto/qmc" }
|
umc_qmc = { path = "../um_crypto/qmc" }
|
||||||
umc_xiami = { path = "../um_crypto/xiami" }
|
|
||||||
umc_xmly = { path = "../um_crypto/xmly" }
|
umc_xmly = { path = "../um_crypto/xmly" }
|
||||||
um_audio = { path = "../um_audio" }
|
um_audio = { path = "../um_audio" }
|
||||||
|
|
||||||
|
@ -4,5 +4,4 @@ pub mod kgm;
|
|||||||
pub mod kuwo;
|
pub mod kuwo;
|
||||||
pub mod ncm;
|
pub mod ncm;
|
||||||
pub mod qmc;
|
pub mod qmc;
|
||||||
mod xiami;
|
|
||||||
pub mod xmly;
|
pub mod xmly;
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
use umc_xiami::XiamiFile;
|
|
||||||
use wasm_bindgen::prelude::wasm_bindgen;
|
|
||||||
use wasm_bindgen::JsError;
|
|
||||||
|
|
||||||
/// Xiami XM file decipher.
|
|
||||||
#[wasm_bindgen(js_name=Xiami)]
|
|
||||||
pub struct JsXiami(XiamiFile);
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_class = Xiami)]
|
|
||||||
impl JsXiami {
|
|
||||||
/// Parse the Xiami header (0x400 bytes)
|
|
||||||
pub fn from_header(header: &[u8]) -> Result<JsXiami, JsError> {
|
|
||||||
let hdr = XiamiFile::from_header(header)?;
|
|
||||||
Ok(JsXiami(hdr))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decrypt encrypted buffer part.
|
|
||||||
pub fn decrypt(&self, buffer: &mut [u8]) {
|
|
||||||
self.0.decrypt(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// After header (0x10 bytes), the number of bytes should be copied without decryption.
|
|
||||||
#[wasm_bindgen(getter, js_name=copyPlainLength)]
|
|
||||||
pub fn get_copy_plain_length(&self) -> usize {
|
|
||||||
self.0.copy_len
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@unlock-music/crypto",
|
"name": "@unlock-music/crypto",
|
||||||
"version": "0.0.0-alpha.13",
|
"version": "0.0.0-alpha.12",
|
||||||
"description": "Project Unlock Music: 加解密支持库",
|
"description": "Project Unlock Music: 加解密支持库",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node build.js",
|
"build": "node build.js",
|
||||||
|
Loading…
Reference in New Issue
Block a user