package com.lechucksoftware.proxy.proxysettings.utils;
import android.annotation.TargetApi;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Parcelable;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.google.gson.Gson;
import com.lechucksoftware.proxy.proxysettings.App;
import com.lechucksoftware.proxy.proxysettings.BuildConfig;
import com.lechucksoftware.proxy.proxysettings.R;
import com.lechucksoftware.proxy.proxysettings.constants.AndroidMarket;
import com.lechucksoftware.proxy.proxysettings.constants.Constants;
import com.lechucksoftware.proxy.proxysettings.db.ProxyEntity;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Stack;
import be.shouldit.proxy.lib.APL;
import be.shouldit.proxy.lib.utils.HttpAnswer;
import be.shouldit.proxy.lib.utils.ProxyUtils;
import timber.log.Timber;
public class Utils
{
public static final String HTTP_FREEGEOIP_NET_JSON_STRING = "http://freegeoip.net/json/";
// TODO: add fallback on telize
public static final String HTTP_TELIZE_NET_JSON_STRING = "http://www.telize.com/geoip/";
public static String TAG = Utils.class.getSimpleName();
public static String BASE_ASSETS = "file:///android_asset/";
public static String getProxyCountryCode(ProxyEntity proxy) throws Exception
{
String result = null;
String host = proxy.getHost();
InetAddress ia = null;
try
{
InetAddress ad = InetAddress.getByName(host);
byte[] ip = ad.getAddress();
ia = InetAddress.getByAddress(ip);
}
catch (UnknownHostException e)
{
Timber.e(e.getMessage());
}
if (ia != null && ia.isSiteLocalAddress())
{
result = "PRIVATE";
}
else
{
String stringUrl = (HTTP_FREEGEOIP_NET_JSON_STRING + host).trim();
result = getProxyCountryCode(stringUrl, proxy);
if (TextUtils.isEmpty(result))
{
stringUrl = (HTTP_TELIZE_NET_JSON_STRING + host).trim();
result = getProxyCountryCode(stringUrl, proxy);
}
}
return result;
}
private static String getProxyCountryCode(String requestUrl, ProxyEntity proxy) throws JSONException
{
URI uri = null;
int timeout = 1000 * 60;
HttpAnswer answer = null;
String result = null;
try
{
Uri parsedUri = Uri.parse(requestUrl);
if (parsedUri != null)
{
String parsedUriString = parsedUri.toString();
uri = new URI(parsedUriString);
}
}
catch (URISyntaxException e)
{
Timber.e(e, "Exception parsing URI on getProxyCountryCode");
}
if (uri != null)
{
try
{
Proxy proxyConf = APL.getProxySelectorConfiguration(uri);
answer = ProxyUtils.getHttpAnswerURI(uri,proxyConf, 10000, timeout);
}
catch (Exception e)
{
Timber.w("Exception on getProxyCountryCode: " + e.toString());
}
if (answer != null)
{
String answerBody = answer.getBody();
//ONLY FOR DEBUG EXCEPTION HANDLING IN CASE OF WRONG ANSWER FROM THE SERVER
// answerBody = "</pre><span style=\"height: 20px; width: 40px; min-height: 20px; min-width: 40px; position: absolute; opacity: 0.85; z-index: 8675309; display: none; cursor: pointer; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAUCAYAAAD/Rn+7AAADU0lEQVR42s2WXUhTYRjHz0VEVPRFUGmtVEaFUZFhHxBhsotCU5JwBWEf1EWEEVHQx4UfFWYkFa2biPJiXbUta33OXFtuUXMzJ4bK3Nqay7m5NeZq6h/tPQ+xU20zugjOxR/+7/O8539+5znnwMtNTExwJtMb3L/fiLv3botCSmUjeCaejTOb39AiFothfHxcFIrHY8RksZjBsckJcOIRMfFsHD/SsbExUYpnI8DR0dGUGjSb0byhEJp5Uqg5CTSzc2CQleJbMEj9/ywBcGRkJEk9DQqouEVQT1sK444yWI9UonmTjGqauVLEIlHa9x8lAMbj8SSpp0rwKGMVvg8P46vbg0C7na8z8JsMcgHe7jlEa+edRhiLy8n/TUMfu6EvLElk+U0WtGwrTrdfAGQf5J8iiK4LVzDU28t8JtMSocf8E+l68myaNFXm/6rXslLK7ay5TOunuRvZWpJuvwAYjUaTpOIWoquuAZ219RTaxKYp9BbjycoN5FvL9qH9TBX5rvoGdJythvXYSTxdtRnWylO/ZdqrLsGwszzhWQ593z2KlAwCYCQSSZJ6ehZ0W7bD9VBLgN0NCqr3qR7R2rBrL3pu3Sb/7nDlz2uy6cG0OXk0GTbZXzNp8trsPAQdTj6frlWzN2DcXZGKQQAMh8NJ6rpyHe+PnkCr/CAFdZyvpfpjuvkifLF9wIt1Wwlo0OHie1RvWrKa93RjzfzliTzPKz3ltB0/Tevmwp14wGUgHAzSOoUEwFAolFaaBSuhnslPRkJexUJtZ6v5HtUeLswl33n1BgEY5fvhs9sJ3FAiT+QYyyvoAQJuD0KBAFRTJNAuz5/s3gJgMBhMJwrVFRThM5tY5zUF/A4X1f2fvQTRLCuBreoim0YmAbqNJryvPEXeeq46kaNdkQ/1HCncbJKPs9ZSv2VHGfWsZ2hfkhKAfr8/pdxWKx4wwD69PmVfNSOL+lr2w+gYqHpWDtXt1xQ8AMlWU0e1lqLd/APRHoP8AJqWrQG9gYxcPMsvSJUvAA4MDKTUJ7MZLaVy8v+qT21tcDx/OemePr0RTkNrur4A6PP5xCgBsL+/X4wiQDpuuVxOeL1eMYmYeDY6sOp0z+B0OuHxeEQhxkJMFosJiSO/UinOI/8Pc+l7KKArAT8AAAAASUVORK5CYII=);\"></span><span id=\"buffer-extension-hover-button\" style=\"display: none;position: absolute;z-index: 8675309;width: 100px;height: 25px;background-image: url(chrome-extension://noojglkidnpfjbincgijbaiedldjfbhh/data/shared/img/buffer-hover-icon@1x.png);background-size: 100px 25px;opacity: 0.9;cursor: pointer;\"></span></body>";
if (answer.getStatus() == HttpURLConnection.HTTP_OK && !TextUtils.isEmpty(answerBody))
{
JSONObject jsonObject = null;
try
{
jsonObject = new JSONObject(answerBody);
}
catch (JSONException e)
{
//It's a common error to receive wrong answers due to the proxy servers
//between the Android device that make the request and the geoIP services
Timber.e("%s reading string: '%s'", e.toString(), answerBody);
}
catch (Exception e)
{
Timber.e(e,"Unhandled exception parsing JSON answer: '%s'",answerBody);
}
if (jsonObject != null && jsonObject.has("country_code"))
{
result = jsonObject.getString("country_code");
}
}
}
}
return result;
}
public static String getAppVersionName(Context ctx)
{
PackageInfo pi = Utils.getAppInfo(ctx);
String appVersionName;
if (pi != null)
{
appVersionName = ctx.getString(R.string.app_versionname, pi.versionName, pi.versionCode);
}
else
{
appVersionName = "";
}
return appVersionName;
}
public static PackageInfo getAppInfo(Context ctx)
{
PackageInfo pInfo = null;
try
{
pInfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
}
catch (PackageManager.NameNotFoundException e)
{
Timber.e(e,"Exception on getAppInfo");
}
return pInfo;
}
public static void startMarketActivity(Context ctx)
{
Uri marketUri = getMarketUri(App.getInstance().activeMarket);
boolean marketShown = false;
try
{
ctx.startActivity(new Intent(Intent.ACTION_VIEW, marketUri));
marketShown = true;
}
catch (Exception e)
{
Timber.e(e,"Exception starting Market activity: '%s",marketUri.toString());
}
if (!marketShown)
{
Toast.makeText(ctx, R.string.market_not_found, Toast.LENGTH_SHORT).show();
}
}
public static Uri getMarketUri(AndroidMarket market)
{
switch (market)
{
case AMAZON:
return Constants.AMAZON_MARKET_URL;
case PLAY:
return Constants.PLAY_MARKET_URL;
default:
return null;
}
}
public static AndroidMarket getInstallerMarket(Context ctx)
{
AndroidMarket res = null;
if (BuildConfig.MARKET_URI != null)
{
if (BuildConfig.MARKET_URI.equals(Constants.PLAY_MARKET_PACKAGE))
{
res = AndroidMarket.PLAY;
}
else if (BuildConfig.MARKET_URI.equals(Constants.AMAZON_MARKET_PACKAGE))
{
res = AndroidMarket.AMAZON;
}
}
if (res == null)
{
res = AndroidMarket.OTHER;
if (BuildConfig.DEBUG)
{
res = AndroidMarket.PLAY;
Timber.d("Enabling Play market because during debug the InstallerPackageName is not filled: '%s'", BuildConfig.MARKET_URI);
}
else
{
Timber.e(new Exception(),"Got a not recognizable InstallerPackageName: '%s' ",BuildConfig.MARKET_URI);
}
}
return res;
}
public static void setHTTPAuthentication(final String user, final String password)
{
Authenticator.setDefault(new Authenticator()
{
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user, password.toCharArray());
}
});
}
public static String getFullAsset(Context ctx, String filename)
{
String text = null;
InputStream inputStream = null;
try
{
inputStream = ctx.getAssets().open(filename);
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String aux;
while ((aux = br.readLine()) != null)
{
builder.append(aux);
}
text = builder.toString();
}
catch (Exception e)
{
Timber.e(e, "Exception getting Full Asset");
}
return text;
}
public static void checkDemoMode(Context ctx)
{
SharedPreferences prefs = ctx.getSharedPreferences(Constants.PREFERENCES_FILENAME, Context.MODE_MULTI_PROCESS);
if (prefs.getBoolean(Constants.PREFERENCES_DEMO_MODE, false))
{
App.getInstance().demoMode = true;
}
else
{
App.getInstance().demoMode = false;
}
}
public static void setDemoMode(Context ctx, boolean enabled)
{
SharedPreferences prefs = ctx.getSharedPreferences(Constants.PREFERENCES_FILENAME, Context.MODE_MULTI_PROCESS);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(Constants.PREFERENCES_DEMO_MODE, enabled);
editor.commit();
}
public static boolean ElapsedNDays(Date date, int days)
{
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, days);
if (System.currentTimeMillis() >= c.getTime().getTime())
{
return true;
}
else
{
return false;
}
}
public static Intent createEmailOnlyChooserIntent(Context context, Intent source, CharSequence chooserTitle)
{
Stack<Intent> intents = new Stack<Intent>();
Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", "info@domain.com", null));
List<ResolveInfo> activities = context.getPackageManager().queryIntentActivities(i, 0);
for (ResolveInfo ri : activities)
{
Intent target = new Intent(source);
target.setPackage(ri.activityInfo.packageName);
intents.add(target);
}
if (!intents.isEmpty())
{
Intent chooserIntent = Intent.createChooser(intents.remove(0), chooserTitle);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[intents.size()]));
return chooserIntent;
}
else
{
return Intent.createChooser(source, chooserTitle);
}
}
public static void sendFeedbackMail(Context context)
{
/* Create the Intent */
final Intent emailIntent = new Intent(Intent.ACTION_SEND);
/* Fill it with Data */
emailIntent.setType("message/rfc822");
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"info@shouldit.be"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.mail_feedback_subject, getAppInfo(context).versionName));
emailIntent.putExtra(Intent.EXTRA_TEXT, "");
/* Send it off to the Activity-Chooser */
try
{
context.startActivity(createEmailOnlyChooserIntent(context, emailIntent, "Send us an email..."));
}
catch (ActivityNotFoundException ex)
{
Toast.makeText(context, R.string.no_email_client_installed, Toast.LENGTH_SHORT).show();
}
catch (Exception e)
{
Timber.e(e,"Unhandled exception starting email client activity");
}
}
public static Object cloneThroughJson(Object t)
{
App.getTraceUtils().startTrace(TAG,"cloneThroughJson", Log.DEBUG);
Gson gson = new Gson();
String json = gson.toJson(t);
Object result = gson.fromJson(json, t.getClass());
App.getTraceUtils().stopTrace(TAG,"cloneThroughJson", Log.DEBUG);
return result;
}
public static boolean airplaneModeEnabled(Context context)
{
boolean result = false;
try
{
result = isAirplaneModeOn(context);
}
catch (Exception e)
{
Timber.e(e,"Exception getting airplaneModeEnabled");
}
return result;
}
/**
* Gets the state of Airplane Mode.
*
* @param context
* @return true if enabled.
*/
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static boolean isAirplaneModeOn(Context context)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
{
return Settings.System.getInt(context.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) != 0;
}
else
{
return Settings.Global.getInt(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
}
}