/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2012 ZAP development team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zaproxy.zap.extension.autoupdate; import java.io.File; import java.net.Authenticator; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.net.Proxy; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.network.ConnectionParam; import org.parosproxy.paros.view.View; public class DownloadManager extends Thread { private static final Logger logger = Logger.getLogger(DownloadManager.class); private List<Downloader> currentDownloads = new ArrayList<>(); private List<Downloader> completedDownloads = new ArrayList<>(); private boolean shutdown = false; private boolean cancelDownloads = false; private ConnectionParam connectionParam; public DownloadManager (ConnectionParam connectionParam) { super("ZAP-DownloadManager"); this.connectionParam = connectionParam; setDaemon(true); // TODO Remove once the class Downloader uses HttpClient instead of URL to download the file Authenticator.setDefault(new ZapProxyAuthenticator()); } public Downloader downloadFile (URL url, File targetFile, long size, String hash) { logger.debug("Download file " + url + " to " + targetFile.getAbsolutePath()); Proxy proxy; if (connectionParam.isUseProxy(url.getHost())) { InetSocketAddress scoketAddress = new InetSocketAddress(connectionParam.getProxyChainName(), connectionParam.getProxyChainPort()); proxy = new Proxy(Proxy.Type.HTTP, scoketAddress); } else { proxy = Proxy.NO_PROXY; } Downloader dl = new Downloader(url, proxy, targetFile, size, hash); dl.start(); this.currentDownloads.add(dl); return dl; } @Override public void run () { while (getCurrentDownloadCount() > 0 || !shutdown) { //logger.debug("# downloads " + this.currentDownloads.size() + " shutdown " + shutdown); List<Downloader> finishedDownloads = new ArrayList<>(); for (Downloader dl : this.currentDownloads) { if (!dl.isAlive()) { if (dl.getException() != null) { logger.debug("Download failed " + dl.getTargetFile().getAbsolutePath()); } else if (dl.isValidated()) { logger.debug("Download finished " + dl.getTargetFile().getAbsolutePath()); } else { // Corrupt or corrupted file? Pretty bad anyway logger.error("Validation failed " + dl.getTargetFile().getAbsolutePath()); dl.cancelDownload(); if (View.isInitialised()) { View.getSingleton().showWarningDialog( Constant.messages.getString("cfu.warn.badhash", new Object[] {dl.getTargetFile().getName()})); } } finishedDownloads.add(dl); } else if (this.cancelDownloads){ logger.debug("Cancelling download " + dl.getTargetFile().getAbsolutePath()); dl.cancelDownload(); } else { logger.debug("Still downloading " + dl.getTargetFile().getAbsolutePath() + " progress % " + dl.getProgressPercent()); } } for (Downloader dl : finishedDownloads) { this.completedDownloads.add(dl); this.currentDownloads.remove(dl); } try { if (getCurrentDownloadCount() > 0) { sleep(200); } else { sleep(1000); } } catch (InterruptedException e) { // Ignore } } logger.debug("Shutdown"); } public int getCurrentDownloadCount() { return this.currentDownloads.size(); } public void shutdown(boolean cancelDownloads) { this.shutdown = true; this.cancelDownloads = cancelDownloads; } public int getProgressPercent(URL url) throws Exception { for (Downloader dl : this.currentDownloads) { if (dl.getUrl().equals(url)) { if (dl.getException() != null) { throw dl.getException(); } return dl.getProgressPercent(); } } for (Downloader dl : this.completedDownloads) { if (dl.getUrl().equals(url)) { if (dl.getException() != null) { throw dl.getException(); } return 100; } } return -1; } public List<Downloader> getProgress() { List<Downloader> allDownloads = new ArrayList<>(); for (Downloader d : this.currentDownloads) { allDownloads.add(d); } for (Downloader d : this.completedDownloads) { allDownloads.add(d); } return allDownloads; } // TODO Remove once the class Downloader uses HttpClient instead of URL to download the file private final class ZapProxyAuthenticator extends Authenticator { @Override protected PasswordAuthentication getPasswordAuthentication() { if (getRequestorType() != RequestorType.PROXY) { return null; } if (getRequestingURL() == null) { return null; } if (!connectionParam.isUseProxy(getRequestingURL().getHost())) { return null; } if (connectionParam.getProxyChainPort() != getRequestingPort()) { return null; } if (!connectionParam.getProxyChainName().equals(getRequestingHost())) { return null; } return new PasswordAuthentication(connectionParam.getProxyChainUserName(), connectionParam.getProxyChainPassword() .toCharArray()); } } }