1.添加多线程支持
2.优化代码结构 3.升级依赖
This commit is contained in:
27
src/main.rs
27
src/main.rs
@ -1,19 +1,26 @@
|
||||
use env_logger::Builder;
|
||||
use hex::decode;
|
||||
use log::{error, info, warn};
|
||||
use ncmmiao::{dump, Key, Ncmfile};
|
||||
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
// use std::time::SystemTime;
|
||||
use walkdir::WalkDir;
|
||||
#[warn(unreachable_code)]
|
||||
use walkdir::WalkDir; //遍历目录
|
||||
|
||||
mod ncmdump;
|
||||
mod threadpool;
|
||||
use ncmdump::{dump, Key, Ncmfile};
|
||||
mod test;
|
||||
|
||||
fn main() {
|
||||
// 最大线程数
|
||||
let max_workers = 4;
|
||||
|
||||
let mut builder = Builder::new();
|
||||
builder.filter(None, log::LevelFilter::Info);
|
||||
builder.init(); //初始化logger
|
||||
|
||||
let keys = Key {
|
||||
let keys: Key = Key {
|
||||
core: decode("687A4852416D736F356B496E62617857").unwrap(),
|
||||
meta: decode("2331346C6A6B5F215C5D2630553C2728").unwrap(),
|
||||
};
|
||||
@ -21,6 +28,7 @@ fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let args = if args.len() == 1 {
|
||||
warn!("未指定文件夹,将使用默认文件夹。");
|
||||
|
||||
let mut args_temp = Vec::new();
|
||||
if Path::new("CloudMusic").exists() {
|
||||
warn!("CloudMusic文件夹存在,将自动使用。");
|
||||
@ -39,7 +47,6 @@ fn main() {
|
||||
} else {
|
||||
args[1..].to_vec()
|
||||
};
|
||||
// let args = &args[1..];
|
||||
|
||||
let mut undumpfile = Vec::new(); // 该列表将存入文件的路径
|
||||
|
||||
@ -78,8 +85,14 @@ fn main() {
|
||||
// let filepaths = undumpfile;
|
||||
// let count = undumpfile.len();
|
||||
// let mut time = 0usize;
|
||||
|
||||
// 初始化线程池
|
||||
let pool = threadpool::Pool::new(max_workers);
|
||||
for filepath in undumpfile {
|
||||
let mut ncmfile = Ncmfile::new(&filepath).unwrap();
|
||||
dump(&mut ncmfile, &keys, Path::new("output")).unwrap();
|
||||
let tkey = keys.clone();
|
||||
pool.execute(move || {
|
||||
let mut ncmfile = Ncmfile::new(filepath.as_str()).unwrap();
|
||||
dump(&mut ncmfile, &tkey, Path::new("output")).unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,9 +16,9 @@ use std::str::from_utf8;
|
||||
pub struct Ncmfile {
|
||||
/// 文件对象
|
||||
pub file: File,
|
||||
/// 只是名称,不带后缀
|
||||
/// 歌曲名称,不带文件后缀
|
||||
pub name: String,
|
||||
/// 带后缀名
|
||||
/// 文件名称,带后缀名
|
||||
pub filename: String,
|
||||
/// 文件大小
|
||||
pub size: u64,
|
||||
@ -182,6 +182,7 @@ struct Metadata {
|
||||
}
|
||||
|
||||
// 存储各种密钥的结构体
|
||||
#[derive(Clone)]
|
||||
pub struct Key {
|
||||
pub core: Vec<u8>,
|
||||
pub meta: Vec<u8>,
|
||||
@ -257,7 +258,7 @@ pub fn dump(ncmfile: &mut Ncmfile, keys: &Key, outputdir: &Path) -> Result<(), M
|
||||
};
|
||||
|
||||
// 跳过4个字节的校验码
|
||||
trace!("跳过4个字节的校验码");
|
||||
trace!("读取校验码");
|
||||
let crc32 = u32::from_le_bytes(ncmfile.seekread(4).unwrap().try_into().unwrap()) as u64;
|
||||
|
||||
// 跳过5个字节
|
||||
@ -278,7 +279,7 @@ pub fn dump(ncmfile: &mut Ncmfile, keys: &Key, outputdir: &Path) -> Result<(), M
|
||||
// trace!("保存图片");
|
||||
// let mut file = File::create(format!("TEST.jpg",)).unwrap();
|
||||
// file.write_all(&image_data).unwrap();
|
||||
|
||||
trace!("组成密码盒");
|
||||
let key_box = {
|
||||
let key_length = key_data.len();
|
||||
let key_data = Vec::from(key_data);
|
||||
@ -430,6 +431,7 @@ pub fn dump(ncmfile: &mut Ncmfile, keys: &Key, outputdir: &Path) -> Result<(), M
|
||||
}
|
||||
|
||||
// fn read_meta(file: &mut File, meta_length: u32) -> Result<Vec<u8>, Error> {}
|
||||
|
||||
fn convert_to_generic_arrays(input: &[u8]) -> Vec<GenericArray<u8, U16>> {
|
||||
// 确保输入的长度是16的倍数
|
||||
assert!(
|
||||
@ -470,6 +472,8 @@ fn aes128(key: &[u8], blocks: &[u8]) -> String {
|
||||
|
||||
x.to_string()
|
||||
}
|
||||
|
||||
/// ## AES128解密
|
||||
fn aes128_to_slice(key: &[u8], blocks: &[u8]) -> Vec<u8> {
|
||||
trace!("进行AES128解密");
|
||||
let key = GenericArray::from_slice(key);
|
||||
@ -481,6 +485,8 @@ fn aes128_to_slice(key: &[u8], blocks: &[u8]) -> Vec<u8> {
|
||||
|
||||
// 开始解密
|
||||
cipher.decrypt_blocks(&mut blocks);
|
||||
|
||||
//取出解密后的值
|
||||
let mut x: Vec<u8> = Vec::new();
|
||||
for block in blocks.iter() {
|
||||
for i in block {
|
||||
@ -496,8 +502,9 @@ fn aes128_to_slice(key: &[u8], blocks: &[u8]) -> Vec<u8> {
|
||||
/// - \ / * ? " : < > |
|
||||
/// - _ _ * ? " : ⟨ ⟩ _
|
||||
fn standardize_filename(old_filename: String) -> String {
|
||||
trace!("格式化文件名");
|
||||
let mut new_filename = String::from(old_filename);
|
||||
debug!("规范文件名:{}", new_filename);
|
||||
// debug!("规范文件名:{}", new_filename);
|
||||
let standard = ["\\", "/", "*", "?", "\"", ":", "<", ">", "|"];
|
||||
let resolution = ["_", "_", "*", "?", """, ":", "⟨", "⟩", "_"];
|
||||
for i in 0..standard.len() {
|
||||
14
src/test.rs
Normal file
14
src/test.rs
Normal file
@ -0,0 +1,14 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
|
||||
#[test]
|
||||
#[ignore = "测验成功"]
|
||||
fn it_works() {
|
||||
let p = threadpool::Pool::new(4);
|
||||
p.execute(|| println!("do new job1"));
|
||||
p.execute(|| println!("do new job2"));
|
||||
p.execute(|| println!("do new job3"));
|
||||
p.execute(|| println!("do new job4"));
|
||||
}
|
||||
}
|
||||
90
src/threadpool.rs
Normal file
90
src/threadpool.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use std::sync::{mpsc, Arc, Mutex};
|
||||
use std::thread::{self, JoinHandle};
|
||||
use log::{info,debug};
|
||||
use serde::de;
|
||||
|
||||
type Job = Box<dyn FnOnce() + 'static + Send>;
|
||||
enum Message {
|
||||
ByeBye,
|
||||
NewJob(Job),
|
||||
}
|
||||
|
||||
struct Worker {
|
||||
_id: usize,
|
||||
t: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
||||
impl Worker {
|
||||
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
|
||||
let t = thread::spawn(move || loop {
|
||||
let message = receiver.lock().unwrap().recv().unwrap();
|
||||
match message {
|
||||
Message::NewJob(job) => {
|
||||
debug!("线程[{}]获得任务", id);
|
||||
job();
|
||||
}
|
||||
Message::ByeBye => {
|
||||
debug!("线程[{}]结束任务", id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Worker {
|
||||
_id: id,
|
||||
t: Some(t),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pool {
|
||||
workers: Vec<Worker>,
|
||||
max_workers: usize,
|
||||
sender: mpsc::Sender<Message>,
|
||||
}
|
||||
|
||||
impl Pool {
|
||||
pub fn new(max_workers: usize) -> Pool {
|
||||
if max_workers == 0 {
|
||||
panic!("最大线程数不能小于零!")
|
||||
}else {
|
||||
debug!("将开启{}线程",max_workers);
|
||||
}
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
let mut workers = Vec::with_capacity(max_workers);
|
||||
let receiver = Arc::new(Mutex::new(rx));
|
||||
for i in 0..max_workers {
|
||||
workers.push(Worker::new(i, Arc::clone(&receiver)));
|
||||
}
|
||||
|
||||
Pool {
|
||||
workers: workers,
|
||||
max_workers: max_workers,
|
||||
sender: tx,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute<F>(&self, f: F)
|
||||
where
|
||||
F: FnOnce() + 'static + Send,
|
||||
{
|
||||
let job = Message::NewJob(Box::new(f));
|
||||
self.sender.send(job).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Pool {
|
||||
fn drop(&mut self) {
|
||||
for _ in 0..self.max_workers {
|
||||
self.sender.send(Message::ByeBye).unwrap();
|
||||
}
|
||||
for w in self.workers.iter_mut() {
|
||||
if let Some(t) = w.t.take() {
|
||||
t.join().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user