Fix backup create if not encrypted, Move more strings to strings.xml

This commit is contained in:
MrLetsplay 2023-10-03 20:54:29 +02:00
parent abe74d8315
commit 4ffd39596b
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
12 changed files with 74 additions and 34 deletions

View File

@ -107,7 +107,7 @@ public class MainActivity extends BaseActivity {
InputImage image = InputImage.fromFilePath(this, img); InputImage image = InputImage.fromFilePath(this, img);
qrScanner.scan(image, code -> { qrScanner.scan(image, code -> {
if(code == null) { if(code == null) {
DialogUtil.showErrorDialog(this, "No codes were detected in the provided image"); DialogUtil.showErrorDialog(this, getString(R.string.error_qr_scan_not_detected));
return; return;
} }
@ -126,9 +126,9 @@ public class MainActivity extends BaseActivity {
for (OTPData dt : code.getOTPs()) frag.addOTP(dt); for (OTPData dt : code.getOTPs()) frag.addOTP(dt);
} }
} }
}, error -> DialogUtil.showErrorDialog(this, "Failed to detect code: " + error)); }, error -> DialogUtil.showErrorDialog(this, getString(R.string.error_qr_scan_failed), error, null));
} catch (IOException e) { } catch (IOException e) {
DialogUtil.showErrorDialog(this, "Failed to read image: " + e); DialogUtil.showErrorDialog(this, getString(R.string.error_qr_scan_image_failed), e);
} }
}); });
@ -172,7 +172,7 @@ public class MainActivity extends BaseActivity {
AlertDialog dialog = new StyledDialogBuilder(this) AlertDialog dialog = new StyledDialogBuilder(this)
.setTitle("Icon pack already exists") .setTitle(R.string.icon_pack_exists_title)
.setView(binding.getRoot()) .setView(binding.getRoot())
.setNeutralButton(R.string.cancel, (d, which) -> {}) .setNeutralButton(R.string.cancel, (d, which) -> {})
.create(); .create();
@ -184,7 +184,7 @@ public class MainActivity extends BaseActivity {
IconUtil.importIconPack(this, doc); IconUtil.importIconPack(this, doc);
Toast.makeText(this, getString(R.string.icon_pack_imported, meta.getIcons().length), Toast.LENGTH_LONG).show(); Toast.makeText(this, getString(R.string.icon_pack_imported, meta.getIcons().length), Toast.LENGTH_LONG).show();
} catch (IconPackException e) { } catch (IconPackException e) {
DialogUtil.showErrorDialog(this, "Failed to import icon pack", e); DialogUtil.showErrorDialog(this, getString(R.string.error_import_icon_pack), e);
} }
break; break;
case 1: // Rename existing case 1: // Rename existing
@ -193,7 +193,7 @@ public class MainActivity extends BaseActivity {
IconUtil.importIconPack(this, doc); IconUtil.importIconPack(this, doc);
Toast.makeText(this, getString(R.string.icon_pack_imported, meta.getIcons().length), Toast.LENGTH_LONG).show(); Toast.makeText(this, getString(R.string.icon_pack_imported, meta.getIcons().length), Toast.LENGTH_LONG).show();
} catch (IconPackException e) { } catch (IconPackException e) {
DialogUtil.showErrorDialog(this, "Failed to import icon pack", e); DialogUtil.showErrorDialog(this, getString(R.string.error_import_icon_pack), e);
} }
break; break;
case 2: // Rename imported case 2: // Rename imported
@ -201,7 +201,7 @@ public class MainActivity extends BaseActivity {
IconUtil.importIconPack(this, doc, meta.getName() + " (" + meta.getVersion() + ")", UUID.randomUUID().toString()); IconUtil.importIconPack(this, doc, meta.getName() + " (" + meta.getVersion() + ")", UUID.randomUUID().toString());
Toast.makeText(this, getString(R.string.icon_pack_imported, meta.getIcons().length), Toast.LENGTH_LONG).show(); Toast.makeText(this, getString(R.string.icon_pack_imported, meta.getIcons().length), Toast.LENGTH_LONG).show();
} catch (IconPackException e) { } catch (IconPackException e) {
DialogUtil.showErrorDialog(this, "Failed to import icon pack", e); DialogUtil.showErrorDialog(this, getString(R.string.error_import_icon_pack), e);
} }
break; break;
} }
@ -217,7 +217,7 @@ public class MainActivity extends BaseActivity {
IconUtil.importIconPack(this, doc); IconUtil.importIconPack(this, doc);
Toast.makeText(this, getString(R.string.icon_pack_imported, meta.getIcons().length), Toast.LENGTH_LONG).show(); Toast.makeText(this, getString(R.string.icon_pack_imported, meta.getIcons().length), Toast.LENGTH_LONG).show();
} catch (IconPackException e) { } catch (IconPackException e) {
DialogUtil.showErrorDialog(this, "Failed to import icon pack", e); DialogUtil.showErrorDialog(this, getString(R.string.error_import_icon_pack), e);
} }
}); });
@ -323,6 +323,7 @@ public class MainActivity extends BaseActivity {
finishAffinity(); finishAffinity();
}else { }else {
backLastPressed = System.currentTimeMillis(); backLastPressed = System.currentTimeMillis();
Toast.makeText(this, R.string.back_pressed, Toast.LENGTH_LONG).show();
} }
} }

