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