/* * Universal Password Manager * Copyright (C) 2005-2013 Adrian Smith * * This file is part of Universal Password Manager. * * Universal Password Manager is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Universal Password Manager is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Universal Password Manager; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package com._17od.upm.transport; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.codec.binary.Base64; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.multipart.FilePart; import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; import org.apache.commons.httpclient.methods.multipart.Part; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import com._17od.upm.util.Preferences; public class HTTPTransport extends Transport { private HttpClient client; public HTTPTransport() { client = new HttpClient(); Boolean acceptSelfSignedCerts = new Boolean(Preferences.get( Preferences.ApplicationOptions.HTTPS_ACCEPT_SELFSIGNED_CERTS)); if (acceptSelfSignedCerts.booleanValue()) { // Create a Protcol handler which contains a HTTPS socket factory // capable of accepting self signed and otherwise invalid certificates. Protocol httpsProtocol = new Protocol("https", (ProtocolSocketFactory) new EasySSLProtocolSocketFactory(), 443); Protocol.registerProtocol("https", httpsProtocol); } //Get the proxy settings Boolean proxyEnabled = new Boolean(Preferences.get(Preferences.ApplicationOptions.HTTP_PROXY_ENABLED)); if (proxyEnabled.booleanValue()) { String proxyHost = Preferences.get(Preferences.ApplicationOptions.HTTP_PROXY_HOST); String proxyPortStr = Preferences.get(Preferences.ApplicationOptions.HTTP_PROXY_PORT); String proxyUserName = Preferences.get(Preferences.ApplicationOptions.HTTP_PROXY_USERNAME); String proxyPassword = Preferences.get(Preferences.ApplicationOptions.HTTP_PROXY_PASSWORD); String decodedPassword = new String(Base64.decodeBase64(proxyPassword.getBytes())); if (isNotEmpty(proxyHost)) { int proxyPort = 0; if (isNotEmpty(proxyPortStr)) { proxyPort = Integer.parseInt(proxyPortStr); client.getHostConfiguration().setProxy(proxyHost, proxyPort); if (isNotEmpty(proxyUserName) && isNotEmpty(proxyPassword)) { client.getState().setProxyCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxyUserName, decodedPassword)); } } } } } public void put(String targetLocation, File file) throws TransportException { put(targetLocation, file, null, null); } public void put(String targetLocation, File file, String username, String password) throws TransportException { targetLocation = addTrailingSlash(targetLocation) + "upload.php"; PostMethod post = new PostMethod(targetLocation); //This part is wrapped in a try/finally so that we can ensure //the connection to the HTTP server is always closed cleanly try { Part[] parts = { new FilePart("userfile", file) }; post.setRequestEntity( new MultipartRequestEntity(parts, post.getParams()) ); //Set the HTTP authentication details if (username != null) { Credentials creds = new UsernamePasswordCredentials(new String(username), new String(password)); URL url = new URL(targetLocation); AuthScope authScope = new AuthScope(url.getHost(), url.getPort()); client.getState().setCredentials(authScope, creds); client.getParams().setAuthenticationPreemptive(true); } // This line makes the HTTP call int status = client.executeMethod(post); // I've noticed on Windows (at least) that PHP seems to fail when moving files on the first attempt // The second attempt works so lets just do that if (status == HttpStatus.SC_OK && post.getResponseBodyAsString().equals("FILE_WASNT_MOVED")) { status = client.executeMethod(post); } if (status != HttpStatus.SC_OK) { throw new TransportException("There's been some kind of problem uploading a file to the HTTP server.\n\nThe HTTP error message is [" + HttpStatus.getStatusText(status) + "]"); } if (!post.getResponseBodyAsString().equals("OK") ) { throw new TransportException("There's been some kind of problem uploading a file to the HTTP server.\n\nThe error message is [" + post.getResponseBodyAsString() + "]"); } } catch (FileNotFoundException e) { throw new TransportException(e); } catch (MalformedURLException e) { throw new TransportException(e); } catch (HttpException e) { throw new TransportException(e); } catch (IOException e) { throw new TransportException(e); } finally { post.releaseConnection(); } } public byte[] get(String url, String fileName) throws TransportException { return get(url, fileName, null, null); } public byte[] get(String url, String fileName, String username, String password) throws TransportException { url = addTrailingSlash(url); return get(url + fileName, username, password); } public byte[] get(String url, String username, String password) throws TransportException { byte[] retVal = null; GetMethod method = new GetMethod(url); //This part is wrapped in a try/finally so that we can ensure //the connection to the HTTP server is always closed cleanly try { //Set the authentication details if (username != null) { Credentials creds = new UsernamePasswordCredentials(new String(username), new String(password)); URL urlObj = new URL(url); AuthScope authScope = new AuthScope(urlObj.getHost(), urlObj.getPort()); client.getState().setCredentials(authScope, creds); client.getParams().setAuthenticationPreemptive(true); } int statusCode = client.executeMethod(method); if (statusCode != HttpStatus.SC_OK) { throw new TransportException("There's been some kind of problem getting the URL [" + url + "].\n\nThe HTTP error message is [" + HttpStatus.getStatusText(statusCode) + "]"); } retVal = method.getResponseBody(); } catch (MalformedURLException e) { throw new TransportException(e); } catch (HttpException e) { throw new TransportException(e); } catch (IOException e) { throw new TransportException(e); } finally { method.releaseConnection(); } return retVal; } public File getRemoteFile(String remoteLocation, String fileName) throws TransportException { return getRemoteFile(remoteLocation, fileName, null, null); } public File getRemoteFile(String remoteLocation) throws TransportException { return getRemoteFile(remoteLocation, null, null); } public File getRemoteFile(String remoteLocation, String fileName, String httpUsername, String httpPassword) throws TransportException { remoteLocation = addTrailingSlash(remoteLocation); return getRemoteFile(remoteLocation + fileName, httpUsername, httpPassword); } public File getRemoteFile(String remoteLocation, String httpUsername, String httpPassword) throws TransportException { try { byte[] remoteFile = get(remoteLocation, httpUsername, httpPassword); File downloadedFile = File.createTempFile("upm", null); FileOutputStream fos = new FileOutputStream(downloadedFile); fos.write(remoteFile); fos.close(); return downloadedFile; } catch (IOException e) { throw new TransportException(e); } } public void delete(String targetLocation, String name, String username, String password) throws TransportException { targetLocation = addTrailingSlash(targetLocation) + "deletefile.php"; PostMethod post = new PostMethod(targetLocation); post.addParameter("fileToDelete", name); //This part is wrapped in a try/finally so that we can ensure //the connection to the HTTP server is always closed cleanly try { //Set the authentication details if (username != null) { Credentials creds = new UsernamePasswordCredentials(new String(username), new String(password)); URL url = new URL(targetLocation); AuthScope authScope = new AuthScope(url.getHost(), url.getPort()); client.getState().setCredentials(authScope, creds); client.getParams().setAuthenticationPreemptive(true); } int status = client.executeMethod(post); if (status != HttpStatus.SC_OK) { throw new TransportException("There's been some kind of problem deleting a file on the HTTP server.\n\nThe HTTP error message is [" + HttpStatus.getStatusText(status) + "]"); } if (!post.getResponseBodyAsString().equals("OK") ) { throw new TransportException("There's been some kind of problem deleting a file to the HTTP server.\n\nThe error message is [" + post.getResponseBodyAsString() + "]"); } } catch (MalformedURLException e) { throw new TransportException(e); } catch (HttpException e) { throw new TransportException(e); } catch (IOException e) { throw new TransportException(e); } finally { post.releaseConnection(); } } public void delete(String targetLocation, String name) throws TransportException { delete(targetLocation, name, null, null); } private String addTrailingSlash(String url) { if (url.charAt(url.length() - 1) != '/') { url = url + '/'; } return url; } private boolean isNotEmpty(String stringToCheck) { boolean retVal = false; if (stringToCheck != null && !stringToCheck.trim().equals("")) { retVal = true; } return retVal; } }