1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.utils;
19
20 import java.io.BufferedInputStream;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.FileOutputStream;
25 import java.io.FilenameFilter;
26 import java.io.IOException;
27 import java.util.zip.GZIPInputStream;
28 import java.util.zip.ZipEntry;
29 import java.util.zip.ZipInputStream;
30
31 import org.apache.commons.compress.archivers.ArchiveEntry;
32 import org.apache.commons.compress.archivers.ArchiveInputStream;
33 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
34 import org.apache.commons.compress.utils.IOUtils;
35 import org.owasp.dependencycheck.Engine;
36 import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
37 import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41
42
43
44
45
46 public final class ExtractionUtil {
47
48
49
50
51 private static final Logger LOGGER = LoggerFactory.getLogger(ExtractionUtil.class);
52
53
54
55
56 private ExtractionUtil() {
57 }
58
59
60
61
62
63
64
65
66
67 public static void extractFiles(File archive, File extractTo) throws ExtractionException {
68 extractFiles(archive, extractTo, null);
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83 public static void extractFiles(File archive, File extractTo, Engine engine) throws ExtractionException {
84 if (archive == null || extractTo == null) {
85 return;
86 }
87
88 FileInputStream fis = null;
89 ZipInputStream zis = null;
90
91 try {
92 fis = new FileInputStream(archive);
93 } catch (FileNotFoundException ex) {
94 LOGGER.debug("", ex);
95 throw new ExtractionException("Archive file was not found.", ex);
96 }
97 zis = new ZipInputStream(new BufferedInputStream(fis));
98 ZipEntry entry;
99 try {
100 while ((entry = zis.getNextEntry()) != null) {
101 if (entry.isDirectory()) {
102 final File d = new File(extractTo, entry.getName());
103 if (!d.exists() && !d.mkdirs()) {
104 final String msg = String.format("Unable to create '%s'.", d.getAbsolutePath());
105 throw new ExtractionException(msg);
106 }
107 } else {
108 final File file = new File(extractTo, entry.getName());
109 if (engine == null || engine.accept(file)) {
110 FileOutputStream fos = null;
111 try {
112 fos = new FileOutputStream(file);
113 IOUtils.copy(zis, fos);
114 } catch (FileNotFoundException ex) {
115 LOGGER.debug("", ex);
116 final String msg = String.format("Unable to find file '%s'.", file.getName());
117 throw new ExtractionException(msg, ex);
118 } catch (IOException ex) {
119 LOGGER.debug("", ex);
120 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
121 throw new ExtractionException(msg, ex);
122 } finally {
123 FileUtils.close(fos);
124 }
125 }
126 }
127 }
128 } catch (IOException ex) {
129 final String msg = String.format("Exception reading archive '%s'.", archive.getName());
130 LOGGER.debug("", ex);
131 throw new ExtractionException(msg, ex);
132 } finally {
133 FileUtils.close(zis);
134 }
135 }
136
137
138
139
140
141
142
143
144
145 public static void extractFilesUsingFilter(File archive, File destination,
146 FilenameFilter filter) throws ExtractionException {
147 if (archive == null || destination == null) {
148 return;
149 }
150
151 FileInputStream fis = null;
152 try {
153 fis = new FileInputStream(archive);
154 } catch (FileNotFoundException ex) {
155 LOGGER.debug("", ex);
156 throw new ExtractionException("Archive file was not found.", ex);
157 }
158 try {
159 extractArchive(new ZipArchiveInputStream(new BufferedInputStream(
160 fis)), destination, filter);
161 } catch (ArchiveExtractionException ex) {
162 LOGGER.warn("Exception extracting archive '{}'.", archive.getName());
163 LOGGER.debug("", ex);
164 } finally {
165 try {
166 fis.close();
167 } catch (IOException ex) {
168 LOGGER.debug("", ex);
169 }
170 }
171 }
172
173
174
175
176
177
178
179
180
181
182 private static void extractArchive(ArchiveInputStream input,
183 File destination, FilenameFilter filter)
184 throws ArchiveExtractionException {
185 ArchiveEntry entry;
186 try {
187 while ((entry = input.getNextEntry()) != null) {
188 if (entry.isDirectory()) {
189 final File dir = new File(destination, entry.getName());
190 if (!dir.exists() && !dir.mkdirs()) {
191 final String msg = String.format(
192 "Unable to create directory '%s'.",
193 dir.getAbsolutePath());
194 throw new AnalysisException(msg);
195 }
196 } else {
197 extractFile(input, destination, filter, entry);
198 }
199 }
200 } catch (IOException ex) {
201 throw new ArchiveExtractionException(ex);
202 } catch (Throwable ex) {
203 throw new ArchiveExtractionException(ex);
204 } finally {
205 FileUtils.close(input);
206 }
207 }
208
209
210
211
212
213
214
215
216
217
218
219
220 private static void extractFile(ArchiveInputStream input, File destination,
221 FilenameFilter filter, ArchiveEntry entry) throws ExtractionException {
222 final File file = new File(destination, entry.getName());
223 if (filter.accept(file.getParentFile(), file.getName())) {
224 LOGGER.debug("Extracting '{}'",
225 file.getPath());
226 FileOutputStream fos = null;
227 try {
228 createParentFile(file);
229 fos = new FileOutputStream(file);
230 IOUtils.copy(input, fos);
231 } catch (FileNotFoundException ex) {
232 LOGGER.debug("", ex);
233 final String msg = String.format("Unable to find file '%s'.",
234 file.getName());
235 throw new ExtractionException(msg, ex);
236 } catch (IOException ex) {
237 LOGGER.debug("", ex);
238 final String msg = String
239 .format("IO Exception while parsing file '%s'.",
240 file.getName());
241 throw new ExtractionException(msg, ex);
242 } finally {
243 FileUtils.close(fos);
244 }
245 }
246 }
247
248
249
250
251
252
253
254
255
256 private static void createParentFile(final File file)
257 throws ExtractionException {
258 final File parent = file.getParentFile();
259 if (!parent.isDirectory() && !parent.mkdirs()) {
260 final String msg = String.format(
261 "Unable to build directory '%s'.",
262 parent.getAbsolutePath());
263 throw new ExtractionException(msg);
264 }
265 }
266
267
268
269
270
271
272
273
274
275 public static void extractGzip(File file) throws FileNotFoundException, IOException {
276 final String originalPath = file.getPath();
277 final File gzip = new File(originalPath + ".gz");
278 if (gzip.isFile() && !gzip.delete()) {
279 LOGGER.debug("Failed to delete initial temporary file when extracting 'gz' {}", gzip.toString());
280 gzip.deleteOnExit();
281 }
282 if (!file.renameTo(gzip)) {
283 throw new IOException("Unable to rename '" + file.getPath() + "'");
284 }
285 final File newfile = new File(originalPath);
286
287 final byte[] buffer = new byte[4096];
288
289 GZIPInputStream cin = null;
290 FileOutputStream out = null;
291 try {
292 cin = new GZIPInputStream(new FileInputStream(gzip));
293 out = new FileOutputStream(newfile);
294
295 int len;
296 while ((len = cin.read(buffer)) > 0) {
297 out.write(buffer, 0, len);
298 }
299 } finally {
300 if (cin != null) {
301 try {
302 cin.close();
303 } catch (IOException ex) {
304 LOGGER.trace("ignore", ex);
305 }
306 }
307 if (out != null) {
308 try {
309 out.close();
310 } catch (IOException ex) {
311 LOGGER.trace("ignore", ex);
312 }
313 }
314 if (gzip.isFile() && !org.apache.commons.io.FileUtils.deleteQuietly(gzip)) {
315 LOGGER.debug("Failed to delete temporary file when extracting 'gz' {}", gzip.toString());
316 gzip.deleteOnExit();
317 }
318 }
319 }
320 }