View File

@ -78,8 +78,8 @@ public class EditOTPFragment extends NamedFragment {
binding.inputImage.setVisibility(SettingsUtil.isShowImages(requireContext()) ? View.VISIBLE : View.GONE); binding.inputImage.setVisibility(SettingsUtil.isShowImages(requireContext()) ? View.VISIBLE : View.GONE);
binding.inputImage.setOnClickListener(v -> { binding.inputImage.setOnClickListener(v -> {
new StyledDialogBuilder(requireContext()) new StyledDialogBuilder(requireContext())
.setTitle("Choose Image") .setTitle(R.string.edit_otp_choose_image)
.setItems(new String[]{"Image from icon pack", "Image from gallery", "No image", "Reset to default image"}, (d, which) -> { .setItems(R.array.edit_otp_choose_image_options, (d, which) -> {
switch(which) { switch(which) {
case 0: case 0:
pickImageFromIconPack(); pickImageFromIconPack();
@ -231,7 +231,7 @@ public class EditOTPFragment extends NamedFragment {
binding.inputImage.setImageBitmap(bm); binding.inputImage.setImageBitmap(bm);
}catch(IOException e) { }catch(IOException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to open image", e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_edit_otp_image), e);
} }
}); });
} }

View File

@ -100,7 +100,7 @@ public class GroupFragment extends NamedFragment {
OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext())); OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext()));
for(OTPData d : data) otpListAdapter.add(d); for(OTPData d : data) otpListAdapter.add(d);
} catch (OTPDatabaseException | CryptoException e) { } catch (OTPDatabaseException | CryptoException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to save database: " + e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_database_save), e);
} }
}, null); }, null);
} }
@ -112,7 +112,7 @@ public class GroupFragment extends NamedFragment {
try { try {
vh.refresh(); vh.refresh();
} catch (Exception e) { } catch (Exception e) {
DialogUtil.showErrorDialog(requireContext(), e.getMessage() == null ? "An error occurred while refreshing the code" : e.getMessage()); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_otp_refresh), e);
} }
} }
} }

View File

