From 4b07a48a08526f2ea3f4605203db14ed04376b15 Mon Sep 17 00:00:00 2001 From: alterwain Date: Sat, 8 Feb 2025 03:40:44 +0300 Subject: [PATCH] modified: outdb modified: src/main.rs modified: src/xobjects.rs --- outdb | Bin 1036 -> 2592 bytes src/main.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++---- src/xobjects.rs | 23 +++++++++++++- 3 files changed, 94 insertions(+), 7 deletions(-) diff --git a/outdb b/outdb index 09f6c51525875a36d0154781d264f0e718c38bb2..12eae6bcf0378c8892d3cfaee27f24b805d028b4 100644 GIT binary patch literal 2592 zcmeHH&r1|>6#uxEF4SSmiwCuVItW56SSFjuf~Fv?ZU+g9kZs3h7G`$0*;N!gEPK<7 zC&828InZNa$NCe5!VZx_m#$sIK5y6W%pm)nO6E}D8y@d{-;dAd&3C@@b*z`>4*>CN zKnHD&dX+l&c6(%f^w8`;KKAW<>SL}kv&pbV7E9en2OmDaFB}TSzb=kdH4_}Nk9vjb zSjF6RTAAIk?3_U>+D?MKXZ1C|w^&OuI2i*v+1yW+8e=${5oajA_qD#UhD5()eMw6Z z>hJtW%agF^>pAx%nEO(C)m%4@e~y1LW_Mb-(^Ide{%~4+nd`i8H28f@Vk8(mC~bMA zBdz&kt*jT;I(2)knfqP6?6*2gvJZ|`HhUQ>P=meVk5iQ-F$@FKD8hwJZx)MK;Yl?x zi83D-&*5MRRaWFNgk{F^$g#GH7aq$L;kpzgt*{IP)){2+h%5#>mtYdBOus;DlTXcR zu|xJyiJ+v_f;PqaEIUmsV1l;9IbB+tnT$7M3R8TiQO2HO2J?7=yL^KRW5M$!r-bLR z;-9b8N|Lb}U!#XsxJ7p#yC<>z2X6+RHg0g~#nsHxBXvr|kE;c(npo<`xK2~=QI*IX z!G0AFvw|hxdyslRPBl_6~^BkA-@hQjQ?hY{5q^K z{@WMiZ+DjOM2MyCcS8QL=>7{GR@lDC?IroY5#2v_iy#-lYWI&{e&hCc-~afHe*w53 Bq}~7k delta 26 icmZ1=(!;@(n~{|Ag@J+L3(H2XRm@BY43oDphXDX`QV2!> diff --git a/src/main.rs b/src/main.rs index 12a8087..b196bf3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use std::{fs::File, io::{Read, Write}}; use env_logger::Builder; use log::{error, info, LevelFilter}; 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; @@ -308,7 +308,7 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase { albums.last_mut().unwrap().args.push(XArgument{ arg_type: entry_type, val: g}); }, 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) => { 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; } 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 => { let entry: LetterJumpEntry = bincode::deserialize(&data[i..i+28]).unwrap(); @@ -336,6 +342,12 @@ pub fn parse_bytes(data: &[u8]) -> XDatabase { h += 12; } 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 => { @@ -431,7 +443,60 @@ fn to_bytes(xdb: XDatabase) -> Vec { let mut pl_bytes = Vec::new(); for u in 0..playlists.len() { let playlist = playlists.get(u).unwrap(); - let mut args = x_args_to_bytes(&playlist.args); + + let mut args: Vec = 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 = 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 = 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 bincode::serialize(&playlist.data).unwrap()); pl_bytes.append(&mut args); @@ -492,14 +557,15 @@ fn main() { .filter(None, LevelFilter::Info) .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(); match f.read_to_end(&mut buf) { Ok(n) => { let data = &buf[..n]; let xdb = parse_bytes(data); - //let mut op = File::create("outdb").unwrap(); - //info!("Write res: {:?}", op.write(&to_bytes(xdb))); + info!("XDB: {:?}", xdb); + let mut op = File::create("outdb").unwrap(); + info!("Write res: {:?}", op.write(&to_bytes(xdb))); }, Err(e) => { error!("Error: {}",e); diff --git a/src/xobjects.rs b/src/xobjects.rs index 6a17bb1..1515ee3 100644 --- a/src/xobjects.rs +++ b/src/xobjects.rs @@ -1,3 +1,5 @@ +use crate::{JumpTable, LetterJumpEntry, PlaylistIndexEntry}; + #[derive(Debug, serde::Serialize)] pub struct XDatabase { @@ -31,7 +33,26 @@ pub struct XAlbumItem { pub struct XPlaylist { pub header: crate::ChunkHeader, pub data: crate::Playlist, - pub args: Vec + pub args: Vec +} + +#[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 +} + +#[derive(Debug, serde::Serialize)] +pub struct XLetterJump { + pub data: LetterJumpEntry, + pub v: Vec } #[derive(Debug, serde::Serialize)]