1use std::path::Path;
24
25use super::PackageParser;
26use super::maven::{JvmArchiveKind, extract_jvm_archive};
27use crate::models::{DatasourceId, PackageData, PackageType};
28use crate::utils::magic;
29
30macro_rules! file_recognizer {
42 ($name:ident, $pkg_type:expr, $datasource:expr, $match_fn:expr) => {
43 pub struct $name;
44
45 impl PackageParser for $name {
46 const PACKAGE_TYPE: PackageType = $pkg_type;
47
48 fn is_match(path: &Path) -> bool {
49 ($match_fn)(path)
50 }
51
52 fn extract_packages(path: &Path) -> Vec<PackageData> {
53 let _ = path;
54 vec![PackageData {
55 package_type: Some($pkg_type),
56 datasource_id: Some($datasource),
57 ..Default::default()
58 }]
59 }
60 }
61 };
62}
63
64pub struct JavaJarRecognizer;
72
73impl PackageParser for JavaJarRecognizer {
74 const PACKAGE_TYPE: PackageType = PackageType::Jar;
75
76 fn is_match(path: &Path) -> bool {
77 path.extension().and_then(|e| e.to_str()) == Some("jar")
78 }
79
80 fn extract_packages(path: &Path) -> Vec<PackageData> {
81 extract_jvm_archive(path, JvmArchiveKind::Jar)
82 }
83}
84
85pub struct JavaWarRecognizer;
87
88impl PackageParser for JavaWarRecognizer {
89 const PACKAGE_TYPE: PackageType = PackageType::War;
90
91 fn is_match(path: &Path) -> bool {
92 path.extension().and_then(|e| e.to_str()) == Some("war")
93 }
94
95 fn extract_packages(path: &Path) -> Vec<PackageData> {
96 extract_jvm_archive(path, JvmArchiveKind::War)
97 }
98}
99
100file_recognizer!(
101 JavaWarWebXmlRecognizer,
102 PackageType::War,
103 DatasourceId::JavaWarWebXml,
104 |path: &Path| path
105 .to_str()
106 .is_some_and(|p| p.ends_with("/WEB-INF/web.xml") || p.ends_with("WEB-INF/web.xml"))
107);
108
109file_recognizer!(
110 JavaEarRecognizer,
111 PackageType::Ear,
112 DatasourceId::JavaEarArchive,
113 |path: &Path| path.extension().and_then(|e| e.to_str()) == Some("ear")
114);
115
116file_recognizer!(
117 JavaEarAppXmlRecognizer,
118 PackageType::Ear,
119 DatasourceId::JavaEarApplicationXml,
120 |path: &Path| path.to_str().is_some_and(
121 |p| p.ends_with("/META-INF/application.xml") || p.ends_with("META-INF/application.xml")
122 )
123);
124
125file_recognizer!(
128 Axis2ModuleXmlRecognizer,
129 PackageType::Axis2,
130 DatasourceId::Axis2ModuleXml,
131 |path: &Path| {
132 path.to_str().is_some_and(|p| {
133 let lower = p.to_lowercase();
134 lower.ends_with("/meta-inf/module.xml") || lower.ends_with("meta-inf/module.xml")
135 })
136 }
137);
138
139file_recognizer!(
140 Axis2MarRecognizer,
141 PackageType::Axis2,
142 DatasourceId::Axis2Mar,
143 |path: &Path| path.extension().and_then(|e| e.to_str()) == Some("mar")
144);
145
146file_recognizer!(
149 JBossSarRecognizer,
150 PackageType::JbossService,
151 DatasourceId::JbossSar,
152 |path: &Path| path.extension().and_then(|e| e.to_str()) == Some("sar")
153);
154
155file_recognizer!(
156 JBossServiceXmlRecognizer,
157 PackageType::JbossService,
158 DatasourceId::JbossServiceXml,
159 |path: &Path| {
160 path.to_str().is_some_and(|p| {
161 let lower = p.to_lowercase();
162 lower.ends_with("/meta-inf/jboss-service.xml")
163 || lower.ends_with("meta-inf/jboss-service.xml")
164 })
165 }
166);
167
168file_recognizer!(
171 MeteorPackageRecognizer,
172 PackageType::Meteor,
173 DatasourceId::MeteorPackage,
174 |path: &Path| path.to_str().is_some_and(|p| p.ends_with("/package.js"))
175);
176
177pub struct AndroidLibraryRecognizer;
181
182impl PackageParser for AndroidLibraryRecognizer {
183 const PACKAGE_TYPE: PackageType = PackageType::AndroidLib;
184
185 fn is_match(path: &Path) -> bool {
186 path.extension().and_then(|e| e.to_str()) == Some("aar")
187 }
188
189 fn extract_packages(path: &Path) -> Vec<PackageData> {
190 extract_jvm_archive(path, JvmArchiveKind::Aar)
191 }
192}
193
194file_recognizer!(
195 MozillaXpiRecognizer,
196 PackageType::Mozilla,
197 DatasourceId::MozillaXpi,
198 |path: &Path| path.extension().and_then(|e| e.to_str()) == Some("xpi")
199);
200
201file_recognizer!(
202 ChromeCrxRecognizer,
203 PackageType::Chrome,
204 DatasourceId::ChromeCrx,
205 |path: &Path| path.extension().and_then(|e| e.to_str()) == Some("crx")
206);
207
208file_recognizer!(
209 IosIpaRecognizer,
210 PackageType::Ios,
211 DatasourceId::IosIpa,
212 |path: &Path| path.extension().and_then(|e| e.to_str()) == Some("ipa")
213);
214
215file_recognizer!(
218 CabArchiveRecognizer,
219 PackageType::Cab,
220 DatasourceId::MicrosoftCabinet,
221 |path: &Path| path.extension().and_then(|e| e.to_str()) == Some("cab")
222);
223
224file_recognizer!(
225 SharArchiveRecognizer,
226 PackageType::Shar,
227 DatasourceId::SharShellArchive,
228 |path: &Path| path.extension().and_then(|e| e.to_str()) == Some("shar")
229);
230
231file_recognizer!(
234 AppleDmgRecognizer,
235 PackageType::Dmg,
236 DatasourceId::AppleDmg,
237 |path: &Path| {
238 path.extension()
239 .and_then(|e| e.to_str())
240 .is_some_and(|ext| ext == "dmg" || ext == "sparseimage")
241 }
242);
243
244file_recognizer!(
245 IsoImageRecognizer,
246 PackageType::Iso,
247 DatasourceId::IsoDiskImage,
248 |path: &Path| {
249 path.extension()
250 .and_then(|e| e.to_str())
251 .is_some_and(|ext| ext == "iso" || ext == "udf" || ext == "img")
252 }
253);
254
255file_recognizer!(
258 SquashfsRecognizer,
259 PackageType::Squashfs,
260 DatasourceId::SquashfsDiskImage,
261 |path: &Path| magic::is_squashfs(path)
262);
263
264file_recognizer!(
265 NsisRecognizer,
266 PackageType::Nsis,
267 DatasourceId::NsisInstaller,
268 |path: &Path| {
269 path.extension()
270 .and_then(|e| e.to_str())
271 .is_some_and(|ext| ext == "exe")
272 && magic::is_nsis_installer(path)
273 }
274);
275
276file_recognizer!(
277 InstallShieldRecognizer,
278 PackageType::Installshield,
279 DatasourceId::InstallshieldInstaller,
280 |path: &Path| {
281 path.extension()
282 .and_then(|e| e.to_str())
283 .is_some_and(|ext| ext == "exe")
284 && magic::is_zip(path)
285 }
286);
287
288pub(crate) static RECOGNIZER_METADATA: &[super::metadata::ParserMetadata] = &[
289 super::metadata::ParserMetadata {
290 description: "Misc file type recognizers (JAR, WAR, EAR, AAR, iOS, Chrome, Mozilla, installers, disk images, etc.)",
291 file_patterns: &[
292 "**/*.jar",
293 "**/*.war",
294 "**/WEB-INF/web.xml",
295 "**/*.ear",
296 "**/META-INF/application.xml",
297 "**/meta-inf/module.xml",
298 "**/*.mar",
299 "**/*.sar",
300 "**/meta-inf/jboss-service.xml",
301 "**/package.js",
302 "**/*.aar",
303 "**/*.xpi",
304 "**/*.crx",
305 "**/*.ipa",
306 "**/*.cab",
307 "**/*.shar",
308 "**/*.dmg",
309 "**/*.sparseimage",
310 "**/*.iso",
311 "**/*.udf",
312 "**/*.img",
313 "**/*.exe",
314 ],
315 package_type: "",
316 primary_language: "",
317 documentation_url: None,
318 },
319];