com.aegiswallet.utils.BasicUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.aegiswallet.utils.BasicUtils.java

Source

/*
 * Aegis Bitcoin Wallet - The secure Bitcoin wallet for Android
 * Copyright 2014 Bojan Simic and specularX.co, designed by Reuven Yamrom
 *
 * This program 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.aegiswallet.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

import com.aegiswallet.R;
import com.aegiswallet.objects.SMSTransactionPojo;
import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.AddressFormatException;
import com.google.bitcoin.core.NetworkParameters;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Nonnull;

import edu.vt.middleware.dictionary.ArrayWordList;
import edu.vt.middleware.dictionary.WordListDictionary;
import edu.vt.middleware.dictionary.WordLists;
import edu.vt.middleware.dictionary.sort.ArraysSort;
import edu.vt.middleware.password.DictionarySubstringRule;
import edu.vt.middleware.password.Password;
import edu.vt.middleware.password.PasswordData;
import edu.vt.middleware.password.PasswordValidator;
import edu.vt.middleware.password.Rule;
import edu.vt.middleware.password.RuleResult;

public class BasicUtils {

    private static SecureRandom random = new SecureRandom();

    public static final String TAG = "BasicUtils";
    public static final BigInteger ONE_BTC = new BigInteger("100000000", 10);
    public static final BigInteger ONE_MBTC = new BigInteger("100000", 10);
    private static final int ONE_BTC_INT = ONE_BTC.intValue();
    private static final int ONE_MBTC_INT = ONE_MBTC.intValue();
    private final static QRCodeWriter qrCodeWriter = new QRCodeWriter();

    public static String satoshiToBTC(BigInteger value) {
        return formatValue(value, "", "-", Constants.BTC_MIN_PRECISION, 0);
    }

    public static String formatValue(@Nonnull final BigInteger value, final int precision, final int shift) {
        return formatValue(value, "", "-", precision, shift);
    }

    public static String formatValue(@Nonnull final BigInteger value, @Nonnull final String plusSign,
            @Nonnull final String minusSign, final int precision, final int shift) {
        long longValue = value.longValue();

        final String sign = longValue < 0 ? minusSign : plusSign;

        if (shift == 0) {
            if (precision == 2)
                longValue = longValue - longValue % 1000000 + longValue % 1000000 / 500000 * 1000000;
            else if (precision == 4)
                longValue = longValue - longValue % 10000 + longValue % 10000 / 5000 * 10000;
            else if (precision == 6)
                longValue = longValue - longValue % 100 + longValue % 100 / 50 * 100;
            else if (precision == 8)
                ;
            else
                throw new IllegalArgumentException("cannot handle precision/shift: " + precision + "/" + shift);

            final long absValue = Math.abs(longValue);
            final long coins = absValue / ONE_BTC_INT;
            final int satoshis = (int) (absValue % ONE_BTC_INT);

            if (satoshis % 1000000 == 0)
                return String.format(Locale.US, "%s%d.%02d", sign, coins, satoshis / 1000000);
            else if (satoshis % 10000 == 0)
                return String.format(Locale.US, "%s%d.%04d", sign, coins, satoshis / 10000);
            else if (satoshis % 100 == 0)
                return String.format(Locale.US, "%s%d.%06d", sign, coins, satoshis / 100);
            else
                return String.format(Locale.US, "%s%d.%08d", sign, coins, satoshis);
        } else if (shift == 3) {
            if (precision == 2)
                longValue = longValue - longValue % 1000 + longValue % 1000 / 500 * 1000;
            else if (precision == 4)
                longValue = longValue - longValue % 10 + longValue % 10 / 5 * 10;
            else if (precision == 5)
                ;
            else
                throw new IllegalArgumentException("cannot handle precision/shift: " + precision + "/" + shift);

            final long absValue = Math.abs(longValue);
            final long coins = absValue / ONE_MBTC_INT;
            final int satoshis = (int) (absValue % ONE_MBTC_INT);

            if (satoshis % 1000 == 0)
                return String.format(Locale.US, "%s%d.%02d", sign, coins, satoshis / 1000);
            else if (satoshis % 10 == 0)
                return String.format(Locale.US, "%s%d.%04d", sign, coins, satoshis / 10);
            else
                return String.format(Locale.US, "%s%d.%05d", sign, coins, satoshis);
        } else {
            throw new IllegalArgumentException("cannot handle shift: " + shift);
        }
    }

    public static BigInteger toNanoCoins(final String value, final int shift) {

        try {
            final BigInteger nanoCoins = new BigDecimal(value).movePointRight(8 - shift).toBigIntegerExact();

            if (nanoCoins.signum() < 0)
                throw new IllegalArgumentException("negative amount: " + value);
            if (nanoCoins.compareTo(NetworkParameters.MAX_MONEY) > 0)
                Log.e(TAG, "AMOUNT TOO LARGE");

            return nanoCoins;
        } catch (ArithmeticException e) {
            Log.d(TAG, e.getMessage());
            return BigInteger.ZERO;
        }
    }

    public static Bitmap encodeAsBitmap(String contents, BarcodeFormat format, int dimension) {

        Bitmap bitmap = null;

        try {
            final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
            //hints.put(EncodeHintType.MARGIN, 0);
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            final BitMatrix result = qrCodeWriter.encode(contents, BarcodeFormat.QR_CODE, dimension, dimension,
                    hints);

            final int width = result.getWidth();
            final int height = result.getHeight();
            final int[] pixels = new int[width * height];

            for (int y = 0; y < height; y++) {
                final int offset = y * width;
                for (int x = 0; x < width; x++) {
                    pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
                }
            }

            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
            return bitmap;

        } catch (WriterException e) {
            Log.e("Basic Utils", "cannot write to bitmap " + e.getMessage());
        }
        return bitmap;
    }

    private static String guessAppropriateEncoding(CharSequence contents) {
        for (int i = 0; i < contents.length(); i++) {
            if (contents.charAt(i) > 0xFF) {
                return "UTF-8";
            }
        }
        return null;
    }

    public static JSONObject parseJSONData(Context context, String fileName) {
        String JSONString = null;
        JSONObject JSONObject = null;
        try {

            //open the inputStream to the file
            InputStream inputStream = context.openFileInput(fileName);

            int sizeOfJSONFile = inputStream.available();

            //array that will store all the data
            byte[] bytes = new byte[sizeOfJSONFile];

            //reading data into the array from the file
            inputStream.read(bytes);

            //close the input stream
            inputStream.close();

            JSONString = new String(bytes, "UTF-8");
            JSONObject = new JSONObject(JSONString);

        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        } catch (JSONException x) {
            return null;
        }
        return JSONObject;
    }

    public static String generateSecureKey() {
        return new BigInteger(512, random).toString(32);
    }

    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
    }

    public static Typeface getCustomTypeFace(Context context) {
        Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/regular.otf");

        return tf;
    }

    public static String[] loadFileList() {

        String[] fileList = null;
        File filesPath = Constants.WALLET_BACKUP_DIRECTORY;

        if (Constants.WALLET_BACKUP_DIRECTORY.exists() && Constants.WALLET_BACKUP_DIRECTORY.isDirectory()) {
            final String filePrefix = "AegisWalletBackup";
            try {
                filesPath.mkdirs();
            } catch (SecurityException e) {
                Log.e(TAG, "Could not write to SD card - " + e.toString());
            }
            if (filesPath.exists()) {
                FilenameFilter filter = new FilenameFilter() {
                    public boolean accept(File dir, String filename) {
                        File sel = new File(dir, filename);
                        return filename.contains(filePrefix) || sel.isDirectory();
                    }
                };
                fileList = filesPath.list(filter);
            } else {
                fileList = new String[0];
            }
        }

        return fileList;
    }

    public static String getNFCErrorMessage(Context context, String writeMessage) {
        String result = null;

        Resources resources = context.getResources();

        if (writeMessage.equals(Constants.NFC_TAG_TOO_SMALL)) {
            result = resources.getString(R.string.nfc_error_tag_too_small);
        } else if (writeMessage.equals(Constants.NFC_READ_ONLY)) {
            result = resources.getString(R.string.nfc_error_tag_read_only);
        } else if (writeMessage.equals(Constants.NFC_CANT_CONNECT)) {
            result = resources.getString(R.string.nfc_error_tag_cant_connect);
        } else if (writeMessage.equals(Constants.NFC_CANT_FORMAT)) {
            result = resources.getString(R.string.nfc_error_tag_cant_format);
        } else if (writeMessage.equals(Constants.NFC_TAG_NOT_SUPPORTED)) {
            result = resources.getString(R.string.nfc_error_tag_not_supported);
        } else if (writeMessage.equals(Constants.NFC_WRITE_EXCEPTION)) {
            result = resources.getString(R.string.nfc_error_tag_write_exception);
        }

        return result;
    }

    public static boolean isPasswordInDictionary(Context context, String password) {
        boolean resultBool = false;

        if (password == null)
            return false;

        try {

            AssetFileDescriptor descriptor = context.getAssets().openFd("commonpasswords.xmf");
            FileReader reader = new FileReader(descriptor.getFileDescriptor());

            // create a case sensitive word list and sort it
            ArrayWordList awl = WordLists.createFromReader(new FileReader[] { reader }, true, new ArraysSort());

            WordListDictionary dict = new WordListDictionary(awl);

            DictionarySubstringRule dictRule = new DictionarySubstringRule(dict);
            dictRule.setWordLength(6); // size of words to check in the password
            dictRule.setMatchBackwards(true); // match dictionary words backwards

            List<Rule> ruleList = new ArrayList<Rule>();
            ruleList.add(dictRule);

            PasswordValidator validator = new PasswordValidator(ruleList);
            PasswordData passwordData = new PasswordData(new Password(password.toLowerCase()));

            RuleResult result = validator.validate(passwordData);
            if (result.isValid()) {
                Log.d(TAG, "Valid password");
                resultBool = true;
            } else {
                Log.d(TAG, "Invalid password");
            }
        } catch (FileNotFoundException e) {
            Log.d(TAG, e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, e.getMessage());
        }

        return resultBool;
    }

    public static String getAddressFromMessage(String message) {
        String address = null;

        String[] splitString = message.split(" ");
        for (String s : splitString) {
            try {
                Address a = new Address(Constants.NETWORK_PARAMETERS, s);
                if (a != null) {
                    return a.toString();
                }
            } catch (AddressFormatException e) {
                continue;
            }

        }

        return address;
    }

    public static String findKeyInPrefs(SharedPreferences prefs, String value) {
        for (Map.Entry<String, ?> entry : prefs.getAll().entrySet()) {
            if (value.equals(entry.getValue())) {
                return entry.getKey();
            }
        }
        return null; // not found
    }

    public static ArrayList<SMSTransactionPojo> getAllPendingTransactions(SharedPreferences prefs) {
        ArrayList<SMSTransactionPojo> list = new ArrayList<SMSTransactionPojo>();

        for (Map.Entry<String, ?> entry : prefs.getAll().entrySet()) {
            SMSTransactionPojo pojo = new SMSTransactionPojo(entry.getValue() + "");
            list.add(pojo);
        }
        return list;
    }

    public static ArrayList<SMSTransactionPojo> getAllRespondedSMSTransactions(SharedPreferences prefs) {
        ArrayList<SMSTransactionPojo> list = new ArrayList<SMSTransactionPojo>();

        for (Map.Entry<String, ?> entry : prefs.getAll().entrySet()) {
            SMSTransactionPojo pojo = new SMSTransactionPojo(entry.getValue() + "");
            if (pojo.getStatus() == Constants.SMS_STATUS_REC) {
                list.add(pojo);
            }
        }
        return list;
    }

    public static ArrayList<SMSTransactionPojo> getAllNotRespondedSMSTransactions(SharedPreferences prefs) {
        ArrayList<SMSTransactionPojo> list = new ArrayList<SMSTransactionPojo>();

        for (Map.Entry<String, ?> entry : prefs.getAll().entrySet()) {
            SMSTransactionPojo pojo = new SMSTransactionPojo(entry.getValue() + "");
            if (pojo.getStatus() == Constants.SMS_STATUS_INIT) {
                list.add(pojo);
            }
        }
        return list;
    }
}