AbstractConnectionManager.java

  1package eu.siacs.conversations.services;
  2
  3import android.content.Context;
  4import android.os.PowerManager;
  5import android.os.SystemClock;
  6import android.util.Log;
  7
  8import org.bouncycastle.crypto.engines.AESEngine;
  9import org.bouncycastle.crypto.io.CipherInputStream;
 10import org.bouncycastle.crypto.io.CipherOutputStream;
 11import org.bouncycastle.crypto.modes.AEADBlockCipher;
 12import org.bouncycastle.crypto.modes.GCMBlockCipher;
 13import org.bouncycastle.crypto.params.AEADParameters;
 14import org.bouncycastle.crypto.params.KeyParameter;
 15
 16import java.io.FileNotFoundException;
 17import java.io.FileOutputStream;
 18import java.io.InputStream;
 19import java.io.OutputStream;
 20import java.security.InvalidAlgorithmParameterException;
 21import java.security.InvalidKeyException;
 22import java.security.NoSuchAlgorithmException;
 23import java.security.NoSuchProviderException;
 24import java.util.concurrent.atomic.AtomicLong;
 25
 26import javax.crypto.NoSuchPaddingException;
 27
 28import eu.siacs.conversations.Config;
 29import eu.siacs.conversations.R;
 30import eu.siacs.conversations.entities.DownloadableFile;
 31import eu.siacs.conversations.utils.Compatibility;
 32
 33public class AbstractConnectionManager {
 34
 35    private static final int UI_REFRESH_THRESHOLD = 250;
 36    private static final AtomicLong LAST_UI_UPDATE_CALL = new AtomicLong(0);
 37    protected XmppConnectionService mXmppConnectionService;
 38
 39    public AbstractConnectionManager(XmppConnectionService service) {
 40        this.mXmppConnectionService = service;
 41    }
 42
 43    public static InputStream upgrade(DownloadableFile file, InputStream is) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, NoSuchProviderException {
 44        if (file.getKey() != null && file.getIv() != null) {
 45            AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine());
 46            cipher.init(true, new AEADParameters(new KeyParameter(file.getKey()), 128, file.getIv()));
 47            return new CipherInputStream(is, cipher);
 48        } else {
 49            return is;
 50        }
 51    }
 52
 53    public static OutputStream createOutputStream(DownloadableFile file, boolean append, boolean decrypt) {
 54        FileOutputStream os;
 55        try {
 56            os = new FileOutputStream(file, append);
 57            if (file.getKey() == null || !decrypt) {
 58                return os;
 59            }
 60        } catch (FileNotFoundException e) {
 61            Log.d(Config.LOGTAG, "unable to create output stream", e);
 62            return null;
 63        }
 64        try {
 65            AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine());
 66            cipher.init(false, new AEADParameters(new KeyParameter(file.getKey()), 128, file.getIv()));
 67            return new CipherOutputStream(os, cipher);
 68        } catch (Exception e) {
 69            Log.d(Config.LOGTAG, "unable to create cipher output stream", e);
 70            return null;
 71        }
 72    }
 73
 74    public XmppConnectionService getXmppConnectionService() {
 75        return this.mXmppConnectionService;
 76    }
 77
 78    public long getAutoAcceptFileSize() {
 79        return this.mXmppConnectionService.getLongPreference("auto_accept_file_size", R.integer.auto_accept_filesize);
 80    }
 81
 82    public boolean hasStoragePermission() {
 83        return Compatibility.hasStoragePermission(mXmppConnectionService);
 84    }
 85
 86    public void updateConversationUi(boolean force) {
 87        synchronized (LAST_UI_UPDATE_CALL) {
 88            if (force || SystemClock.elapsedRealtime() - LAST_UI_UPDATE_CALL.get() >= UI_REFRESH_THRESHOLD) {
 89                LAST_UI_UPDATE_CALL.set(SystemClock.elapsedRealtime());
 90                mXmppConnectionService.updateConversationUi();
 91            }
 92        }
 93    }
 94
 95    public PowerManager.WakeLock createWakeLock(String name) {
 96        PowerManager powerManager = (PowerManager) mXmppConnectionService.getSystemService(Context.POWER_SERVICE);
 97        return powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
 98    }
 99
100    public static class Extension {
101        public final String main;
102        public final String secondary;
103
104        private Extension(String main, String secondary) {
105            this.main = main;
106            this.secondary = secondary;
107        }
108
109        public static Extension of(String path) {
110            final int pos = path.lastIndexOf('/');
111            final String filename = path.substring(pos + 1).toLowerCase();
112            final String[] parts = filename.split("\\.");
113            final String main = parts.length >= 2 ? parts[parts.length - 1] : null;
114            final String secondary = parts.length >= 3 ? parts[parts.length - 2] : null;
115            return new Extension(main, secondary);
116        }
117    }
118}