@ -103,7 +103,7 @@ public class SettingsFragment extends NamedFragment {
binding.settingsBiometricLock.setEnabled(true); binding.settingsBiometricLock.setEnabled(true);
} }
} catch (CryptoException | OTPDatabaseException e) { } catch (CryptoException | OTPDatabaseException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to enable encryption", e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_enable_encryption), e);
} }
}, () -> view.setChecked(false)); }, () -> view.setChecked(false));
}else { }else {
@ -118,7 +118,7 @@ public class SettingsFragment extends NamedFragment {
binding.settingsBiometricLock.setChecked(false); binding.settingsBiometricLock.setChecked(false);
binding.settingsBiometricLock.setEnabled(false); binding.settingsBiometricLock.setEnabled(false);
} catch (OTPDatabaseException | CryptoException e) { } catch (OTPDatabaseException | CryptoException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to disable encryption", e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_disable_encryption), e);
} }
}, () -> view.setChecked(true)); }, () -> view.setChecked(true));
} }
@ -135,7 +135,7 @@ public class SettingsFragment extends NamedFragment {
BiometricKey biometricKey = Crypto.createBiometricKey(SettingsUtil.getCryptoParameters(requireContext())); BiometricKey biometricKey = Crypto.createBiometricKey(SettingsUtil.getCryptoParameters(requireContext()));
SettingsUtil.enableBiometricEncryption(requireContext(), biometricKey); SettingsUtil.enableBiometricEncryption(requireContext(), biometricKey);
} catch (CryptoException e) { } catch (CryptoException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to enable: " + e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_biometric_encryption_enable), e);
} }
}, () -> view.setChecked(false)); }, () -> view.setChecked(false));
}, null); }, null);
@ -144,7 +144,7 @@ public class SettingsFragment extends NamedFragment {
BiometricKey key = SettingsUtil.getBiometricKey(requireContext()); BiometricKey key = SettingsUtil.getBiometricKey(requireContext());
if(key != null) Crypto.deleteBiometricKey(key); if(key != null) Crypto.deleteBiometricKey(key);
} catch (CryptoException e) { } catch (CryptoException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to delete key: " + e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_biometric_encryption_disable), e);
} }
SettingsUtil.disableBiometricEncryption(requireContext()); SettingsUtil.disableBiometricEncryption(requireContext());
@ -231,6 +231,11 @@ public class SettingsFragment extends NamedFragment {
.setItems(R.array.backup_create, (d, which) -> { .setItems(R.array.backup_create, (d, which) -> {
switch(which) { switch(which) {
case 0: case 0:
if(!SettingsUtil.isDatabaseEncrypted(requireContext())) {
DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_backup_database_not_encrypted));
return;
}
OTPDatabase.promptLoadDatabase(requireActivity(), () -> { OTPDatabase.promptLoadDatabase(requireActivity(), () -> {
SecretKey key = OTPDatabase.getLoadedKey(); SecretKey key = OTPDatabase.getLoadedKey();
CryptoParameters parameters = SettingsUtil.getCryptoParameters(requireContext()); CryptoParameters parameters = SettingsUtil.getCryptoParameters(requireContext());
@ -287,7 +292,7 @@ public class SettingsFragment extends NamedFragment {
binding.manageIconPacksList.setAdapter(new IconPackListAdapter(requireContext(), IconUtil.loadAllIconPacks(requireContext()))); binding.manageIconPacksList.setAdapter(new IconPackListAdapter(requireContext(), IconUtil.loadAllIconPacks(requireContext())));
new StyledDialogBuilder(requireContext()) new StyledDialogBuilder(requireContext())
.setTitle("Manage icon packs") .setTitle(R.string.manage_icon_packs_title)
.setView(binding.getRoot()) .setView(binding.getRoot())
.setPositiveButton(R.string.ok, (d, which) -> {}) .setPositiveButton(R.string.ok, (d, which) -> {})
.show(); .show();
@ -319,7 +324,7 @@ public class SettingsFragment extends NamedFragment {
return; return;
} catch (CryptoException ignored) { // Load with password } catch (CryptoException ignored) { // Load with password
} catch (BackupException | OTPDatabaseException e) { } catch (BackupException | OTPDatabaseException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to load backup", e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_backup_load_other), e);
return; return;
} }
} }
@ -330,9 +335,9 @@ public class SettingsFragment extends NamedFragment {
SecretKey key = Crypto.generateKey(parameters, password); SecretKey key = Crypto.generateKey(parameters, password);
loadBackup(uri, key, parameters); loadBackup(uri, key, parameters);
} catch (CryptoException e) { } catch (CryptoException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to load backup. Make sure the password is valid", e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_backup_load_crypto), e);
} catch (BackupException | OTPDatabaseException e) { } catch (BackupException | OTPDatabaseException e) {
DialogUtil.showErrorDialog(requireContext(), "Failed to load backup", e); DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_backup_load_other), e);
} }
}, null); }, null);
}, null); }, null);

View File

@ -93,7 +93,7 @@ public class IconListAdapter extends BaseExpandableListAdapter implements Expand
@Override @Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
IconListCategoryBinding binding = IconListCategoryBinding.inflate(LayoutInflater.from(context)); IconListCategoryBinding binding = IconListCategoryBinding.inflate(LayoutInflater.from(context));
binding.getRoot().setText((String) getGroup(groupPosition)); binding.getRoot().setText(getGroup(groupPosition));
return binding.getRoot(); return binding.getRoot();
} }

