1use std::fs::File;
8use std::io::Read;
9use std::path::Path;
10
11pub fn is_zip(path: &Path) -> bool {
18 check_magic_bytes(path, &[0x50, 0x4B, 0x03, 0x04])
19}
20
21pub fn is_squashfs(path: &Path) -> bool {
29 check_magic_bytes(path, &[0x68, 0x73, 0x71, 0x73])
32 || check_magic_bytes(path, &[0x73, 0x71, 0x73, 0x68])
33}
34
35pub fn is_nsis_installer(path: &Path) -> bool {
43 const SEARCH_SIZE: usize = 8192; const NSIS_SIGNATURE: &[u8] = b"Nullsoft.NSIS.exehead";
45
46 let mut file = match File::open(path) {
47 Ok(f) => f,
48 Err(_) => return false,
49 };
50
51 let mut buffer = vec![0u8; SEARCH_SIZE];
52 let bytes_read = match file.read(&mut buffer) {
53 Ok(n) => n,
54 Err(_) => return false,
55 };
56
57 buffer.truncate(bytes_read);
58
59 buffer
61 .windows(NSIS_SIGNATURE.len())
62 .any(|window| window == NSIS_SIGNATURE)
63}
64
65fn check_magic_bytes(path: &Path, magic: &[u8]) -> bool {
69 let mut file = match File::open(path) {
70 Ok(f) => f,
71 Err(_) => return false,
72 };
73
74 let mut buffer = vec![0u8; magic.len()];
75 match file.read_exact(&mut buffer) {
76 Ok(()) => buffer == magic,
77 Err(_) => false,
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use std::io::Write;
85 use tempfile::NamedTempFile;
86
87 #[test]
88 fn test_is_zip() {
89 let mut file = NamedTempFile::new().unwrap();
91 file.write_all(&[0x50, 0x4B, 0x03, 0x04, 0x00, 0x00])
92 .unwrap();
93 assert!(is_zip(file.path()));
94
95 let mut file2 = NamedTempFile::new().unwrap();
97 file2.write_all(&[0x1F, 0x8B, 0x08, 0x00]).unwrap();
98 assert!(!is_zip(file2.path()));
99
100 assert!(!is_zip(Path::new("/nonexistent/file.zip")));
102 }
103
104 #[test]
105 fn test_is_squashfs_little_endian() {
106 let mut file = NamedTempFile::new().unwrap();
108 file.write_all(&[0x68, 0x73, 0x71, 0x73, 0x00, 0x00])
109 .unwrap();
110 assert!(is_squashfs(file.path()));
111 }
112
113 #[test]
114 fn test_is_squashfs_big_endian() {
115 let mut file = NamedTempFile::new().unwrap();
117 file.write_all(&[0x73, 0x71, 0x73, 0x68, 0x00, 0x00])
118 .unwrap();
119 assert!(is_squashfs(file.path()));
120 }
121
122 #[test]
123 fn test_is_squashfs_negative() {
124 let mut file = NamedTempFile::new().unwrap();
126 file.write_all(&[0x50, 0x4B, 0x03, 0x04]).unwrap();
127 assert!(!is_squashfs(file.path()));
128
129 assert!(!is_squashfs(Path::new("/nonexistent/file.squashfs")));
131 }
132
133 #[test]
134 fn test_is_nsis_installer() {
135 let mut file = NamedTempFile::new().unwrap();
137 file.write_all(b"MZ\x90\x00").unwrap(); file.write_all(b"Nullsoft.NSIS.exehead").unwrap();
139 file.write_all(&[0u8; 100]).unwrap();
140 assert!(is_nsis_installer(file.path()));
141
142 let mut file2 = NamedTempFile::new().unwrap();
144 file2.write_all(&vec![0u8; 1000]).unwrap();
145 file2.write_all(b"Nullsoft.NSIS.exehead").unwrap();
146 assert!(is_nsis_installer(file2.path()));
147
148 let mut file3 = NamedTempFile::new().unwrap();
150 file3.write_all(b"This is not an NSIS installer").unwrap();
151 assert!(!is_nsis_installer(file3.path()));
152
153 assert!(!is_nsis_installer(Path::new("/nonexistent/setup.exe")));
155 }
156
157 #[test]
158 fn test_is_nsis_installer_beyond_8kb() {
159 let mut file = NamedTempFile::new().unwrap();
161 file.write_all(&vec![0u8; 8500]).unwrap();
162 file.write_all(b"Nullsoft.NSIS.exehead").unwrap();
163 assert!(!is_nsis_installer(file.path()));
164 }
165
166 #[test]
167 fn test_check_magic_bytes_short_file() {
168 let mut file = NamedTempFile::new().unwrap();
170 file.write_all(&[0x50, 0x4B]).unwrap(); assert!(!check_magic_bytes(file.path(), &[0x50, 0x4B, 0x03, 0x04]));
172 }
173
174 #[test]
175 fn test_check_magic_bytes_empty_file() {
176 let file = NamedTempFile::new().unwrap();
178 assert!(!check_magic_bytes(file.path(), &[0x50, 0x4B]));
179 }
180}