diff --git a/app/src/main/java/com/cringe_studios/code_guard/fragment/GroupFragment.java b/app/src/main/java/com/cringe_studios/code_guard/fragment/GroupFragment.java index c4b59b1..897c1b1 100644 --- a/app/src/main/java/com/cringe_studios/code_guard/fragment/GroupFragment.java +++ b/app/src/main/java/com/cringe_studios/code_guard/fragment/GroupFragment.java @@ -95,13 +95,14 @@ public class GroupFragment extends NamedFragment { public void addOTP(OTPData... data) { OTPDatabase.promptLoadDatabase(requireActivity(), () -> { - try { - for(OTPData d : data) OTPDatabase.getLoadedDatabase().addOTP(groupID, d); - OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext())); - for(OTPData d : data) otpListAdapter.add(d); - } catch (OTPDatabaseException | CryptoException e) { - DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_database_save), e); - } + OTPDatabase.getLoadedDatabase().promptAddOTPs(requireContext(), groupID, () -> { + try { + OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext())); + for(OTPData d : data) otpListAdapter.add(d); + } catch (OTPDatabaseException | CryptoException e) { + DialogUtil.showErrorDialog(requireContext(), getString(R.string.error_database_save), e); + } + }, data); }, null); } @@ -149,19 +150,22 @@ public class GroupFragment extends NamedFragment { DialogUtil.showChooseGroupDialog(requireContext(), group -> { OTPDatabase.promptLoadDatabase(requireActivity(), () -> { - try { - for(OTPListItem item : items) { - OTPData data = item.getOTPData(); - OTPDatabase.getLoadedDatabase().addOTP(group, data); - otpListAdapter.remove(data); - } - - OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext())); - saveOTPs(); - otpListAdapter.finishEditing(); - } catch (OTPDatabaseException | CryptoException e) { - DialogUtil.showErrorDialog(requireContext(), e.toString()); + OTPData[] otps = new OTPData[items.size()]; + for(int i = 0; i < otps.length; i++) { + OTPData data = items.get(i).getOTPData(); + otps[i] = data; } + + OTPDatabase.getLoadedDatabase().promptAddOTPs(requireContext(), group, () -> { + try { + OTPDatabase.saveDatabase(requireContext(), SettingsUtil.getCryptoParameters(requireContext())); + for(OTPData data : otps) otpListAdapter.remove(data); + saveOTPs(); + otpListAdapter.finishEditing(); + } catch (OTPDatabaseException | CryptoException e) { + DialogUtil.showErrorDialog(requireContext(), e.toString()); + } + }, otps); }, null); saveOTPs(); }, null); diff --git a/app/src/main/java/com/cringe_studios/code_guard/model/OTPData.java b/app/src/main/java/com/cringe_studios/code_guard/model/OTPData.java index 90cf8f0..41ef18d 100644 --- a/app/src/main/java/com/cringe_studios/code_guard/model/OTPData.java +++ b/app/src/main/java/com/cringe_studios/code_guard/model/OTPData.java @@ -11,7 +11,7 @@ public class OTPData implements Serializable { public static final String IMAGE_DATA_NONE = "none"; - private final String name; + private String name; private final String issuer; private final OTPType type; private final String secret; @@ -41,6 +41,10 @@ public class OTPData implements Serializable { return name; } + public void setName(String name) { + this.name = name; + } + public String getIssuer() { return issuer; } diff --git a/app/src/main/java/com/cringe_studios/code_guard/urihandler/URIHandlerActivity.java b/app/src/main/java/com/cringe_studios/code_guard/urihandler/URIHandlerActivity.java index 6b78d1d..a8fc246 100644 --- a/app/src/main/java/com/cringe_studios/code_guard/urihandler/URIHandlerActivity.java +++ b/app/src/main/java/com/cringe_studios/code_guard/urihandler/URIHandlerActivity.java @@ -63,12 +63,13 @@ public class URIHandlerActivity extends BaseActivity { OTPDatabase.promptLoadDatabase(this, () -> { DialogUtil.showChooseGroupDialog(this, group -> { for(OTPData d : data) { - OTPDatabase.getLoadedDatabase().addOTP(group, d); - try { - OTPDatabase.saveDatabase(this, SettingsUtil.getCryptoParameters(this)); - } catch (OTPDatabaseException | CryptoException e) { - DialogUtil.showErrorDialog(this, e.toString()); - } + OTPDatabase.getLoadedDatabase().promptAddOTPs(this, group, () -> { + try { + OTPDatabase.saveDatabase(this, SettingsUtil.getCryptoParameters(this)); + } catch (OTPDatabaseException | CryptoException e) { + DialogUtil.showErrorDialog(this, e.toString()); + } + }, d); } Toast.makeText(this, R.string.uri_handler_code_added, Toast.LENGTH_SHORT).show(); }, this::finishAndRemoveTask); diff --git a/app/src/main/java/com/cringe_studios/code_guard/util/OTPDatabase.java b/app/src/main/java/com/cringe_studios/code_guard/util/OTPDatabase.java index 216e6ff..0645b34 100644 --- a/app/src/main/java/com/cringe_studios/code_guard/util/OTPDatabase.java +++ b/app/src/main/java/com/cringe_studios/code_guard/util/OTPDatabase.java @@ -2,8 +2,10 @@ package com.cringe_studios.code_guard.util; import android.app.Activity; import android.content.Context; +import android.util.Log; import com.cringe_studios.code_guard.BaseActivity; +import com.cringe_studios.code_guard.R; import com.cringe_studios.code_guard.crypto.Crypto; import com.cringe_studios.code_guard.crypto.CryptoException; import com.cringe_studios.code_guard.crypto.CryptoParameters; @@ -23,6 +25,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.crypto.SecretKey; @@ -45,11 +48,61 @@ public class OTPDatabase { return o; } - public void addOTP(String groupId, OTPData o) { - // TODO: check for code with same name + public void promptAddOTPs(Context context, String groupId, Runnable done, OTPData... data) { List os = new ArrayList<>(getOTPs(groupId)); - os.add(o); + + boolean anyDuplicates = false; + boolean[] duplicates = new boolean[data.length]; + for(int i = 0; i < data.length; i++) { + OTPData o = data[i]; + + for (OTPData o2 : os) { + if (Objects.equals(o.getName(), o2.getName()) && Objects.equals(o.getIssuer(), o2.getIssuer())) { + anyDuplicates = true; + duplicates[i] = true; + break; + } + } + } + + Log.d("ADD", "Any dupes?" + anyDuplicates); + + if (anyDuplicates) { + DialogUtil.showYesNoCancel(context, R.string.error_duplicate_otp_title, R.string.error_duplicate_otp_message, () -> { + for(int i = 0; i < data.length; i++) { + OTPData o = data[i]; + if(duplicates[i]) { + String oldName = o.getName(); + int count = 1; + boolean hasDuplicates; + do { + o.setName(oldName + " - " + (count++)); + hasDuplicates = false; + for(OTPData o2 : os) { + if(Objects.equals(o.getName(), o2.getName()) && Objects.equals(o.getIssuer(), o2.getIssuer())) { + hasDuplicates = true; + break; + } + } + }while(hasDuplicates); + } + } + + os.addAll(Arrays.asList(data)); + updateOTPs(groupId, os); + if (done != null) done.run(); + }, () -> { + os.addAll(Arrays.asList(data)); + updateOTPs(groupId, os); + if (done != null) done.run(); + }, null); + + return; + } + + os.addAll(Arrays.asList(data)); updateOTPs(groupId, os); + if(done != null) done.run(); } public void updateOTPs(String groupId, List o) { diff --git a/app/src/main/res/layout/dialog_set_password.xml b/app/src/main/res/layout/dialog_set_password.xml index 1f33821..243a010 100644 --- a/app/src/main/res/layout/dialog_set_password.xml +++ b/app/src/main/res/layout/dialog_set_password.xml @@ -28,7 +28,7 @@ android:layout_marginTop="10dp" app:passwordToggleEnabled="true"> - Schließen Sicherheit Lokalisierung + Ein OTP mit dem Namen des OTPs, das du hinzufügen willst, existiert bereits.\n\nWillst du das neue OTP umbenennen lassen, um sie voneinander zu unterscheiden? + Doppeltes OTP \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b139695..b9e7fd7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -169,6 +169,8 @@ Close Security Localization + An OTP with the name of the OTP you\'re trying to add already exists.\n\nDo you want to automatically rename the new OTP to distinguish them from each other? + Duplicate OTP Image from icon pack Image from gallery