Skip to main content

verifyos_cli/parsers/
zip_extractor.rs

1use std::fs;
2use std::io;
3use std::path::{Path, PathBuf};
4use tempfile::TempDir;
5use zip::ZipArchive;
6
7#[derive(Debug, thiserror::Error)]
8pub enum ExtractionError {
9    #[error("IO Error: {0}")]
10    Io(#[from] io::Error),
11    #[error("Zip Error: {0}")]
12    Zip(#[from] zip::result::ZipError),
13    #[error("Invalid IPA path: {0}")]
14    InvalidPath(PathBuf),
15}
16
17pub struct ExtractedIpa {
18    pub temp_dir: TempDir,
19    pub payload_dir: PathBuf,
20}
21
22impl ExtractedIpa {
23    pub fn get_app_bundle_path(&self) -> io::Result<Option<PathBuf>> {
24        if !self.payload_dir.exists() {
25            return Ok(None);
26        }
27
28        for entry in fs::read_dir(&self.payload_dir)? {
29            let entry = entry?;
30            let path = entry.path();
31            if path.extension().and_then(|e| e.to_str()) == Some("app") {
32                return Ok(Some(path));
33            }
34        }
35        Ok(None)
36    }
37}
38
39pub fn extract_ipa<P: AsRef<Path>>(ipa_path: P) -> Result<ExtractedIpa, ExtractionError> {
40    let path = ipa_path.as_ref();
41    if !path.exists() {
42        return Err(ExtractionError::InvalidPath(path.to_path_buf()));
43    }
44    let file = fs::File::open(path)?;
45    let mut archive = ZipArchive::new(file)?;
46    let temp_dir = tempfile::tempdir()?;
47    let extract_path = temp_dir.path();
48
49    archive.extract(extract_path)?;
50
51    let payload_dir = extract_path.join("Payload");
52
53    Ok(ExtractedIpa {
54        temp_dir,
55        payload_dir,
56    })
57}