mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
newreg: simplify getting file/dir and context
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@ use crate::AppContext;
|
|||||||
pub struct Format {
|
pub struct Format {
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
pub detector_func: fn(&AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>>,
|
pub detector_func: fn(&AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>>,
|
||||||
pub extractor_func: fn(&AppContext, Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>>,
|
pub extractor_func: fn(&AppContext, Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod mstar;
|
pub mod mstar;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "amlogic", detector_func: is_amlogic_file, extractor_func: extract_amlogic }
|
Format { name: "amlogic", detector_func: is_amlogic_file, extractor_func: extract_amlogic }
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ impl ItemEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_amlogic_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_amlogic_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 8, 4)?;
|
let header = common::read_file(&file, 8, 4)?;
|
||||||
if header == b"\x56\x19\xB5\x27" {
|
if header == b"\x56\x19\xB5\x27" {
|
||||||
@@ -60,8 +60,8 @@ pub fn is_amlogic_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_amlogic(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_amlogic(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
file.seek(SeekFrom::Start(0))?;
|
file.seek(SeekFrom::Start(0))?;
|
||||||
let header: ImageHeader = file.read_le()?;
|
let header: ImageHeader = file.read_le()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "android_ota_payload", detector_func: is_android_ota_payload_file, extractor_func: extract_android_ota_payload }
|
Format { name: "android_ota_payload", detector_func: is_android_ota_payload_file, extractor_func: extract_android_ota_payload }
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ struct Header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_android_ota_payload_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_android_ota_payload_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 4)?;
|
let header = common::read_file(&file, 0, 4)?;
|
||||||
if header == b"CrAU" {
|
if header == b"CrAU" {
|
||||||
@@ -33,8 +33,8 @@ pub fn is_android_ota_payload_file(app_ctx: &AppContext) -> Result<Option<Box<dy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_android_ota_payload(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_android_ota_payload(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: Header = file.read_be()?;
|
let header: Header = file.read_be()?;
|
||||||
println!("File info:\nFormat version: {}\nManifest size: {}", header.file_format_version, header.manifest_size);
|
println!("File info:\nFormat version: {}\nManifest size: {}", header.file_format_version, header.manifest_size);
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "bdl", detector_func: is_bdl_file, extractor_func: extract_bdl }
|
Format { name: "bdl", detector_func: is_bdl_file, extractor_func: extract_bdl }
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ impl PkgEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_bdl_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_bdl_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 4)?;
|
let header = common::read_file(&file, 0, 4)?;
|
||||||
if header == b"ibdl" {
|
if header == b"ibdl" {
|
||||||
@@ -96,8 +96,8 @@ pub fn is_bdl_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_bdl(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_bdl(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: BdlHeader = file.read_le()?;
|
let header: BdlHeader = file.read_le()?;
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "epk", detector_func: is_epk_file, extractor_func: extract_epk }
|
Format { name: "epk", detector_func: is_epk_file, extractor_func: extract_epk }
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@ pub struct EpkContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_epk_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_epk_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let versions = common::read_file(&file, 1712, 36)?;
|
let versions = common::read_file(&file, 1712, 36)?;
|
||||||
if let Some(epk_version) = check_epk_version(&versions) {
|
if let Some(epk_version) = check_epk_version(&versions) {
|
||||||
@@ -51,9 +51,9 @@ fn match_with_pattern(data: &[u8], pattern: &str) -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_epk(app_ctx: &AppContext, ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_epk(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
let ctx = ctx.and_then(|c| c.downcast::<EpkContext>().ok()).ok_or("Context is invalid or missing!")?;
|
let ctx = ctx.downcast::<EpkContext>().expect("Missing context");
|
||||||
|
|
||||||
let versions = common::read_file(&file, 1712, 36)?;
|
let versions = common::read_file(&file, 1712, 36)?;
|
||||||
|
|
||||||
@@ -63,10 +63,10 @@ pub fn extract_epk(app_ctx: &AppContext, ctx: Option<Box<dyn Any>>) -> Result<()
|
|||||||
|
|
||||||
if ctx.epk_version == 2 {
|
if ctx.epk_version == 2 {
|
||||||
println!("EPK2 detected!\n");
|
println!("EPK2 detected!\n");
|
||||||
formats::epk2::extract_epk2(app_ctx, None)?;
|
formats::epk2::extract_epk2(app_ctx, Box::new(()))?;
|
||||||
} else if ctx.epk_version == 3 {
|
} else if ctx.epk_version == 3 {
|
||||||
println!("EPK3 detected!\n");
|
println!("EPK3 detected!\n");
|
||||||
formats::epk3::extract_epk3(app_ctx, None)?;
|
formats::epk3::extract_epk3(app_ctx, Box::new(()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "epk1", detector_func: is_epk1_file, extractor_func: extract_epk1 }
|
Format { name: "epk1", detector_func: is_epk1_file, extractor_func: extract_epk1 }
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ struct Pak {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_epk1_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_epk1_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let epk2_magic = common::read_file(&file, 12, 4)?; //for epk2b
|
let epk2_magic = common::read_file(&file, 12, 4)?; //for epk2b
|
||||||
let epak_magic = common::read_file(&file, 0, 4)?;
|
let epak_magic = common::read_file(&file, 0, 4)?;
|
||||||
@@ -52,8 +52,8 @@ pub fn is_epk1_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_epk1(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_epk1(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
//check type of epk1
|
//check type of epk1
|
||||||
let epk1_type;
|
let epk1_type;
|
||||||
let init_pak_count_bytes = common::read_file(&file, 8, 4)?;
|
let init_pak_count_bytes = common::read_file(&file, 8, 4)?;
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "epk2", detector_func: is_epk2_file, extractor_func: extract_epk2 }
|
Format { name: "epk2", detector_func: is_epk2_file, extractor_func: extract_epk2 }
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ struct Pak {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_epk2_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_epk2_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 128, 4)?;
|
let header = common::read_file(&file, 128, 4)?;
|
||||||
if header == b"epak" {
|
if header == b"epak" {
|
||||||
@@ -82,8 +82,8 @@ pub fn is_epk2_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_epk2(app_ctx: &AppContext, _: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_epk2(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let _header_signature = common::read_exact(&mut file, SIGNATURE_SIZE as usize)?;
|
let _header_signature = common::read_exact(&mut file, SIGNATURE_SIZE as usize)?;
|
||||||
let stored_header = common::read_exact(&mut file, 1584)?; //max header size
|
let stored_header = common::read_exact(&mut file, 1584)?; //max header size
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "epk2b", detector_func: is_epk2b_file, extractor_func: extract_epk2b }
|
Format { name: "epk2b", detector_func: is_epk2b_file, extractor_func: extract_epk2b }
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ struct Pak {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_epk2b_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_epk2b_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let epk2_magic = common::read_file(&file, 12, 4)?;
|
let epk2_magic = common::read_file(&file, 12, 4)?;
|
||||||
let epak_magic = common::read_file(&file, 0, 4)?;
|
let epak_magic = common::read_file(&file, 0, 4)?;
|
||||||
@@ -68,8 +68,8 @@ pub fn is_epk2b_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_epk2b(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_epk2b(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: EpkHeader = file.read_le()?;
|
let header: EpkHeader = file.read_le()?;
|
||||||
println!("EPK info -\nData size: {}\nPak count: {}\nOTA ID: {}\nVersion: {:02x?}.{:02x?}.{:02x?}",
|
println!("EPK info -\nData size: {}\nPak count: {}\nOTA ID: {}\nVersion: {:02x?}.{:02x?}.{:02x?}",
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "epk3", detector_func: is_epk3_file, extractor_func: extract_epk3 }
|
Format { name: "epk3", detector_func: is_epk3_file, extractor_func: extract_epk3 }
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,8 @@ pub fn is_epk3_file(_app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<d
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_epk3(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_epk3(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
file.seek(SeekFrom::Start(0))?;
|
file.seek(SeekFrom::Start(0))?;
|
||||||
let stored_header = common::read_exact(&mut file, 1712)?;
|
let stored_header = common::read_exact(&mut file, 1712)?;
|
||||||
let header: Vec<u8>;
|
let header: Vec<u8>;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "funai_upg", detector_func: is_funai_upg_file, extractor_func: extract_funai_upg }
|
Format { name: "funai_upg", detector_func: is_funai_upg_file, extractor_func: extract_funai_upg }
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ struct Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_funai_upg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_funai_upg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
let header = common::read_file(&file, 0, 6)?;
|
let header = common::read_file(&file, 0, 6)?;
|
||||||
if header == b"UPG\x00\x00\x00" {
|
if header == b"UPG\x00\x00\x00" {
|
||||||
Ok(Some(Box::new(())))
|
Ok(Some(Box::new(())))
|
||||||
@@ -35,8 +35,8 @@ pub fn is_funai_upg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_funai_upg(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_funai_upg(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: Header = file.read_le()?;
|
let header: Header = file.read_le()?;
|
||||||
println!("File info:\nFile size: {}\nEntry count: {}", header.file_size, header.entry_count);
|
println!("File info:\nFile size: {}\nEntry count: {}", header.file_size, header.entry_count);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "invincible_image", detector_func: is_invincible_image_file, extractor_func: extract_invincible_image }
|
Format { name: "invincible_image", detector_func: is_invincible_image_file, extractor_func: extract_invincible_image }
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ impl Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_invincible_image_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_invincible_image_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 16)?;
|
let header = common::read_file(&file, 0, 16)?;
|
||||||
if header == b"INVINCIBLE_IMAGE" {
|
if header == b"INVINCIBLE_IMAGE" {
|
||||||
@@ -73,8 +73,8 @@ pub fn is_invincible_image_file(app_ctx: &AppContext) -> Result<Option<Box<dyn A
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_invincible_image(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_invincible_image(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: Header = file.read_le()?;
|
let header: Header = file.read_le()?;
|
||||||
println!("File info:\nFile Version: {}.{}\nVersion(1): {}\nVersion(2): {}\nVersion(3): {}\nVersion(4): {}\nData size: {}\nData start offset: {}\nKeep data size: {}\nSkip data size: {}\n\nPayload Count: {}",
|
println!("File info:\nFile Version: {}.{}\nVersion(1): {}\nVersion(2): {}\nVersion(3): {}\nVersion(4): {}\nData size: {}\nData start offset: {}\nKeep data size: {}\nSkip data size: {}\n\nPayload Count: {}",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "msd10", detector_func: is_msd10_file, extractor_func: extract_msd10 }
|
Format { name: "msd10", detector_func: is_msd10_file, extractor_func: extract_msd10 }
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ struct Section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_msd10_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_msd10_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 6)?;
|
let header = common::read_file(&file, 0, 6)?;
|
||||||
if header == b"MSDU10" {
|
if header == b"MSDU10" {
|
||||||
@@ -58,8 +58,8 @@ pub fn is_msd10_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_msd10(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_msd10(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: FileHeader = file.read_le()?;
|
let header: FileHeader = file.read_le()?;
|
||||||
println!("\nNumber of sections: {}", header.section_count);
|
println!("\nNumber of sections: {}", header.section_count);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "msd11", detector_func: is_msd11_file, extractor_func: extract_msd11 }
|
Format { name: "msd11", detector_func: is_msd11_file, extractor_func: extract_msd11 }
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ struct Section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_msd11_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_msd11_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 6)?;
|
let header = common::read_file(&file, 0, 6)?;
|
||||||
if header == b"MSDU11" {
|
if header == b"MSDU11" {
|
||||||
@@ -59,8 +59,8 @@ pub fn is_msd11_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_msd11(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_msd11(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: FileHeader = file.read_le()?;
|
let header: FileHeader = file.read_le()?;
|
||||||
println!("\nNumber of sections: {}", header.section_count);
|
println!("\nNumber of sections: {}", header.section_count);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "mstar", detector_func: is_mstar_file, extractor_func: extract_mstar }
|
Format { name: "mstar", detector_func: is_mstar_file, extractor_func: extract_mstar }
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ use crate::utils::lzop::{unlzop_to_file};
|
|||||||
use crate::utils::sparse::{unsparse_to_file};
|
use crate::utils::sparse::{unsparse_to_file};
|
||||||
|
|
||||||
pub fn is_mstar_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_mstar_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 32768)?;
|
let header = common::read_file(&file, 0, 32768)?;
|
||||||
let header_string = String::from_utf8_lossy(&header);
|
let header_string = String::from_utf8_lossy(&header);
|
||||||
@@ -33,8 +33,8 @@ fn parse_number(s: &str) -> Option<u64> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_mstar(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_mstar(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let mut script = common::read_file(&file, 0, 32768)?;
|
let mut script = common::read_file(&file, 0, 32768)?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "mtk_bdp", detector_func: is_mtk_bdp_file, extractor_func: extract_mtk_bdp }
|
Format { name: "mtk_bdp", detector_func: is_mtk_bdp_file, extractor_func: extract_mtk_bdp }
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ fn find_bytes(data: &[u8], pattern: &[u8]) -> Option<usize> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_mtk_bdp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_mtk_bdp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let mut file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
let file_size = file.metadata()?.len();
|
let file_size = file.metadata()?.len();
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
|
|
||||||
@@ -95,9 +95,9 @@ pub fn is_mtk_bdp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_mtk_bdp(app_ctx: &AppContext, ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_mtk_bdp(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
let ctx = ctx.and_then(|c: Box<dyn Any>| c.downcast::<MtkBdpContext>().ok()).ok_or("Context is invalid or missing!")?;
|
let ctx = ctx.downcast::<MtkBdpContext>().expect("Missing context");
|
||||||
|
|
||||||
let offset = ctx.pitit_offset;
|
let offset = ctx.pitit_offset;
|
||||||
println!("\nReading PITIT at: {}", offset);
|
println!("\nReading PITIT at: {}", offset);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "mtk_pkg", detector_func: is_mtk_pkg_file, extractor_func: extract_mtk_pkg }
|
Format { name: "mtk_pkg", detector_func: is_mtk_pkg_file, extractor_func: extract_mtk_pkg }
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ static HEADER_KEY: [u8; 16] = [
|
|||||||
static HEADER_IV: [u8; 16] = [0x00; 16];
|
static HEADER_IV: [u8; 16] = [0x00; 16];
|
||||||
|
|
||||||
pub fn is_mtk_pkg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_mtk_pkg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let mut encrypted_header = common::read_file(&file, 0, HEADER_SIZE)?;
|
let mut encrypted_header = common::read_file(&file, 0, HEADER_SIZE)?;
|
||||||
let mut header = decrypt_aes128_cbc_nopad(&encrypted_header, &HEADER_KEY, &HEADER_IV)?;
|
let mut header = decrypt_aes128_cbc_nopad(&encrypted_header, &HEADER_KEY, &HEADER_IV)?;
|
||||||
@@ -101,9 +101,9 @@ pub fn is_mtk_pkg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_mtk_pkg(app_ctx: &AppContext, ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_mtk_pkg(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
let ctx = ctx.and_then(|c: Box<dyn Any>| c.downcast::<MtkPkgContext>().ok()).ok_or("Context is invalid or missing!")?;
|
let ctx = ctx.downcast::<MtkPkgContext>().expect("Missing context");
|
||||||
|
|
||||||
let file_size = file.metadata()?.len();
|
let file_size = file.metadata()?.len();
|
||||||
let header = ctx.decrypted_header;
|
let header = ctx.decrypted_header;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "mtk_pkg_new", detector_func: is_mtk_pkg_new_file, extractor_func: extract_mtk_pkg_new }
|
Format { name: "mtk_pkg_new", detector_func: is_mtk_pkg_new_file, extractor_func: extract_mtk_pkg_new }
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ impl PartEntry {
|
|||||||
static HEADER_SIZE: usize = 0x170;
|
static HEADER_SIZE: usize = 0x170;
|
||||||
|
|
||||||
pub fn is_mtk_pkg_new_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_mtk_pkg_new_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let encrypted_header = common::read_file(&file, 0, HEADER_SIZE)?;
|
let encrypted_header = common::read_file(&file, 0, HEADER_SIZE)?;
|
||||||
for (key_hex, iv_hex, name) in keys::MTK_PKG_CUST {
|
for (key_hex, iv_hex, name) in keys::MTK_PKG_CUST {
|
||||||
@@ -92,9 +92,9 @@ pub fn is_mtk_pkg_new_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>,
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_mtk_pkg_new(app_ctx: &AppContext, ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_mtk_pkg_new(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
let ctx = ctx.and_then(|c: Box<dyn Any>| c.downcast::<MtkPkgNewContext>().ok()).ok_or("Context is invalid or missing!")?;
|
let ctx = ctx.downcast::<MtkPkgNewContext>().expect("Missing context");
|
||||||
|
|
||||||
let file_size = file.metadata()?.len();
|
let file_size = file.metadata()?.len();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "mtk_pkg_old", detector_func: is_mtk_pkg_old_file, extractor_func: extract_mtk_pkg_old }
|
Format { name: "mtk_pkg_old", detector_func: is_mtk_pkg_old_file, extractor_func: extract_mtk_pkg_old }
|
||||||
}
|
}
|
||||||
@@ -64,8 +64,8 @@ impl PartEntry {
|
|||||||
static HEADER_SIZE: usize = 0x98;
|
static HEADER_SIZE: usize = 0x98;
|
||||||
|
|
||||||
pub fn is_mtk_pkg_old_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_mtk_pkg_old_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let mut file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let encrypted_header = common::read_file(&file, 0, HEADER_SIZE)?;
|
let encrypted_header = common::read_file(&file, 0, HEADER_SIZE)?;
|
||||||
let header = decrypt(&encrypted_header, KEY, Some(HEADER_XOR_MASK));
|
let header = decrypt(&encrypted_header, KEY, Some(HEADER_XOR_MASK));
|
||||||
if &header[4..12] == MTK_HEADER_MAGIC {
|
if &header[4..12] == MTK_HEADER_MAGIC {
|
||||||
@@ -83,8 +83,8 @@ pub fn is_mtk_pkg_old_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_mtk_pkg_old(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_mtk_pkg_old(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let file_size = file.metadata()?.len();
|
let file_size = file.metadata()?.len();
|
||||||
let encrypted_header = common::read_exact(&mut file, HEADER_SIZE)?;
|
let encrypted_header = common::read_exact(&mut file, HEADER_SIZE)?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "novatek", detector_func: is_novatek_file, extractor_func: extract_novatek }
|
Format { name: "novatek", detector_func: is_novatek_file, extractor_func: extract_novatek }
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ struct PartEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_novatek_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_novatek_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 4)?;
|
let header = common::read_file(&file, 0, 4)?;
|
||||||
if header == b"NFWB" {
|
if header == b"NFWB" {
|
||||||
@@ -51,8 +51,8 @@ pub fn is_novatek_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_novatek(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_novatek(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: Header = file.read_le()?;
|
let header: Header = file.read_le()?;
|
||||||
println!("File info:\nFirmware name: {}\nVersion: {}.{}\nData size: {}\nPart count: {}",
|
println!("File info:\nFirmware name: {}\nVersion: {}.{}\nData size: {}\nPart count: {}",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "nvt_timg", detector_func: is_nvt_timg_file, extractor_func: extract_nvt_timg }
|
Format { name: "nvt_timg", detector_func: is_nvt_timg_file, extractor_func: extract_nvt_timg }
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ impl PIMG {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_nvt_timg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_nvt_timg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 4)?;
|
let header = common::read_file(&file, 0, 4)?;
|
||||||
if header == b"TIMG" {
|
if header == b"TIMG" {
|
||||||
@@ -60,8 +60,8 @@ pub fn is_nvt_timg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_nvt_timg(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_nvt_timg(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let file_size = file.metadata()?.len();
|
let file_size = file.metadata()?.len();
|
||||||
let timg: TIMG = file.read_le()?;
|
let timg: TIMG = file.read_le()?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "pana_dvd", detector_func: is_pana_dvd_file, extractor_func: extract_pana_dvd }
|
Format { name: "pana_dvd", detector_func: is_pana_dvd_file, extractor_func: extract_pana_dvd }
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ pub fn find_aes_key_pair<'a>(key_array: &'a [(&'a str, &'a str, &'a str)], data:
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_pana_dvd_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_pana_dvd_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
let header = common::read_file(&file, 0, 64)?;
|
let header = common::read_file(&file, 0, 64)?;
|
||||||
if let Some(matching_key) = find_key(&keys::PANA_DVD_KEYONLY, &header, b"PROG", 0)? {
|
if let Some(matching_key) = find_key(&keys::PANA_DVD_KEYONLY, &header, b"PROG", 0)? {
|
||||||
Ok(Some(Box::new(PanaDvdContext {
|
Ok(Some(Box::new(PanaDvdContext {
|
||||||
@@ -181,9 +181,9 @@ pub fn is_pana_dvd_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_pana_dvd(app_ctx: &AppContext, ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_pana_dvd(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
let context = ctx.and_then(|c: Box<dyn Any>| c.downcast::<PanaDvdContext>().ok()).ok_or("Context is invalid or missing!")?;
|
let context = ctx.downcast::<PanaDvdContext>().expect("Missing context");
|
||||||
|
|
||||||
let mut data = Vec::new(); // we need to load the entire file into memory so we can swap it with AES decrypted data if its AES encrypted
|
let mut data = Vec::new(); // we need to load the entire file into memory so we can swap it with AES decrypted data if its AES encrypted
|
||||||
file.read_to_end(&mut data)?;
|
file.read_to_end(&mut data)?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "pfl_upg", detector_func: is_pfl_upg_file, extractor_func: extract_pfl_upg }
|
Format { name: "pfl_upg", detector_func: is_pfl_upg_file, extractor_func: extract_pfl_upg }
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ impl FileHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_pfl_upg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_pfl_upg_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 8)?;
|
let header = common::read_file(&file, 0, 8)?;
|
||||||
if header == b"2SWU3TXV" {
|
if header == b"2SWU3TXV" {
|
||||||
@@ -91,8 +91,8 @@ fn decrypt_aes256_ecb(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Box<dyn
|
|||||||
Ok(buffer)
|
Ok(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_pfl_upg(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_pfl_upg(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: Header = file.read_le()?;
|
let header: Header = file.read_le()?;
|
||||||
let signature = common::read_exact(&mut file, 128)?;
|
let signature = common::read_exact(&mut file, 128)?;
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "pup", detector_func: is_pup_file, extractor_func: extract_pup }
|
Format { name: "pup", detector_func: is_pup_file, extractor_func: extract_pup }
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ struct BlockEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_pup_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_pup_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 4)?;
|
let header = common::read_file(&file, 0, 4)?;
|
||||||
if header == b"\x4F\x15\x3D\x1D" || header == b"\x54\x14\xF5\xEE" { //ps4, ps5
|
if header == b"\x4F\x15\x3D\x1D" || header == b"\x54\x14\xF5\xEE" { //ps4, ps5
|
||||||
@@ -67,8 +67,8 @@ pub fn is_pup_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_pup(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_pup(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: Header = file.read_le()?;
|
let header: Header = file.read_le()?;
|
||||||
println!("File info:\nFile size: {}\nEntry count: {}",
|
println!("File info:\nFile size: {}\nEntry count: {}",
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "roku", detector_func: is_roku_file, extractor_func: extract_roku }
|
Format { name: "roku", detector_func: is_roku_file, extractor_func: extract_roku }
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ impl ImageHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_roku_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_roku_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 32)?;
|
let header = common::read_file(&file, 0, 32)?;
|
||||||
let try_decrypt_header = decrypt_aes128_cbc_nopad(&header, &FILE_KEY, &FILE_IV)?;
|
let try_decrypt_header = decrypt_aes128_cbc_nopad(&header, &FILE_KEY, &FILE_IV)?;
|
||||||
@@ -74,8 +74,8 @@ pub fn is_roku_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_roku(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_roku(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let mut encrypted_data = Vec::new();
|
let mut encrypted_data = Vec::new();
|
||||||
file.read_to_end(&mut encrypted_data)?;
|
file.read_to_end(&mut encrypted_data)?;
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "ruf", detector_func: is_ruf_file, extractor_func: extract_ruf }
|
Format { name: "ruf", detector_func: is_ruf_file, extractor_func: extract_ruf }
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ impl RufEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ruf_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_ruf_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 6)?;
|
let header = common::read_file(&file, 0, 6)?;
|
||||||
if header == b"RUF\x00\x00\x00" {
|
if header == b"RUF\x00\x00\x00" {
|
||||||
@@ -86,8 +86,8 @@ pub fn is_ruf_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_ruf(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_ruf(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: RufHeader = file.read_be()?;
|
let header: RufHeader = file.read_be()?;
|
||||||
if header.is_dual_ruf() {
|
if header.is_dual_ruf() {
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "rvp", detector_func: is_rvp_file, extractor_func: extract_rvp }
|
Format { name: "rvp", detector_func: is_rvp_file, extractor_func: extract_rvp }
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ fn decrypt_xor(data: &[u8]) -> Vec<u8> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_rvp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_rvp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let mut file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
//MVP
|
//MVP
|
||||||
let header = common::read_file(&file, 0, 4)?;
|
let header = common::read_file(&file, 0, 4)?;
|
||||||
if header == b"UPDT" {
|
if header == b"UPDT" {
|
||||||
@@ -39,8 +39,8 @@ pub fn is_rvp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn
|
|||||||
Ok(Some(Box::new(())))
|
Ok(Some(Box::new(())))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_rvp(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_rvp(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let mut obf_data = Vec::new(); //we sadly cannot deXOR on the fly because of its 32 byte pattern
|
let mut obf_data = Vec::new(); //we sadly cannot deXOR on the fly because of its 32 byte pattern
|
||||||
file.read_to_end(&mut obf_data)?;
|
file.read_to_end(&mut obf_data)?;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "samsung_old", detector_func: is_samsung_old_dir, extractor_func: extract_samsung_old }
|
Format { name: "samsung_old", detector_func: is_samsung_old_dir, extractor_func: extract_samsung_old }
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ use crate::utils::aes::{decrypt_aes128_cbc_pcks7};
|
|||||||
use md5;
|
use md5;
|
||||||
|
|
||||||
pub fn is_samsung_old_dir(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_samsung_old_dir(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let dir = match &app_ctx.input {InputTarget::Directory(p) => p, InputTarget::File(_) => return Ok(None)};
|
let dir = match app_ctx.dir() {Some(d) => d, None => return Ok(None)};
|
||||||
|
|
||||||
if Path::new(&dir).join("image").is_dir() & Path::new(&dir).join("image/info.txt").exists(){
|
if Path::new(&dir).join("image").is_dir() & Path::new(&dir).join("image/info.txt").exists(){
|
||||||
Ok(Some(Box::new(())))
|
Ok(Some(Box::new(())))
|
||||||
@@ -35,8 +35,8 @@ fn decrypt_xor(data: &[u8], key: &str) -> Vec<u8> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_samsung_old(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_samsung_old(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let path = match &app_ctx.input {InputTarget::Directory(p) => p, InputTarget::File(_) => return Err("Extractor expected directory, not file".into())};
|
let path = app_ctx.dir().ok_or("Extractor expected directory")?;
|
||||||
|
|
||||||
let fw_info = fs::read_to_string(Path::new(&path).join("image/info.txt"))?;
|
let fw_info = fs::read_to_string(Path::new(&path).join("image/info.txt"))?;
|
||||||
println!("Firmware info: {}", fw_info);
|
println!("Firmware info: {}", fw_info);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//sddl_dec 5.0
|
//sddl_dec 5.0
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "sddl_sec", detector_func: is_sddl_sec_file, extractor_func: extract_sddl_sec }
|
Format { name: "sddl_sec", detector_func: is_sddl_sec_file, extractor_func: extract_sddl_sec }
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ static DEC_IV: [u8; 16] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
pub fn is_sddl_sec_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_sddl_sec_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 32)?;
|
let header = common::read_file(&file, 0, 32)?;
|
||||||
let deciph_header = decipher(&header);
|
let deciph_header = decipher(&header);
|
||||||
@@ -157,8 +157,8 @@ fn decipher(s: &[u8]) -> Vec<u8> {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_sddl_sec(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_sddl_sec(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let mut hdr_reader = Cursor::new(decipher(&common::read_exact(&mut file, 32)?));
|
let mut hdr_reader = Cursor::new(decipher(&common::read_exact(&mut file, 32)?));
|
||||||
let hdr: SddlSecHeader = hdr_reader.read_be()?;
|
let hdr: SddlSecHeader = hdr_reader.read_be()?;
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use crate::{InputTarget, AppContext, formats::Format};
|
use crate::{AppContext, formats::Format};
|
||||||
pub fn format() -> Format {
|
pub fn format() -> Format {
|
||||||
Format { name: "slp", detector_func: is_slp_file, extractor_func: extract_slp }
|
Format { name: "slp", detector_func: is_slp_file, extractor_func: extract_slp }
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ struct EntryNew {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_slp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_slp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 4)?;
|
let header = common::read_file(&file, 0, 4)?;
|
||||||
if header == b"SLP\x00" {
|
if header == b"SLP\x00" {
|
||||||
@@ -63,8 +63,8 @@ pub fn is_slp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_slp(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_slp(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let header: Header = file.read_le()?;
|
let header: Header = file.read_le()?;
|
||||||
println!("File info:\nModel: {}\nVersion: {}\nFirmware: {}\nNew type: {}\n",
|
println!("File info:\nModel: {}\nVersion: {}\nFirmware: {}\nNew type: {}\n",
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ struct Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_sony_bdp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_sony_bdp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let header = common::read_file(&file, 0, 4)?;
|
let header = common::read_file(&file, 0, 4)?;
|
||||||
if header == b"\x01\x73\xEC\xC9" || header == b"\x01\x73\xEC\x1F" || header == b"\xEC\x7D\xB0\xB0" { //MSB1x, MSB0x, BDPPxx
|
if header == b"\x01\x73\xEC\xC9" || header == b"\x01\x73\xEC\x1F" || header == b"\xEC\x7D\xB0\xB0" { //MSB1x, MSB0x, BDPPxx
|
||||||
@@ -74,8 +74,8 @@ pub fn is_sony_bdp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_sony_bdp(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_sony_bdp(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = match &app_ctx.input {InputTarget::File(f) => f, InputTarget::Directory(_) => return Err("Extractor expected file, not directory".into())};
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
|
||||||
let obf_header = common::read_exact(&mut file, 300)?;
|
let obf_header = common::read_exact(&mut file, 300)?;
|
||||||
let header = hex_substitute(&obf_header);
|
let header = hex_substitute(&obf_header);
|
||||||
@@ -128,7 +128,7 @@ pub fn extract_sony_bdp(app_ctx: &AppContext, _ctx: Option<Box<dyn Any>>) -> Res
|
|||||||
if let Some(result) = formats::mtk_bdp::is_mtk_bdp_file(&ctx)? {
|
if let Some(result) = formats::mtk_bdp::is_mtk_bdp_file(&ctx)? {
|
||||||
println!("- MTK BDP file detected!\n");
|
println!("- MTK BDP file detected!\n");
|
||||||
|
|
||||||
formats::mtk_bdp::extract_mtk_bdp(&ctx, Some(result))?;
|
formats::mtk_bdp::extract_mtk_bdp(&ctx, result)?;
|
||||||
} else {
|
} else {
|
||||||
println!("- Not an MTK BDP file.");
|
println!("- Not an MTK BDP file.");
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-3
@@ -23,6 +23,21 @@ pub struct AppContext {
|
|||||||
pub input: InputTarget,
|
pub input: InputTarget,
|
||||||
pub output_dir: PathBuf,
|
pub output_dir: PathBuf,
|
||||||
}
|
}
|
||||||
|
impl AppContext {
|
||||||
|
pub fn file(&self) -> Option<&File> {
|
||||||
|
match &self.input {
|
||||||
|
InputTarget::File(f) => Some(f),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dir(&self) -> Option<&PathBuf> {
|
||||||
|
match &self.input {
|
||||||
|
InputTarget::Directory(p) => Some(p),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!("unixtract Firmware extractor");
|
println!("unixtract Firmware extractor");
|
||||||
@@ -69,12 +84,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let formats: Vec<Format> = get_registry();
|
let formats: Vec<Format> = get_registry();
|
||||||
println!("Loaded {} formats!\n", formats.len());
|
println!("Loaded {} formats!", formats.len());
|
||||||
|
|
||||||
for format in formats {
|
for format in formats {
|
||||||
if let Some(ctx) = (format.detector_func)(&app_ctx)? {
|
if let Some(ctx) = (format.detector_func)(&app_ctx)? {
|
||||||
println!("{} detected!", format.name);
|
println!("\n{} detected!", format.name);
|
||||||
(format.extractor_func)(&app_ctx, Some(ctx))?;
|
(format.extractor_func)(&app_ctx, ctx)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user