package org.researchstack.backbone.storage.file; import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.WorkerThread; import org.researchstack.backbone.storage.file.aes.Encrypter; import org.researchstack.backbone.utils.FileUtils; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.GeneralSecurityException; /** * This class is a simple implementation of FileAccess that passes all data read/written through the * encrypter for encryption/decryption. An encrypter such as {@link UnencryptedProvider} can be used * to write unencrypted data instead. */ public class SimpleFileAccess implements FileAccess { private Encrypter encrypter; @Override @WorkerThread public void writeData(Context context, String path, byte[] data) { try { File localFile = findLocalFile(context, path); FileUtils.makeParent(localFile); FileUtils.writeSafe(localFile, encrypter.encrypt(data)); } catch (GeneralSecurityException e) { throw new StorageAccessException(e); } } @Override @WorkerThread public byte[] readData(Context context, String path) { try { File localFile = findLocalFile(context, path); return encrypter.decrypt(FileUtils.readAll(localFile)); } catch (IOException | GeneralSecurityException e) { throw new StorageAccessException(e); } } @Override public void moveData(Context context, String fromPath, String toPath) { File from = findLocalFile(context, fromPath); File to = findLocalFile(context, toPath); FileUtils.makeParent(to); try { FileUtils.copy(new FileInputStream(from), to); } catch (IOException e) { throw new RuntimeException(e); } if (!from.delete()) { throw new RuntimeException("Failed to delete temp file"); } } @NonNull private File findLocalFile(Context context, String path) { checkPath(path); return new File(context.getFilesDir() + path); } @Override @WorkerThread public boolean dataExists(Context context, String path) { return findLocalFile(context, path).exists(); } @Override public void clearData(Context context, String path) { File localFile = findLocalFile(context, path); localFile.delete(); } @Override public void setEncrypter(Encrypter encrypter) { this.encrypter = encrypter; } public void checkPath(String path) { if (!path.startsWith("/")) { throw new StorageAccessException("Path must be absolute (ie start with '/')"); } } }