View File

@ -207,10 +207,11 @@ public class IconUtil {
for(IconPack pack : packs) { for(IconPack pack : packs) {
for(Icon i : pack.getIcons()) { for(Icon i : pack.getIcons()) {
String category = i.getMetadata().getCategory(); String category = i.getMetadata().getCategory();
if(icons.containsKey(category)) { List<Icon> is = icons.get(category);
icons.get(category).add(i); if(is != null) {
is.add(i);
}else { }else {
List<Icon> is = new ArrayList<>(); is = new ArrayList<>();
is.add(i); is.add(i);
icons.put(category, is); icons.put(category, is);
} }

View File

@ -190,7 +190,7 @@ public class OTPListAdapter extends RecyclerView.Adapter<OTPListItem> {
try { try {
h.refresh(); h.refresh();
} catch (OTPException e) { } catch (OTPException e) {
DialogUtil.showErrorDialog(context, e.getMessage() == null ? "An error occurred while refreshing the code" : e.getMessage()); DialogUtil.showErrorDialog(context, context.getString(R.string.error_otp_refresh), e);
} }
} }
} }

View File

@ -28,7 +28,10 @@ public class QRScannerContract extends ActivityResultContract<Void, ScannerResul
return null; return null;
} }
return new ScannerResult((OTPData[]) intent.getSerializableExtra("data")); OTPData[] data = (OTPData[]) intent.getSerializableExtra("data");
if(data == null) return null;
return new ScannerResult(data);
} }
} }

View File

@ -8,6 +8,7 @@ import androidx.annotation.Nullable;
import com.cringe_studios.code_guard.BaseActivity; import com.cringe_studios.code_guard.BaseActivity;
import com.cringe_studios.code_guard.MainActivity; import com.cringe_studios.code_guard.MainActivity;
import com.cringe_studios.code_guard.R;
import com.cringe_studios.code_guard.crypto.BiometricKey; import com.cringe_studios.code_guard.crypto.BiometricKey;
import com.cringe_studios.code_guard.crypto.Crypto; import com.cringe_studios.code_guard.crypto.Crypto;
import com.cringe_studios.code_guard.crypto.CryptoException; import com.cringe_studios.code_guard.crypto.CryptoException;
@ -49,7 +50,7 @@ public class UnlockActivity extends BaseActivity {
OTPDatabase.loadDatabase(this, key); OTPDatabase.loadDatabase(this, key);
success(); success();
} catch (CryptoException | OTPDatabaseException e) { } catch (CryptoException | OTPDatabaseException e) {
DialogUtil.showErrorDialog(this, "Failed to load database: " + e); DialogUtil.showErrorDialog(this, getString(R.string.error_unlock_other), e);
} }
}; };
@ -61,7 +62,7 @@ public class UnlockActivity extends BaseActivity {
binding.unlockButton.setOnClickListener(view -> { binding.unlockButton.setOnClickListener(view -> {
if(binding.unlockPassword.getText().length() == 0) { if(binding.unlockPassword.getText().length() == 0) {
DialogUtil.showErrorDialog(this, "You need to enter a password"); DialogUtil.showErrorDialog(this, getString(R.string.error_unlock_no_password));
return; return;
} }
@ -72,9 +73,9 @@ public class UnlockActivity extends BaseActivity {
OTPDatabase.loadDatabase(this, key); OTPDatabase.loadDatabase(this, key);
success(); success();
}catch(CryptoException e) { }catch(CryptoException e) {
DialogUtil.showErrorDialog(this, "Failed to load database: Invalid password or database corrupted", this::failure); DialogUtil.showErrorDialog(this, getString(R.string.error_unlock_crypto), this::failure);
} catch (OTPDatabaseException e) { } catch (OTPDatabaseException e) {
DialogUtil.showErrorDialog(this, "Failed to load database: " + e, this::failure); DialogUtil.showErrorDialog(this, getString(R.string.error_unlock_other), e, this::failure);
} }
}); });
} }

View File

