package com.universalbits.conorganizer.common; import javax.net.ssl.*; import java.io.*; import java.net.*; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; public class APIClient { private static final Logger LOGGER = Logger.getLogger(APIClient.class.getName()); private ISettings settings; private MessageDigest digest; public static final String PROPERTY_NAME = "name"; public static final String PROPERTY_UUID = "uuid"; public static final String PROPERTY_TOKEN = "token"; public static final String PROPERTY_COUNTER = "counter"; public static final String PROPERTY_KEY = "key"; public static final String PROPERTY_URL_PREFIX = "urlPrefix"; public APIClient(ISettings settings) { this.settings = settings; APIClient.setupHTTPS(); if (settings == null) { throw new IllegalStateException("Settings cannot be null"); } String uuid = settings.getProperty(PROPERTY_UUID, ""); if (uuid.length() != 32) { uuid = UUID.randomUUID().toString().replaceAll("-", ""); settings.setProperty(PROPERTY_UUID, uuid); } final String clientName = settings.getProperty(PROPERTY_NAME, getHostname()); settings.setProperty(PROPERTY_NAME, clientName); final String token = settings.getProperty(PROPERTY_TOKEN, ""); settings.setProperty(PROPERTY_TOKEN, token); try { digest = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } public void setToken(String token) { setProperty(PROPERTY_TOKEN, token); } public String getToken() { return getProperty(PROPERTY_TOKEN); } public boolean hasToken() { String token = getProperty(PROPERTY_TOKEN); return token != null && !token.isEmpty(); } public void setURLPrefix(final String urlPrefix) { setProperty(PROPERTY_URL_PREFIX, urlPrefix); } public String getURLPrefix() { return getProperty(PROPERTY_URL_PREFIX); } public String getClientName() { return getProperty(PROPERTY_NAME); } public void setClientName(final String name) { setProperty(PROPERTY_NAME, name); } private static String getHostname() { String hostname = "localhost"; try { InetAddress address = InetAddress.getLocalHost(); hostname = address.getHostName(); } catch (UnknownHostException e) { e.printStackTrace(); } return hostname; } public String getProperty(String name) { return settings.getProperty(name); } public void setProperty(final String name, final String value) { settings.setProperty(name, value); } public Map<String, String> getRequestParams() { final Map<String, String> params = new HashMap<>(); final String uuid = settings.getProperty(PROPERTY_UUID); final String token = settings.getProperty(PROPERTY_TOKEN); String counter = settings.getProperty(PROPERTY_COUNTER, "0"); // System.out.println("counter=" + counter); counter = (Integer.parseInt(counter) + 1) + ""; settings.setProperty(PROPERTY_COUNTER, counter); String key = ""; if (token != null && token.length() == 8) { try { final String keyContent = uuid + "-" + token + "-" + counter; // System.out.println("keyContent=" + keyContent); byte[] hash = digest.digest((keyContent).getBytes("UTF-8")); final StringBuilder hexString = new StringBuilder(); for (byte b : hash) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } key = hexString.toString(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } params.put(PROPERTY_UUID, uuid); params.put(PROPERTY_COUNTER, counter); params.put(PROPERTY_KEY, key); return params; } public URL getRequestUrl(String service, Map<String, String> params) { final HashMap<String, String> reqParams = new HashMap<>(); reqParams.putAll(params); reqParams.putAll(getRequestParams()); String urlPrefix = settings.getProperty(PROPERTY_URL_PREFIX); StringBuilder builder = new StringBuilder(512); builder.append(urlPrefix); builder.append(service); builder.append("?"); boolean first = true; try { for (String key : reqParams.keySet()) { if (!first) { builder.append("&"); } first = false; final String value = reqParams.get(key); builder.append(URLEncoder.encode(key, "ISO-8859-1")); builder.append("="); builder.append(URLEncoder.encode(value, "ISO-8859-1")); } } catch (UnsupportedEncodingException e) { LOGGER.log(Level.SEVERE, "error building url", e); } URL url = null; try { url = new URL(builder.toString()); } catch (MalformedURLException e) { e.printStackTrace(); } return url; } public static String getUrlAsString(final URL url) throws IOException { final URLConnection connection = url.openConnection(); connection.setConnectTimeout(45000); connection.setReadTimeout(45000); final InputStream inputStream = connection.getInputStream(); final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); final BufferedReader in = new BufferedReader(inputStreamReader); final StringBuilder response = new StringBuilder(); String inputLine; while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); return response.toString(); } private static void setupHTTPS() { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { } }}; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { LOGGER.log(Level.INFO, "error installing trust manager", e); } HostnameVerifier hv = new HostnameVerifier() { @Override public boolean verify(String urlHostName, SSLSession session) { if (!session.getPeerHost().equals(urlHostName)) { LOGGER.warning("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost()); } return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(hv); } }