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.Closeable;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.FilenameFilter;
27 import java.io.IOException;
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 public static void extractFiles(File archive, File extractTo) throws ExtractionException {
67 extractFiles(archive, extractTo, null);
68 }
69
70
71
72
73
74
75
76
77
78
79 public static void extractFiles(File archive, File extractTo, Engine engine) throws ExtractionException {
80 if (archive == null || extractTo == null) {
81 return;
82 }
83
84 FileInputStream fis = null;
85 ZipInputStream zis = null;
86
87 try {
88 fis = new FileInputStream(archive);
89 } catch (FileNotFoundException ex) {
90 LOGGER.debug("", ex);
91 throw new ExtractionException("Archive file was not found.", ex);
92 }
93 zis = new ZipInputStream(new BufferedInputStream(fis));
94 ZipEntry entry;
95 try {
96 while ((entry = zis.getNextEntry()) != null) {
97 if (entry.isDirectory()) {
98 final File d = new File(extractTo, entry.getName());
99 if (!d.exists() && !d.mkdirs()) {
100 final String msg = String.format("Unable to create '%s'.", d.getAbsolutePath());
101 throw new ExtractionException(msg);
102 }
103 } else {
104 final File file = new File(extractTo, entry.getName());
105 if (engine == null || engine.accept(file)) {
106 FileOutputStream fos = null;
107 try {
108 fos = new FileOutputStream(file);
109 IOUtils.copy(zis, fos);
110 } catch (FileNotFoundException ex) {
111 LOGGER.debug("", ex);
112 final String msg = String.format("Unable to find file '%s'.", file.getName());
113 throw new ExtractionException(msg, ex);
114 } catch (IOException ex) {
115 LOGGER.debug("", ex);
116 final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
117 throw new ExtractionException(msg, ex);
118 } finally {
119 closeStream(fos);
120 }
121 }
122 }
123 }
124 } catch (IOException ex) {
125 final String msg = String.format("Exception reading archive '%s'.", archive.getName());
126 LOGGER.debug("", ex);
127 throw new ExtractionException(msg, ex);
128 } finally {
129 closeStream(zis);
130 }
131 }
132
133
134
135
136
137
138
139
140
141 public static void extractFilesUsingFilter(File archive, File destination,
142 FilenameFilter filter) throws ExtractionException {
143 if (archive == null || destination == null) {
144 return;
145 }
146
147 FileInputStream fis = null;
148 try {
149 fis = new FileInputStream(archive);
150 } catch (FileNotFoundException ex) {
151 LOGGER.debug("", ex);
152 throw new ExtractionException("Archive file was not found.", ex);
153 }
154 try {
155 extractArchive(new ZipArchiveInputStream(new BufferedInputStream(
156 fis)), destination, filter);
157 } catch (ArchiveExtractionException ex) {
158 LOGGER.warn("Exception extracting archive '{}'.", archive.getName());
159 LOGGER.debug("", ex);
160 } finally {
161 try {
162 fis.close();
163 } catch (IOException ex) {
164 LOGGER.debug("", ex);
165 }
166 }
167 }
168
169
170
171
172
173
174
175
176
177 private static void extractArchive(ArchiveInputStream input,
178 File destination, FilenameFilter filter)
179 throws ArchiveExtractionException {
180 ArchiveEntry entry;
181 try {
182 while ((entry = input.getNextEntry()) != null) {
183 if (entry.isDirectory()) {
184 final File dir = new File(destination, entry.getName());
185 if (!dir.exists() && !dir.mkdirs()) {
186 final String msg = String.format(
187 "Unable to create directory '%s'.",
188 dir.getAbsolutePath());
189 throw new AnalysisException(msg);
190 }
191 } else {
192 extractFile(input, destination, filter, entry);
193 }
194 }
195 } catch (IOException ex) {
196 throw new ArchiveExtractionException(ex);
197 } catch (Throwable ex) {
198 throw new ArchiveExtractionException(ex);
199 } finally {
200 closeStream(input);
201 }
202 }
203
204
205
206
207
208
209
210
211
212
213 private static void extractFile(ArchiveInputStream input, File destination,
214 FilenameFilter filter, ArchiveEntry entry) throws ExtractionException {
215 final File file = new File(destination, entry.getName());
216 if (filter.accept(file.getParentFile(), file.getName())) {
217 LOGGER.debug("Extracting '{}'",
218 file.getPath());
219 FileOutputStream fos = null;
220 try {
221 createParentFile(file);
222 fos = new FileOutputStream(file);
223 IOUtils.copy(input, fos);
224 } catch (FileNotFoundException ex) {
225 LOGGER.debug("", ex);
226 final String msg = String.format("Unable to find file '%s'.",
227 file.getName());
228 throw new ExtractionException(msg, ex);
229 } catch (IOException ex) {
230 LOGGER.debug("", ex);
231 final String msg = String
232 .format("IO Exception while parsing file '%s'.",
233 file.getName());
234 throw new ExtractionException(msg, ex);
235 } finally {
236 closeStream(fos);
237 }
238 }
239 }
240
241
242
243
244
245
246 private static void closeStream(Closeable stream) {
247 if (stream != null) {
248 try {
249 stream.close();
250 } catch (IOException ex) {
251 LOGGER.trace("", ex);
252 }
253 }
254 }
255
256
257
258
259
260
261
262 private static void createParentFile(final File file)
263 throws ExtractionException {
264 final File parent = file.getParentFile();
265 if (!parent.isDirectory() && !parent.mkdirs()) {
266 final String msg = String.format(
267 "Unable to build directory '%s'.",
268 parent.getAbsolutePath());
269 throw new ExtractionException(msg);
270 }
271 }
272 }