Skip to content

Commit

Permalink
added DeviceInfo parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Raleigh Littles authored and Raleigh Littles committed Nov 17, 2024
1 parent 7588b32 commit e7409c6
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 9 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The table below shows which iTunesDB files are supported.
| File type | Supported? |
|----------------------|------------------------------------------------------------------|
| Artwork DB | :negative_squared_cross_mark: Not yet supported |
| DeviceInfo | :negative_squared_cross_mark: Not yet supported |
| DeviceInfo | Partial - Can extract iPod name only |
| Equalizer Presets | :negative_squared_cross_mark: Not yet supported |
| On The Go Playlist | :negative_squared_cross_mark: Not yet supported |
| Photo Database | :heavy_check_mark: Can extract all associated metadata of images |
Expand Down Expand Up @@ -63,7 +63,8 @@ It requires two arguments:

(2) the type of iTunesDB file.

Possible options are:
The 7 possible "type" options are:


| Field | Value |
|---------------|------------------------------------------|
Expand All @@ -73,6 +74,7 @@ Possible options are:
| "playcounts" | Playcounts file |
| "pfalbums" | Photo Folder Albums |
| "preferences" | Preferences file |
| "deviceinfo" | DeviceInfo file |


```bash
Expand All @@ -98,4 +100,9 @@ This project is a very early work-in-progress. The next major feature to come is

If you have any iTunesDB files from the unsupported list and are willing to share, please contact me.

Special thanks to @AZProductions for providing an iTunesDB file.
Special thanks to:

* @AZProductions
* @joshkenney

for providing iTunesDB files!
8 changes: 8 additions & 0 deletions parser/src/constants/deviceinfo_constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* File: deviceinfo_constants.rs
*
* See: http://www.ipodlinux.org/ITunesDB/#DeviceInfo_File
*/

pub const DEVICEINFO_FILE_SIZE: usize = 1536; // 0x600
pub const DEVICEINFO_STRING_LENGTH: usize = 510;
28 changes: 23 additions & 5 deletions parser/src/helpers/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
/**
* File: helpers.rs
*
*
* General helper methods. For iTunes-specific helper methods, see itunesdb_helpers.rs
*
*/

use std::fmt::Write;

// TODO: Once Rust adds support for default arguments, add the following arguments:
// * endianness
// * radix
pub fn build_le_u16_from_bytes(bytes: &[u8]) -> u16 {
let mut number: u16 = 0;
const RADIX: u16 = 256;

for (idx, item) in bytes.iter().enumerate() {
let summand: u16 = RADIX
.checked_pow(idx as u32)
.unwrap_or_else(|| panic!("Can't raise {} to power {}", RADIX, idx))
as u16;

number += (summand as u16) * (*item as u16);
}

return number;
}

pub fn build_le_u32_from_bytes(bytes: &[u8]) -> u32 {
let mut number: u32 = 0;
const RADIX: u32 = 256;
Expand Down Expand Up @@ -122,10 +137,13 @@ const MAC_TO_LINUX_EPOCH_CONVERSION: i64 = 2082844800;

/// Converts a given Mac epoch time into an actual UTC timestamp
pub fn get_timestamp_as_mac(mac_timestamp: u64) -> chrono::DateTime<chrono::Utc> {
return chrono::DateTime::<chrono::Utc>::from_timestamp((mac_timestamp as i64) - MAC_TO_LINUX_EPOCH_CONVERSION, 0).unwrap();
return chrono::DateTime::<chrono::Utc>::from_timestamp(
(mac_timestamp as i64) - MAC_TO_LINUX_EPOCH_CONVERSION,
0,
)
.unwrap();
}


/// Converts an integer seconds into a string representing that time in hours, minutes, and seconds
/// only showing the time units appropriately (ie not showing "hours" if the time is less than 1 hour)
/// and with correct pluralization (ie "1 second" vs "2 seconds")
Expand Down Expand Up @@ -209,4 +227,4 @@ pub fn init_csv_writer(filename: &str) -> csv::Writer<std::fs::File> {
.expect(&format!("Can't initialize CSV file '{}'", &filename));

return csv_writer;
}
}
7 changes: 6 additions & 1 deletion parser/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod constants {
pub mod photofolderalbums_constants;
pub mod playcounts_constants;
pub mod preferences_constants;
pub mod deviceinfo_constants;
}

mod helpers {
Expand All @@ -21,6 +22,7 @@ mod parsers {
pub mod photo_type_parser;
pub mod playcounts_parser;
pub mod preferences_parser;
pub mod deviceinfo_parser;
}

mod itunesdb;
Expand Down Expand Up @@ -85,7 +87,10 @@ fn main() {
parsers::photo_type_parser::parse_photofolder_albums_file(itunesdb_file_as_bytes);
} else if itunesdb_file_type == "preferences" {
parsers::preferences_parser::parse_preferences_file(itunesdb_file_as_bytes);
} else {
} else if itunesdb_file_type == "deviceinfo" {
parsers::deviceinfo_parser::parse_device_info_file(itunesdb_file_as_bytes);
}
else {
println!(
"'{}' is not a supported iTunesDB file type!",
itunesdb_file_type
Expand Down
29 changes: 29 additions & 0 deletions parser/src/parsers/deviceinfo_parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

use crate::constants::deviceinfo_constants;
use crate::helpers::helpers;

pub fn parse_device_info_file(deviceinfo_file_as_bytes: Vec<u8>) {

if deviceinfo_file_as_bytes.len() != deviceinfo_constants::DEVICEINFO_FILE_SIZE {
panic!("Invalid DeviceInfo file size! Expected: {} | Got: {}", deviceinfo_constants::DEVICEINFO_FILE_SIZE, deviceinfo_file_as_bytes.len());
}

let ipod_name_length_raw = &deviceinfo_file_as_bytes[0..2];

let ipod_name_length = helpers::build_le_u16_from_bytes(ipod_name_length_raw) as usize;

// The strings are formatted using UTF-16 so this byte value must be a multiple of 2
if ipod_name_length % 2 != 0 {
panic!("Invalid iPod Name Length! Expected multiple of 2 | Got: {}", ipod_name_length);
}

println!("iPod Name Length: {}", ipod_name_length);

// factor of 2 to account for UTF-16 encoding (2 bytes per character),
// and the +2 to account for the length bytes
let ipod_name_raw_bytes = &deviceinfo_file_as_bytes[2 .. (ipod_name_length * 2 + 2)];

println!("iPod Name: {:?}", String::from_utf16(&helpers::return_utf16_from_utf8(ipod_name_raw_bytes)).unwrap());


}
Binary file added sample-files/2005-10-06_DeviceInfo
Binary file not shown.

0 comments on commit e7409c6

Please sign in to comment.