##### Coverage Report - org.owasp.dependencycheck.utils.Downloader

Classes in this File | Line Coverage | Branch Coverage | Complexity
Downloader |
7% | 7/88
3% | 1/28
| 6.6;6.6
Downloader$1 |
0% | 0/4
0% | 0/2
| 6.6;6.6

1 |  |
     /*
2 |  |
      * This file is part of dependency-check-core.
3 |  |
      *
4 |  |
      * Dependency-check-core is free software: you can redistribute it and/or modify it
5 |  |
      * under the terms of the GNU General Public License as published by the Free
6 |  |
      * Software Foundation, either version 3 of the License, or (at your option) any
7 |  |
      * later version.
8 |  |
      *
9 |  |
      * Dependency-check-core is distributed in the hope that it will be useful, but
10 |  |
      * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 |  |
      * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 |  |
      * details.
13 |  |
      *
14 |  |
      * You should have received a copy of the GNU General Public License along with
15 |  |
      * dependency-check-core. If not, see http://www.gnu.org/licenses/.
16 |  |
      *
17 |  |
      * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
18 |  |
      */
19 |  |
     package org.owasp.dependencycheck.utils;
20 |  |
21 |  |
     import java.io.BufferedOutputStream;
22 |  |
     import java.io.File;
23 |  |
     import java.io.FileOutputStream;
24 |  |
     import java.io.IOException;
25 |  |
     import java.io.InputStream;
26 |  |
     import java.net.Authenticator;
27 |  |
     import java.net.HttpURLConnection;
28 |  |
     import java.net.InetSocketAddress;
29 |  |
     import java.net.PasswordAuthentication;
30 |  |
     import java.net.Proxy;
31 |  |
     import java.net.SocketAddress;
32 |  |
     import java.net.URISyntaxException;
33 |  |
     import java.net.URL;
34 |  |
     import java.util.logging.Level;
35 |  |
     import java.util.logging.Logger;
36 |  |
     import java.util.zip.GZIPInputStream;
37 |  |
     import java.util.zip.InflaterInputStream;
38 |  |
39 |  |
     /**
40 |  |
      * A utility to download files from the Internet.
41 |  |
      *
42 |  |
      * @author Jeremy Long (jeremy.long@owasp.org)
43 |  |
      */
44 |  |
     public final class Downloader {
45 |  |
46 |  |
         /**
47 |  |
          * Private constructor for utility class.
48 |  |
          */
49 | 0 |
         private Downloader() {
50 | 0 |
         }
51 |  |
52 |  |
         /**
53 |  |
          * Retrieves a file from a given URL and saves it to the outputPath.
54 |  |
          *
55 |  |
          * @param url the URL of the file to download.
56 |  |
          * @param outputPath the path to the save the file to.
57 |  |
          * @throws DownloadFailedException is thrown if there is an error
58 |  |
          * downloading the file.
59 |  |
          */
60 |  |
         public static void fetchFile(URL url, File outputPath) throws DownloadFailedException {
61 | 0 |
             HttpURLConnection conn = null;
62 |  |
             try {
63 | 0 |
                 conn = Downloader.getConnection(url);
64 | 0 |
                 conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
65 | 0 |
                 conn.connect();
66 | 0 |
             } catch (IOException ex) {
67 |  |
                 try {
68 | 0 |
                     if (conn != null) {
69 | 0 |
                         conn.disconnect();
70 |  |
                     }
71 |  |
                 } finally {
72 | 0 |
                     conn = null;
73 | 0 |
                 }
74 | 0 |
                 throw new DownloadFailedException("Error downloading file.", ex);
75 | 0 |
             }
76 | 0 |
             final String encoding = conn.getContentEncoding();
77 |  |
78 | 0 |
             BufferedOutputStream writer = null;
79 | 0 |
             InputStream reader = null;
80 |  |
             try {
81 | 0 |
                 if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
82 | 0 |
                     reader = new GZIPInputStream(conn.getInputStream());
83 | 0 |
                 } else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
84 | 0 |
                     reader = new InflaterInputStream(conn.getInputStream());
85 |  |
                 } else {
86 | 0 |
                     reader = conn.getInputStream();
87 |  |
                 }
88 |  |
89 | 0 |
                 writer = new BufferedOutputStream(new FileOutputStream(outputPath));
90 | 0 |
                 final byte[] buffer = new byte[4096];
91 |  |
                 int bytesRead;
92 | 0 |
                 while ((bytesRead = reader.read(buffer)) > 0) {
93 | 0 |
                     writer.write(buffer, 0, bytesRead);
94 |  |
                 }
95 | 0 |
             } catch (Exception ex) {
96 | 0 |
                 throw new DownloadFailedException("Error saving downloaded file.", ex);
97 |  |
             } finally {
98 | 0 |
                 if (writer != null) {
99 |  |
                     try {
100 | 0 |
                         writer.close();
101 | 0 |
                     } catch (Exception ex) {
102 | 0 |
                         Logger.getLogger(Downloader.class.getName()).log(Level.FINEST,
103 |  |
                                 "Error closing the writer in Downloader.", ex);
104 | 0 |
                     }
105 |  |
                 }
106 | 0 |
                 if (reader != null) {
107 |  |
                     try {
108 | 0 |
                         reader.close();
109 | 0 |
                     } catch (Exception ex) {
110 | 0 |
                         Logger.getLogger(Downloader.class.getName()).log(Level.FINEST,
111 |  |
                                 "Error closing the reader in Downloader.", ex);
112 | 0 |
                     }
113 |  |
                 }
114 |  |
                 try {
115 | 0 |
                     conn.disconnect();
116 |  |
                 } finally {
117 | 0 |
                     conn = null;
118 | 0 |
                 }
119 | 0 |
             }
