/*
* Copyright (c) 2010-2016, openHAB.org and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.habdroid.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.util.Base64;
import android.util.Log;
import com.caverock.androidsvg.SVG;
import com.caverock.androidsvg.SVGParseException;
import com.loopj.android.image.SmartImage;
import com.loopj.android.image.WebImageCache;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class MyWebImage implements SmartImage {
private static final int CONNECT_TIMEOUT = 5000;
private static final int READ_TIMEOUT = 10000;
private static WebImageCache webImageCache;
private String url;
private boolean useCache = true;
private String authUsername;
private String authPassword;
private boolean shouldAuth = false;
public MyWebImage(String url, String username, String password) {
this.url = url;
this.useCache = true;
this.setAuthentication(username, password);
}
public MyWebImage(String url, boolean useCache, String username, String password) {
this.url = url;
this.useCache = useCache;
this.setAuthentication(username, password);
}
public Bitmap getBitmap(Context context) {
// Don't leak context
if(webImageCache == null) {
webImageCache = new WebImageCache(context);
}
// Try getting bitmap from cache first
Bitmap bitmap = null;
if(url != null) {
if (this.useCache)
bitmap = webImageCache.get(url);
if(bitmap == null) {
Log.i("MyWebImage", "Cache for " + url + " is empty, getting image");
final String iconFormat = PreferenceManager.getDefaultSharedPreferences(context).getString("iconFormatType","PNG");
bitmap = getBitmapFromUrl(context, url, iconFormat);
if(bitmap != null && this.useCache) {
webImageCache.put(url, bitmap);
}
}
}
return bitmap;
}
private Bitmap getBitmapFromUrl(Context context, String url, String iconFormat) {
Bitmap bitmap = null;
String encodedUserPassword = null;
if (shouldAuth)
try {
String userPassword = this.authUsername + ":" + this.authPassword;
encodedUserPassword = Base64.encodeToString(userPassword.getBytes("UTF-8"), Base64.NO_WRAP);
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (url.startsWith("https")) {
try {
HttpsURLConnection.setDefaultHostnameVerifier(getHostnameVerifier());
HttpsURLConnection conn = (HttpsURLConnection) new URL(url).openConnection();
conn.setSSLSocketFactory(getSSLSocketFactory(context));
conn.setConnectTimeout(CONNECT_TIMEOUT);
conn.setReadTimeout(READ_TIMEOUT);
if (this.shouldAuth)
conn.setRequestProperty("Authorization", "Basic " + encodedUserPassword);
int responseCode = conn.getResponseCode();
if (responseCode >= 400) {
throw new Exception("Bad https response status: " + responseCode);
}
else {
InputStream is = (InputStream) conn.getContent();
bitmap = getBitmapFromInputStream(iconFormat, is); }
} catch(Exception e) {
e.printStackTrace();
}
} else {
try {
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);
conn.setReadTimeout(READ_TIMEOUT);
if (this.shouldAuth)
conn.setRequestProperty("Authorization", "Basic " + encodedUserPassword);
int responseCode = conn.getResponseCode();
if (responseCode >= 400) {
throw new Exception("Bad http response status: " + responseCode);
}
else {
InputStream is = (InputStream) conn.getContent();
bitmap = getBitmapFromInputStream(iconFormat, is); }
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmap;
}
private Bitmap getBitmapFromInputStream(String iconFormat, InputStream is) {
Bitmap bitmap;
if("SVG".equals(iconFormat)) {
bitmap = getBitmapFromSvgInputstream(is);
}else {
bitmap = BitmapFactory.decodeStream(is);
}
return bitmap;
}
private Bitmap getBitmapFromSvgInputstream(InputStream is) {
Bitmap bitmap = null;
try {
SVG svg = SVG.getFromInputStream(is);
double width = svg.getDocumentViewBox().width();
double height = svg.getDocumentViewBox().height();
bitmap = Bitmap.createBitmap((int) Math.ceil(width), (int) Math.ceil(height), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//drawARGB(0,0,0,0);//drawRGB(255, 255, 255);
svg.renderToCanvas(canvas);
} catch (SVGParseException e) {
e.printStackTrace();
}
return bitmap;
}
public static void removeFromCache(String url) {
if(webImageCache != null) {
webImageCache.remove(url);
}
}
public SSLSocketFactory getSSLSocketFactory(Context context) {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted( final X509Certificate[] chain, final String authType ) {
}
@Override
public void checkServerTrusted( final X509Certificate[] chain, final String authType ) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} };
// Install the all-trusting trust manager
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance( "SSL" );
sslContext.init(MyKeyManager.getInstance(context), trustAllCerts, new java.security.SecureRandom() );
// Create an ssl socket factory with our all-trusting manager
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
return sslSocketFactory;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public HostnameVerifier getHostnameVerifier() {
HostnameVerifier allHostsValid = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
return allHostsValid;
}
public void setAuthentication(String username, String password) {
this.authUsername = username;
this.authPassword = password;
if (this.authUsername != null && (this.authUsername.length() > 0 && this.authPassword.length() > 0))
this.shouldAuth = true;
}
}