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.BufferedOutputStream;
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.net.HttpURLConnection;
26 import java.net.URISyntaxException;
27 import java.net.URL;
28 import java.util.logging.Level;
29 import java.util.logging.Logger;
30 import java.util.zip.GZIPInputStream;
31 import java.util.zip.InflaterInputStream;
32
33
34
35
36
37
38 public final class Downloader {
39
40
41
42
43 private static final Logger LOGGER = Logger.getLogger(Downloader.class.getName());
44
45
46
47
48 private Downloader() {
49 }
50
51
52
53
54
55
56
57
58 public static void fetchFile(URL url, File outputPath) throws DownloadFailedException {
59 fetchFile(url, outputPath, true);
60 }
61
62
63
64
65
66
67
68
69
70 public static void fetchFile(URL url, File outputPath, boolean useProxy) throws DownloadFailedException {
71 if ("file".equalsIgnoreCase(url.getProtocol())) {
72 File file;
73 try {
74 file = new File(url.toURI());
75 } catch (URISyntaxException ex) {
76 final String msg = String.format("Download failed, unable to locate '%s'", url.toString());
77 throw new DownloadFailedException(msg);
78 }
79 if (file.exists()) {
80 try {
81 org.apache.commons.io.FileUtils.copyFile(file, outputPath);
82 } catch (IOException ex) {
83 final String msg = String.format("Download failed, unable to copy '%s' to '%s'", url.toString(), outputPath.getAbsolutePath());
84 throw new DownloadFailedException(msg);
85 }
86 } else {
87 final String msg = String.format("Download failed, file ('%s') does not exist", url.toString());
88 throw new DownloadFailedException(msg);
89 }
90 } else {
91 HttpURLConnection conn = null;
92 try {
93 conn = URLConnectionFactory.createHttpURLConnection(url, useProxy);
94 conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
95 conn.connect();
96 } catch (IOException ex) {
97 try {
98 if (conn != null) {
99 conn.disconnect();
100 }
101 } finally {
102 conn = null;
103 }
104 final String msg = String.format("Error downloading file %s; unable to connect.", url.toString());
105 throw new DownloadFailedException(msg, ex);
106 }
107 final String encoding = conn.getContentEncoding();
108
109 BufferedOutputStream writer = null;
110 InputStream reader = null;
111 try {
112 if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
113 reader = new GZIPInputStream(conn.getInputStream());
114 } else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
115 reader = new InflaterInputStream(conn.getInputStream());
116 } else {
117 reader = conn.getInputStream();
118 }
119
120 writer = new BufferedOutputStream(new FileOutputStream(outputPath));
121 final byte[] buffer = new byte[4096];
122 int bytesRead;
123 while ((bytesRead = reader.read(buffer)) > 0) {
124 writer.write(buffer, 0, bytesRead);
125 }
126 } catch (IOException ex) {
127 final String msg = String.format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
128 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
129 throw new DownloadFailedException(msg, ex);
130 } catch (Throwable ex) {
131 final String msg = String.format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
132 url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
133 throw new DownloadFailedException(msg, ex);
134 } finally {
135 if (writer != null) {
136 try {
137 writer.close();
138 } catch (IOException ex) {
139 LOGGER.log(Level.FINEST,
140 "Error closing the writer in Downloader.", ex);
141 }
142 }
143 if (reader != null) {
144 try {
145 reader.close();
146 } catch (IOException ex) {
147 LOGGER.log(Level.FINEST,
148 "Error closing the reader in Downloader.", ex);
149 }
150 }
151 try {
152 conn.disconnect();
153 } finally {
154 conn = null;
155 }
156 }
157 }
158 }
159
160
161
162
163
164
165
166
167
168 public static long getLastModified(URL url) throws DownloadFailedException {
169 long timestamp = 0;
170
171 if ("file".equalsIgnoreCase(url.getProtocol())) {
172 File lastModifiedFile;
173 try {
174 lastModifiedFile = new File(url.toURI());
175 } catch (URISyntaxException ex) {
176 final String msg = String.format("Unable to locate '%s'", url.toString());
177 throw new DownloadFailedException(msg);
178 }
179 timestamp = lastModifiedFile.lastModified();
180 } else {
181 HttpURLConnection conn = null;
182 try {
183 conn = URLConnectionFactory.createHttpURLConnection(url);
184 conn.setRequestMethod("HEAD");
185 conn.connect();
186 final int t = conn.getResponseCode();
187 if (t >= 200 && t < 300) {
188 timestamp = conn.getLastModified();
189 } else {
190 throw new DownloadFailedException("HEAD request returned a non-200 status code");
191 }
192 } catch (URLConnectionFailureException ex) {
193 throw new DownloadFailedException("Error creating URL Connection for HTTP HEAD request.", ex);
194 } catch (IOException ex) {
195 throw new DownloadFailedException("Error making HTTP HEAD request.", ex);
196 } finally {
197 if (conn != null) {
198 try {
199 conn.disconnect();
200 } finally {
201 conn = null;
202 }
203 }
204 }
205 }
206 return timestamp;
207 }
208 }