120 | 0 |
         }
121 |  |
122 |  |
         /**
123 |  |
          * Makes an HTTP Head request to retrieve the last modified date of the
124 |  |
          * given URL. If the file:// protocol is specified, then the lastTimestamp
125 |  |
          * of the file is returned.
126 |  |
          *
127 |  |
          * @param url the URL to retrieve the timestamp from
128 |  |
          * @return an epoch timestamp
129 |  |
          * @throws DownloadFailedException is thrown if an exception occurs making
130 |  |
          * the HTTP request
131 |  |
          */
132 |  |
         public static long getLastModified(URL url) throws DownloadFailedException {
133 | 14 |
             long timestamp = 0;
134 |  |
             //TODO add the FPR protocol?
135 | 14 |
             if ("file".equalsIgnoreCase(url.getProtocol())) {
136 |  |
                 File lastModifiedFile;
137 |  |
                 try {
138 |  |
     //                if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
139 |  |
     //                    String filePath = url.toString();
140 |  |
     //                    if (filePath.matches("file://[a-zA-Z]:.*")) {
141 |  |
     //                        f = new File(filePath.substring(7));
142 |  |
     //                    } else {
143 |  |
     //                        f = new File(url.toURI());
144 |  |
     //                    }
145 |  |
     //                } else {
146 | 14 |
                     lastModifiedFile = new File(url.toURI());
147 |  |
     //                }
148 | 0 |
                 } catch (URISyntaxException ex) {
149 | 0 |
                     final String msg = String.format("Unable to locate '%s'; is the cve.url-2.0.modified property set correctly?", url.toString());
150 | 0 |
                     throw new DownloadFailedException(msg);
151 | 14 |
                 }
152 | 14 |
                 timestamp = lastModifiedFile.lastModified();
153 | 14 |
             } else {
154 | 0 |
                 HttpURLConnection conn = null;
155 |  |
                 try {
156 | 0 |
                     conn = Downloader.getConnection(url);
157 | 0 |
                     conn.setRequestMethod("HEAD");
158 | 0 |
                     conn.connect();
159 | 0 |
                     timestamp = conn.getLastModified();
160 | 0 |
                 } catch (Exception ex) {
161 | 0 |
                     throw new DownloadFailedException("Error making HTTP HEAD request.", ex);
162 |  |
                 } finally {
163 | 0 |
                     if (conn != null) {
164 |  |
                         try {
165 | 0 |
                             conn.disconnect();
166 |  |
                         } finally {
167 | 0 |
                             conn = null;
168 | 0 |
                         }
169 |  |
                     }
170 |  |
                 }
171 |  |
             }
172 | 14 |
             return timestamp;
173 |  |
         }
174 |  |
175 |  |
         /**
176 |  |
          * Utility method to get an HttpURLConnection. If the app is configured to
177 |  |
          * use a proxy this method will retrieve the proxy settings and use them
178 |  |
          * when setting up the connection.
179 |  |
          *
180 |  |
          * @param url the url to connect to
181 |  |
          * @return an HttpURLConnection
182 |  |
          * @throws DownloadFailedException thrown if there is an exception
183 |  |
          */
184 |  |
         private static HttpURLConnection getConnection(URL url) throws DownloadFailedException {
185 | 0 |
             HttpURLConnection conn = null;
186 | 0 |
             Proxy proxy = null;
187 | 0 |
             final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_URL);
188 |  |
             try {
189 | 0 |
                 if (proxyUrl != null) {
190 | 0 |
                     final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);
191 | 0 |
                     final SocketAddress addr = new InetSocketAddress(proxyUrl, proxyPort);
192 |  |
193 | 0 |
                     final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME);
194 | 0 |
                     final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD);
195 | 0 |
                     if (username != null && password != null) {
196 | 0 |
                         final Authenticator auth = new Authenticator() {
197 |  |
                             @Override
198 |  |
                             public PasswordAuthentication getPasswordAuthentication() {
199 | 0 |
                                 if (getRequestorType().equals(RequestorType.PROXY)) {
200 | 0 |
                                     return new PasswordAuthentication(username, password.toCharArray());
201 |  |
                                 }
202 | 0 |
                                 return super.getPasswordAuthentication();
203 |  |
                             }
204 |  |
                         };
205 | 0 |
                         Authenticator.setDefault(auth);
206 |  |
                     }
207 |  |
208 | 0 |
                     proxy = new Proxy(Proxy.Type.HTTP, addr);
209 | 0 |
                     conn = (HttpURLConnection) url.openConnection(proxy);
210 | 0 |
                 } else {
211 | 0 |
                     conn = (HttpURLConnection) url.openConnection();
212 |  |
                 }
213 | 0 |
                 final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 60000);
214 | 0 |
                 conn.setConnectTimeout(timeout);
215 | 0 |
             } catch (IOException ex) {
216 | 0 |
                 if (conn != null) {
217 |  |
                     try {
218 | 0 |
                         conn.disconnect();
219 |  |
                     } finally {
220 | 0 |
                         conn = null;
221 | 0 |
                     }
222 |  |
                 }
223 | 0 |
                 throw new DownloadFailedException("Error getting connection.", ex);
224 | 0 |
             }
225 | 0 |
             return conn;
226 |  |
         }
227 |  |
     }