@ -78,13 +78,17 @@ public class DialogUtil {
} }
public static void showErrorDialog(Context context, String errorMessage, Runnable closed) { public static void showErrorDialog(Context context, String errorMessage, Runnable closed) {
showErrorDialog(context, errorMessage, null, closed); showErrorDialog(context, errorMessage, (String) null, closed);
} }
public static void showErrorDialog(Context context, String errorMessage) { public static void showErrorDialog(Context context, String errorMessage) {
showErrorDialog(context, errorMessage, (Runnable) null); showErrorDialog(context, errorMessage, (Runnable) null);
} }
public static void showErrorDialog(Context context, String errorMessage, Exception exception, Runnable closed) {
showErrorDialog(context, errorMessage, stackTraceToString(exception), closed);
}
public static void showErrorDialog(Context context, String errorMessage, Exception exception) { public static void showErrorDialog(Context context, String errorMessage, Exception exception) {
showErrorDialog(context, errorMessage, stackTraceToString(exception), null); showErrorDialog(context, errorMessage, stackTraceToString(exception), null);
} }

View File

@ -13,8 +13,6 @@ import com.cringe_studios.code_guard.fragment.NamedFragment;
public class NavigationUtil { public class NavigationUtil {
// TODO: check if this still works after changes
private static void updateActivity(AppCompatActivity activity, NamedFragment newFragment) { private static void updateActivity(AppCompatActivity activity, NamedFragment newFragment) {
ActionBar bar = activity.getSupportActionBar(); ActionBar bar = activity.getSupportActionBar();
if(newFragment == null) newFragment = (NamedFragment) getCurrentFragment(activity.getSupportFragmentManager()); if(newFragment == null) newFragment = (NamedFragment) getCurrentFragment(activity.getSupportFragmentManager());

View File

@ -128,6 +128,33 @@
<string name="icon_pack_imported">Icon pack with %d icon(s) imported</string> <string name="icon_pack_imported">Icon pack with %d icon(s) imported</string>
<string name="enable_encryption_message">It is recommended to enable encryption to improve the security of the application.\n\nDo you want to go to the settings now to enable encryption?</string> <string name="enable_encryption_message">It is recommended to enable encryption to improve the security of the application.\n\nDo you want to go to the settings now to enable encryption?</string>
<string name="enable_encryption_title">Enable encryption</string> <string name="enable_encryption_title">Enable encryption</string>
<string name="back_pressed">Press back again to exit</string>
<string name="error_backup_database_not_encrypted">Database must be encrypted for this option</string>
<string name="manage_icon_packs_title">Manage icon packs</string>
<string name="error_backup_load_crypto">Failed to load backup. Make sure the password is valid</string>
<string name="error_backup_load_other">Failed to load backup</string>
<string name="error_biometric_encryption_enable">Failed to enable biometric encryption</string>
<string name="error_biometric_encryption_disable">Failed to enable biometric encryption</string>
<string name="edit_otp_choose_image">Choose Image</string>
<string name="error_edit_otp_image">Failed to open image</string>
<string name="error_database_save">Failed to save database</string>
<string name="error_otp_refresh">An error occurred while refreshing the code</string>
<string name="error_enable_encryption">Failed to enable encryption</string>
<string name="error_disable_encryption">Failed to disable encryption</string>
<string name="error_unlock_no_password">You need to enter a password</string>
<string name="error_unlock_crypto">Failed to load database: Invalid password or database corrupted</string>
<string name="error_unlock_other">Failed to load database</string>
<string name="error_qr_scan_not_detected">No codes were detected in the provided image</string>
<string name="error_qr_scan_failed">"Failed to detect code: "</string>
<string name="error_qr_scan_image_failed">"Failed to read image: "</string>
<string name="icon_pack_exists_title">Icon pack already exists</string>
<string name="error_import_icon_pack">Failed to import icon pack</string>
<string-array name="edit_otp_choose_image_options">
<item>Image from icon pack</item>
<item>Image from gallery</item>
<item>No image</item>
<item>Reset to default image</item>
</string-array>
<string-array name="error_icon_pack_exists_choices"> <string-array name="error_icon_pack_exists_choices">
<item>Override</item> <item>Override</item>
<item>Rename existing</item> <item>Rename existing</item>