modified: outdb

modified:   src/main.rs
	modified:   src/xobjects.rs
This commit is contained in:
Michael Wain 2025-02-08 03:40:44 +03:00
parent 84f5824411
commit 4b07a48a08
3 changed files with 94 additions and 7 deletions

BIN
outdb

Binary file not shown.

View File

@ -2,7 +2,7 @@ use std::{fs::File, io::{Read, Write}};
use env_logger::Builder; use env_logger::Builder;
use log::{error, info, LevelFilter}; use log::{error, info, LevelFilter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use xobjects::{XAlbumItem, XArgument, XDataSet, XDatabase, XPlaylist, XSomeList, XTrackItem}; use xobjects::{XAlbumItem, XArgument, XDataSet, XDatabase, XLetterJump, XPlArgument, XPlaylist, XPlaylistIndexEntry, XSomeList, XTrackItem};
mod xobjects; mod xobjects;
@ -308,7 +308,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase {
albums.last_mut().unwrap().args.push(XArgument{ arg_type: entry_type, val: g}); albums.last_mut().unwrap().args.push(XArgument{ arg_type: entry_type, val: g});
}, },
XSomeList::Playlists(playlists) => { XSomeList::Playlists(playlists) => {
playlists.last_mut().unwrap().args.push(XArgument{ arg_type: entry_type, val: g}); playlists.last_mut().unwrap().args.push(XPlArgument::String(XArgument{ arg_type: entry_type, val: g}));
}, },
XSomeList::TrackList(tracks) => { XSomeList::TrackList(tracks) => {
tracks.last_mut().unwrap().args.push(XArgument{ arg_type: entry_type, val: g}); tracks.last_mut().unwrap().args.push(XArgument{ arg_type: entry_type, val: g});
@ -325,6 +325,12 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase {
h += 4; h += 4;
} }
info!("Indexes: {:?}", v); info!("Indexes: {:?}", v);
match &mut xdb.find_dataset(last_type).child {
XSomeList::Playlists(playlists) => {
playlists.last_mut().unwrap().args.push(XPlArgument::IndexEntry(XPlaylistIndexEntry{data: entry, v}));
}
_ => {}
}
}, },
53 => { 53 => {
let entry: LetterJumpEntry = bincode::deserialize(&data[i..i+28]).unwrap(); let entry: LetterJumpEntry = bincode::deserialize(&data[i..i+28]).unwrap();
@ -336,6 +342,12 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase {
h += 12; h += 12;
} }
info!("Indexes: {:?}", v); info!("Indexes: {:?}", v);
match &mut xdb.find_dataset(last_type).child {
XSomeList::Playlists(playlists) => {
playlists.last_mut().unwrap().args.push(XPlArgument::LetterJumpEntry(XLetterJump{ data: entry, v }));
}
_ => {}
}
}, },
100 => { 100 => {
@ -431,7 +443,60 @@ fn to_bytes(xdb: XDatabase) -> Vec<u8> {
let mut pl_bytes = Vec::new(); let mut pl_bytes = Vec::new();
for u in 0..playlists.len() { for u in 0..playlists.len() {
let playlist = playlists.get(u).unwrap(); let playlist = playlists.get(u).unwrap();
let mut args = x_args_to_bytes(&playlist.args);
let mut args: Vec<u8> = playlist.args.iter()
.map(|arg| match arg {
XPlArgument::String(xarg) => {
let s = string_to_ipod16(&xarg.val);
let mut b = bincode::serialize(&StringEntry {
entry_type: xarg.arg_type,
unk1: 0,
unk2: 0,
position: 1,
length: s.len() as u32,
unknown: 0,
unk4: 0
}).unwrap();
let h = bincode::serialize(&ChunkHeader {
chunk_type: ChunkType::StringTypes.into(),
end_of_chunk: 0x18,
children_count: 16 + 0x18 + s.len() as u32
}).unwrap();
b = [h, b, s].concat();
return b;
},
XPlArgument::IndexEntry(xpl) => {
let mut b = bincode::serialize(&xpl.data).unwrap();
let mut v: Vec<u8> = Vec::new();
for i in xpl.v.iter() {
v = [v, i.to_le_bytes().to_vec()].concat();
}
let h = bincode::serialize(&ChunkHeader {
chunk_type: ChunkType::StringTypes.into(),
end_of_chunk: 60,
children_count: 60 + (4 * xpl.v.len() as u32)
}).unwrap();
b = [h, b, v].concat();
return b;
},
XPlArgument::LetterJumpEntry(xjump) => {
let mut b = bincode::serialize(&xjump.data).unwrap();
let mut v: Vec<u8> = Vec::new();
for i in xjump.v.iter() {
v.append(&mut bincode::serialize(i).unwrap());
}
let h = bincode::serialize(&ChunkHeader {
chunk_type: ChunkType::StringTypes.into(),
end_of_chunk: 28,
children_count: 28 + (12 * xjump.v.len() as u32)
}).unwrap();
b = [h, b, v].concat();
return b;
},
})
.flatten()
.collect();
pl_bytes.append(&mut generate_header(ChunkType::Playlist, 36,args.len())); pl_bytes.append(&mut generate_header(ChunkType::Playlist, 36,args.len()));
pl_bytes.append(&mut bincode::serialize(&playlist.data).unwrap()); pl_bytes.append(&mut bincode::serialize(&playlist.data).unwrap());
pl_bytes.append(&mut args); pl_bytes.append(&mut args);
@ -492,14 +557,15 @@ fn main() {
.filter(None, LevelFilter::Info) .filter(None, LevelFilter::Info)
.init(); .init();
let mut f = File::open("outdb").unwrap(); // D:\\Documents\\iTunes\\iTunesDB let mut f = File::open("D:\\Documents\\iTunes\\iTunesDB").unwrap(); // D:\\Documents\\iTunes\\iTunesDB
let mut buf = Vec::new(); let mut buf = Vec::new();
match f.read_to_end(&mut buf) { match f.read_to_end(&mut buf) {
Ok(n) => { Ok(n) => {
let data = &buf[..n]; let data = &buf[..n];
let xdb = parse_bytes(data); let xdb = parse_bytes(data);
//let mut op = File::create("outdb").unwrap(); info!("XDB: {:?}", xdb);
//info!("Write res: {:?}", op.write(&to_bytes(xdb))); let mut op = File::create("outdb").unwrap();
info!("Write res: {:?}", op.write(&to_bytes(xdb)));
}, },
Err(e) => { Err(e) => {
error!("Error: {}",e); error!("Error: {}",e);

View File

@ -1,3 +1,5 @@
use crate::{JumpTable, LetterJumpEntry, PlaylistIndexEntry};
#[derive(Debug, serde::Serialize)] #[derive(Debug, serde::Serialize)]
pub struct XDatabase { pub struct XDatabase {
@ -31,7 +33,26 @@ pub struct XAlbumItem {
pub struct XPlaylist { pub struct XPlaylist {
pub header: crate::ChunkHeader, pub header: crate::ChunkHeader,
pub data: crate::Playlist, pub data: crate::Playlist,
pub args: Vec<XArgument> pub args: Vec<XPlArgument>
}
#[derive(Debug, serde::Serialize)]
pub enum XPlArgument {
String(XArgument),
IndexEntry(XPlaylistIndexEntry),
LetterJumpEntry(XLetterJump)
}
#[derive(Debug, serde::Serialize)]
pub struct XPlaylistIndexEntry {
pub data: PlaylistIndexEntry,
pub v: Vec<u32>
}
#[derive(Debug, serde::Serialize)]
pub struct XLetterJump {
pub data: LetterJumpEntry,
pub v: Vec<JumpTable>
} }
#[derive(Debug, serde::Serialize)] #[derive(Debug, serde::Serialize)]