-
-
Notifications
You must be signed in to change notification settings - Fork 245
Expand file tree
/
Copy pathvalidation.rs
More file actions
73 lines (56 loc) · 2.31 KB
/
validation.rs
File metadata and controls
73 lines (56 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
use std::path::Path;
use anyhow::Result;
pub fn is_zip_file(bytes: &[u8]) -> bool {
if bytes.len() < 4 {
return false;
}
let magic = &bytes[0..4];
// https://en.wikipedia.org/wiki/List_of_file_signatures
const ZIP_MAGIC: [u8; 4] = [0x50, 0x4B, 0x03, 0x04];
const ZIP_MAGIC_EMPTY: [u8; 4] = [0x50, 0x4B, 0x05, 0x06];
const ZIP_MAGIC_SPANNED: [u8; 4] = [0x50, 0x4B, 0x07, 0x08];
magic == ZIP_MAGIC || magic == ZIP_MAGIC_EMPTY || magic == ZIP_MAGIC_SPANNED
}
pub fn is_apk_file(bytes: &[u8]) -> Result<bool> {
let cursor = std::io::Cursor::new(bytes);
let mut archive = zip::ZipArchive::new(cursor)?;
// APK files must contain AndroidManifest.xml at the root of the zip file
let has_manifest = archive.by_name("AndroidManifest.xml").is_ok();
Ok(has_manifest)
}
pub fn is_aab_file(bytes: &[u8]) -> Result<bool> {
let cursor = std::io::Cursor::new(bytes);
let mut archive = zip::ZipArchive::new(cursor)?;
// AAB files must contain BundleConfig.pb and base/manifest/AndroidManifest.xml
let has_bundle_config = archive.by_name("BundleConfig.pb").is_ok();
let has_base_manifest = archive.by_name("base/manifest/AndroidManifest.xml").is_ok();
Ok(has_bundle_config && has_base_manifest)
}
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
pub fn is_ipa_file(bytes: &[u8]) -> Result<bool> {
let cursor = std::io::Cursor::new(bytes);
let archive = zip::ZipArchive::new(cursor)?;
let is_ipa = archive.file_names().any(|name| {
name.starts_with("Payload/")
&& name.ends_with(".app/Info.plist")
&& name.matches('/').count() == 2
});
Ok(is_ipa)
}
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
pub fn is_xcarchive_directory<P>(path: P) -> bool
where
P: AsRef<Path>,
{
let path = path.as_ref();
// XCArchive should have Info.plist and a Products/ directory
let info_plist = path.join("Info.plist");
let products_dir = path.join("Products");
info_plist.exists() && products_dir.exists() && products_dir.is_dir()
}
/// A path is an Apple app if it points to an xarchive directory
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
pub fn is_apple_app(path: &Path) -> bool {
path.is_dir() && is_xcarchive_directory(path)
}