diff --git a/app/src/androidTest/java/com/keepassdroid/tests/PwEntryTestV4.java b/app/src/androidTest/java/com/keepassdroid/tests/PwEntryTestV4.java index 2f666b3e2..73017db3c 100644 --- a/app/src/androidTest/java/com/keepassdroid/tests/PwEntryTestV4.java +++ b/app/src/androidTest/java/com/keepassdroid/tests/PwEntryTestV4.java @@ -50,7 +50,7 @@ public class PwEntryTestV4 extends TestCase { entry.icon = new PwIconStandard(5); entry.overrideURL = "override"; entry.parent = new PwGroupV4(); - entry.strings.put("key2", new ProtectedString(false, "value2")); + entry.addField("key2", new ProtectedString(false, "value2")); entry.url = "http://localhost"; entry.uuid = UUID.randomUUID(); diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f1bb70a0e..9c5bee226 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -111,11 +111,7 @@ android:configChanges="orientation|keyboardHidden" android:windowSoftInputMode="stateHidden" /> - diff --git a/app/src/main/java/com/keepassdroid/activities/EntryActivity.java b/app/src/main/java/com/keepassdroid/activities/EntryActivity.java index 1301570b0..2b2584e3f 100644 --- a/app/src/main/java/com/keepassdroid/activities/EntryActivity.java +++ b/app/src/main/java/com/keepassdroid/activities/EntryActivity.java @@ -260,9 +260,11 @@ public class EntryActivity extends LockCloseHideActivity { entryContentsView.assignComment(mEntry.getNotes(true, pm)); // Assign custom fields - entryContentsView.clearExtraFields(); - for (Map.Entry field : mEntry.getExtraFields(pm).entrySet()) { - entryContentsView.addExtraField(field.getKey(), field.getValue()); + if (mEntry.allowExtraFields()) { + entryContentsView.clearExtraFields(); + for (Map.Entry field : mEntry.getExtraFields(pm).entrySet()) { + entryContentsView.addExtraField(field.getKey(), field.getValue()); + } } // Assign dates diff --git a/app/src/main/java/com/keepassdroid/activities/EntryEditActivity.java b/app/src/main/java/com/keepassdroid/activities/EntryEditActivity.java index 5fbbced90..df25c0333 100644 --- a/app/src/main/java/com/keepassdroid/activities/EntryEditActivity.java +++ b/app/src/main/java/com/keepassdroid/activities/EntryEditActivity.java @@ -29,26 +29,28 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; +import android.view.ViewGroup; import android.widget.EditText; import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; import com.keepassdroid.app.App; import com.keepassdroid.database.Database; import com.keepassdroid.database.PwDatabase; +import com.keepassdroid.database.PwDatabaseV4; import com.keepassdroid.database.PwEntry; -import com.keepassdroid.database.PwEntryV3; import com.keepassdroid.database.PwEntryV4; import com.keepassdroid.database.PwGroup; import com.keepassdroid.database.PwGroupId; -import com.keepassdroid.database.PwGroupV3; -import com.keepassdroid.database.PwGroupV4; import com.keepassdroid.database.PwIconStandard; import com.keepassdroid.database.edit.AddEntry; import com.keepassdroid.database.edit.OnFinish; import com.keepassdroid.database.edit.RunnableOnFinish; import com.keepassdroid.database.edit.UpdateEntry; +import com.keepassdroid.database.security.ProtectedString; import com.keepassdroid.fragments.GeneratePasswordDialogFragment; import com.keepassdroid.fragments.IconPickerDialogFragment; import com.keepassdroid.icons.Icons; @@ -56,14 +58,17 @@ import com.keepassdroid.tasks.ProgressTask; import com.keepassdroid.utils.MenuUtil; import com.keepassdroid.utils.Types; import com.keepassdroid.utils.Util; +import com.keepassdroid.view.EntryEditNewField; import com.kunzisoft.keepass.KeePass; import com.kunzisoft.keepass.R; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.Map; import java.util.UUID; -public abstract class EntryEditActivity extends LockCloseHideActivity +public class EntryEditActivity extends LockCloseHideActivity implements IconPickerDialogFragment.IconPickerListener, GeneratePasswordDialogFragment.GeneratePasswordListener { @@ -82,52 +87,31 @@ public abstract class EntryEditActivity extends LockCloseHideActivity protected boolean mIsNew; protected int mSelectedIconID = -1; + private ScrollView scrollView; + private ViewGroup extraFieldsContainer; + /** * launch EntryEditActivity to update an existing entry * @param act from activity * @param pw Entry to update */ public static void Launch(Activity act, PwEntry pw) { - Intent i; - if (pw instanceof PwEntryV3) { - i = new Intent(act, EntryEditActivityV3.class); - } - else if (pw instanceof PwEntryV4) { - i = new Intent(act, EntryEditActivityV4.class); - } - else { - throw new RuntimeException("Not yet implemented."); - } - - i.putExtra(KEY_ENTRY, Types.UUIDtoBytes(pw.getUUID())); - - act.startActivityForResult(i, ADD_OR_UPDATE_ENTRY_REQUEST_CODE); + Intent intent = new Intent(act, EntryEditActivity.class); + intent.putExtra(KEY_ENTRY, Types.UUIDtoBytes(pw.getUUID())); + act.startActivityForResult(intent, ADD_OR_UPDATE_ENTRY_REQUEST_CODE); } /** * launch EntryEditActivity to add a new entry * @param act from activity - * @param pw Group who will contains new entry + * @param pwGroup Group who will contains new entry */ - public static void Launch(Activity act, PwGroup pw) { - Intent i; - if (pw instanceof PwGroupV3) { - i = new Intent(act, EntryEditActivityV3.class); - EntryEditActivityV3.putParentId(i, KEY_PARENT, (PwGroupV3)pw); - } - else if (pw instanceof PwGroupV4) { - i = new Intent(act, EntryEditActivityV4.class); - EntryEditActivityV4.putParentId(i, KEY_PARENT, (PwGroupV4)pw); - } - else { - throw new RuntimeException("Not yet implemented."); - } - - act.startActivityForResult(i, ADD_OR_UPDATE_ENTRY_REQUEST_CODE); + public static void Launch(Activity act, PwGroup pwGroup) { + Intent intent = new Intent(act, EntryEditActivity.class); + intent.putExtra(KEY_PARENT, pwGroup.getId()); + act.startActivityForResult(intent, ADD_OR_UPDATE_ENTRY_REQUEST_CODE); } - protected abstract PwGroupId getParentGroupId(Intent i, String key); - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -148,17 +132,15 @@ public abstract class EntryEditActivity extends LockCloseHideActivity return; } - Intent i = getIntent(); - byte[] uuidBytes = i.getByteArrayExtra(KEY_ENTRY); + Intent intent = getIntent(); + byte[] uuidBytes = intent.getByteArrayExtra(KEY_ENTRY); PwDatabase pm = db.pm; if ( uuidBytes == null ) { - - PwGroupId parentId = getParentGroupId(i, KEY_PARENT); + PwGroupId parentId = (PwGroupId) intent.getSerializableExtra(KEY_PARENT); PwGroup parent = pm.groups.get(parentId); mEntry = PwEntry.getInstance(parent); mIsNew = true; - } else { UUID uuid = Types.bytestoUUID(uuidBytes); mEntry = pm.entries.get(uuid); @@ -166,11 +148,12 @@ public abstract class EntryEditActivity extends LockCloseHideActivity fillData(); } - View scrollView = findViewById(R.id.entry_scroll); + scrollView = (ScrollView) findViewById(R.id.entry_scroll); scrollView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); View iconButton = findViewById(R.id.icon_button); iconButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { IconPickerDialogFragment.launch(EntryEditActivity.this); } @@ -194,7 +177,6 @@ public abstract class EntryEditActivity extends LockCloseHideActivity if (!validateBeforeSaving()) { return; } - mCallbackNewEntry = populateNewEntry(); OnFinish onFinish = new AfterSave(); @@ -210,6 +192,29 @@ public abstract class EntryEditActivity extends LockCloseHideActivity } }); + + extraFieldsContainer = (ViewGroup) findViewById(R.id.advanced_container); + if (mEntry.allowExtraFields()) { + View add = findViewById(R.id.add_new_field); + add.setVisibility(View.VISIBLE); + add.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + EntryEditNewField ees = new EntryEditNewField(EntryEditActivity.this); + ees.setData("", new ProtectedString(false, "")); + extraFieldsContainer.addView(ees); + + // Scroll bottom + scrollView.post(new Runnable() { + @Override + public void run() { + scrollView.fullScroll(ScrollView.FOCUS_DOWN); + } + }); + } + }); + } } protected boolean validateBeforeSaving() { @@ -227,39 +232,74 @@ public abstract class EntryEditActivity extends LockCloseHideActivity Toast.makeText(this, R.string.error_pass_match, Toast.LENGTH_LONG).show(); return false; } - - return true; + + // Validate extra fields + if (mEntry.allowExtraFields()) { + for (int i = 0; i < extraFieldsContainer.getChildCount(); i++) { + EntryEditNewField ees = (EntryEditNewField) extraFieldsContainer.getChildAt(i); + String key = ees.getLabel(); + if (key == null || key.length() == 0) { + Toast.makeText(this, R.string.error_string_key, Toast.LENGTH_LONG).show(); + return false; + } + } + } + + return true; } protected PwEntry populateNewEntry() { - return populateNewEntry(null); - } - - protected PwEntry populateNewEntry(PwEntry entry) { - PwEntry newEntry; - if (entry == null) { - newEntry = mEntry.clone(true); - } - else { - newEntry = entry; - } - - Date now = Calendar.getInstance().getTime(); - newEntry.setLastAccessTime(now); - newEntry.setLastModificationTime(now); - - PwDatabase db = App.getDB().pm; - newEntry.setTitle(Util.getEditText(this, R.id.entry_title), db); - if(mSelectedIconID != -1) - newEntry.setIcon(new PwIconStandard(mSelectedIconID)); - newEntry.setUrl(Util.getEditText(this, R.id.entry_url), db); - newEntry.setUsername(Util.getEditText(this, R.id.entry_user_name), db); - newEntry.setNotes(Util.getEditText(this, R.id.entry_comment), db); - newEntry.setPassword(Util.getEditText(this, R.id.entry_password), db); - - return newEntry; + if (mEntry instanceof PwEntryV4) { + // TODO backup + PwEntryV4 newEntry = (PwEntryV4) mEntry.clone(true); + newEntry.history = (ArrayList) newEntry.history.clone(); + newEntry.createBackup((PwDatabaseV4) App.getDB().pm); + } + + PwEntry newEntry = mEntry.clone(true); + + Date now = Calendar.getInstance().getTime(); + newEntry.setLastAccessTime(now); + newEntry.setLastModificationTime(now); + + PwDatabase db = App.getDB().pm; + newEntry.setTitle(Util.getEditText(this, R.id.entry_title), db); + if(mSelectedIconID != -1) + // or TODO icon factory newEntry.setIcon(App.getDB().pm.iconFactory.getIcon(mSelectedIconID)); + newEntry.setIcon(new PwIconStandard(mSelectedIconID)); + else { + if (mIsNew) { + newEntry.setIcon(App.getDB().pm.iconFactory.getIcon(0)); + } + else { + // Keep previous icon, if no new one was selected + newEntry.setIcon(mEntry.icon); + } + } + newEntry.setUrl(Util.getEditText(this, R.id.entry_url), db); + newEntry.setUsername(Util.getEditText(this, R.id.entry_user_name), db); + newEntry.setNotes(Util.getEditText(this, R.id.entry_comment), db); + newEntry.setPassword(Util.getEditText(this, R.id.entry_password), db); + + + if (newEntry.allowExtraFields()) { + // Delete all new standard strings + newEntry.removeExtraFields(); + + // Add extra fields from views + for (int i = 0; i < extraFieldsContainer.getChildCount(); i++) { + EntryEditNewField view = (EntryEditNewField) extraFieldsContainer.getChildAt(i); + String key = view.getLabel(); + String value = view.getValue(); + boolean protect = view.isProtected(); + newEntry.addField(key, new ProtectedString(protect, value)); + } + } + + return newEntry; } + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); @@ -295,6 +335,15 @@ public abstract class EntryEditActivity extends LockCloseHideActivity populateText(R.id.entry_confpassword, password); populateText(R.id.entry_comment, mEntry.getNotes()); + + if (mEntry.allowExtraFields()) { + LinearLayout container = (LinearLayout) findViewById(R.id.advanced_container); + for (Map.Entry pair : mEntry.getExtraProtectedFields().entrySet()) { + EntryEditNewField ees = new EntryEditNewField(EntryEditActivity.this); + ees.setData(pair.getKey(), pair.getValue()); + container.addView(ees); + } + } } private void populateText(int viewId, String text) { diff --git a/app/src/main/java/com/keepassdroid/activities/EntryEditActivityV3.java b/app/src/main/java/com/keepassdroid/activities/EntryEditActivityV3.java deleted file mode 100644 index bba806e4f..000000000 --- a/app/src/main/java/com/keepassdroid/activities/EntryEditActivityV3.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePass DX. - * - * KeePass DX 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 2 of the License, or - * (at your option) any later version. - * - * KeePass DX 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 KeePass DX. If not, see . - * - */ -package com.keepassdroid.activities; - -import android.content.Intent; - -import com.keepassdroid.app.App; -import com.keepassdroid.database.PwEntry; -import com.keepassdroid.database.PwGroupId; -import com.keepassdroid.database.PwGroupIdV3; -import com.keepassdroid.database.PwGroupV3; - -public class EntryEditActivityV3 extends EntryEditActivity { - - @Override - protected PwEntry populateNewEntry(PwEntry entry) { - PwEntry newEntry = super.populateNewEntry(entry); - - if (mSelectedIconID == -1) { - if (mIsNew) { - newEntry.icon = App.getDB().pm.iconFactory.getIcon(0); - } - else { - // Keep previous icon, if no new one was selected - newEntry.icon = mEntry.icon; - } - } - else { - newEntry.icon = App.getDB().pm.iconFactory.getIcon(mSelectedIconID); - } - - return newEntry; - } - - protected static void putParentId(Intent i, String parentKey, PwGroupV3 parent) { - i.putExtra(parentKey, parent.groupId); - } - - @Override - protected PwGroupId getParentGroupId(Intent i, String key) { - int groupId = i.getIntExtra(key, -1); - - return new PwGroupIdV3(groupId); - } -} diff --git a/app/src/main/java/com/keepassdroid/activities/EntryEditActivityV4.java b/app/src/main/java/com/keepassdroid/activities/EntryEditActivityV4.java deleted file mode 100644 index d7411bf53..000000000 --- a/app/src/main/java/com/keepassdroid/activities/EntryEditActivityV4.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePass DX. - * - * KeePass DX 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 2 of the License, or - * (at your option) any later version. - * - * KeePass DX 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 KeePass DX. If not, see . - * - */ -package com.keepassdroid.activities; - -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; -import android.widget.Toast; - -import com.keepassdroid.app.App; -import com.keepassdroid.database.PwDatabaseV4; -import com.keepassdroid.database.PwEntry; -import com.keepassdroid.database.PwEntryV4; -import com.keepassdroid.database.PwGroupId; -import com.keepassdroid.database.PwGroupIdV4; -import com.keepassdroid.database.PwGroupV4; -import com.keepassdroid.database.security.ProtectedString; -import com.keepassdroid.utils.Types; -import com.keepassdroid.view.EntryEditNewField; -import com.kunzisoft.keepass.R; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -public class EntryEditActivityV4 extends EntryEditActivity { - - private ScrollView scroll; - - protected static void putParentId(Intent i, String parentKey, PwGroupV4 parent) { - PwGroupId id = parent.getId(); - PwGroupIdV4 id4 = (PwGroupIdV4) id; - - i.putExtra(parentKey, Types.UUIDtoBytes(id4.getId())); - - } - - @Override - protected PwGroupId getParentGroupId(Intent i, String key) { - byte[] buf = i.getByteArrayExtra(key); - UUID id = Types.bytestoUUID(buf); - - return new PwGroupIdV4(id); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - scroll = (ScrollView) findViewById(R.id.entry_scroll); - - View add = findViewById(R.id.add_new_field); - add.setVisibility(View.VISIBLE); - add.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - LinearLayout container = (LinearLayout) findViewById(R.id.advanced_container); - - EntryEditNewField ees = new EntryEditNewField(EntryEditActivityV4.this); - ees.setData("", new ProtectedString(false, "")); - container.addView(ees); - - // Scroll bottom - scroll.post(new Runnable() { - @Override - public void run() { - scroll.fullScroll(ScrollView.FOCUS_DOWN); - } - }); - } - }); - } - - @Override - protected void fillData() { - super.fillData(); - - PwEntryV4 entry = (PwEntryV4) mEntry; - - LinearLayout container = (LinearLayout) findViewById(R.id.advanced_container); - - if (entry.strings.size() > 0) { - for (Entry pair : entry.strings.entrySet()) { - String key = pair.getKey(); - - if (!PwEntryV4.IsStandardString(key)) { - EntryEditNewField ees = new EntryEditNewField(EntryEditActivityV4.this); - ees.setData(key, pair.getValue()); - container.addView(ees); - } - } - } - - } - - @SuppressWarnings("unchecked") - @Override - protected PwEntry populateNewEntry() { - PwEntryV4 newEntry = (PwEntryV4) mEntry.clone(true); - newEntry.history = (ArrayList) newEntry.history.clone(); - newEntry.createBackup((PwDatabaseV4)App.getDB().pm); - - newEntry = (PwEntryV4) super.populateNewEntry(newEntry); - - Map strings = newEntry.strings; - - // Delete all new standard strings - Iterator> iter = strings.entrySet().iterator(); - while (iter.hasNext()) { - Entry pair = iter.next(); - if (!PwEntryV4.IsStandardString(pair.getKey())) { - iter.remove(); - } - } - - LinearLayout container = (LinearLayout) findViewById(R.id.advanced_container); - for (int i = 0; i < container.getChildCount(); i++) { - EntryEditNewField view = (EntryEditNewField) container.getChildAt(i); - String key = view.getLabel(); - String value = view.getValue(); - boolean protect = view.isProtected(); - strings.put(key, new ProtectedString(protect, value)); - } - - return newEntry; - } - - @Override - protected boolean validateBeforeSaving() { - if(!super.validateBeforeSaving()) { - return false; - } - - ViewGroup container = (ViewGroup) findViewById(R.id.advanced_container); - for (int i = 0; i < container.getChildCount(); i++) { - EntryEditNewField ees = (EntryEditNewField) container.getChildAt(i); - String key = ees.getLabel(); - if (key == null || key.length() == 0) { - Toast.makeText(this, R.string.error_string_key, Toast.LENGTH_LONG).show(); - return false; - } - } - - return true; - } - -} - \ No newline at end of file diff --git a/app/src/main/java/com/keepassdroid/database/PwEntry.java b/app/src/main/java/com/keepassdroid/database/PwEntry.java index 434903761..e5f36f306 100644 --- a/app/src/main/java/com/keepassdroid/database/PwEntry.java +++ b/app/src/main/java/com/keepassdroid/database/PwEntry.java @@ -35,10 +35,6 @@ public abstract class PwEntry extends PwNode implements Cloneable { public PwIconStandard icon = PwIconStandard.FIRST; public static PwEntry getInstance(PwGroup parent) { - return PwEntry.getInstance(parent, true, true); - } - - public static PwEntry getInstance(PwGroup parent, boolean initId, boolean initDates) { if (parent instanceof PwGroupV3) { return new PwEntryV3((PwGroupV3)parent); } @@ -140,6 +136,16 @@ public abstract class PwEntry extends PwNode implements Cloneable { } } + // TODO encapsulate extra fields + + /** + * To redefine if version of entry allow extra field, + * @return true if entry allows extra field + */ + public boolean allowExtraFields() { + return false; + } + /** * Retrieve extra fields to show, key is the label, value is the value of field * @param pm Database @@ -149,6 +155,26 @@ public abstract class PwEntry extends PwNode implements Cloneable { return new HashMap<>(); } + /** + * Retrieve extra protected fields to show, key is the label, value is the value protected of field + * @return Map of label/value + */ + public Map getExtraProtectedFields() { + return new HashMap<>(); + } + + /** + * Add an extra field to the list + * @param label Label of field, must be unique + * @param value Value of field + */ + public void addField(String label, ProtectedString value) {} + + /** + * Delete all extra fields + */ + public void removeExtraFields() {} + public boolean isMetaStream() { return false; } diff --git a/app/src/main/java/com/keepassdroid/database/PwEntryV4.java b/app/src/main/java/com/keepassdroid/database/PwEntryV4.java index 6dd711481..9a3ae3bf0 100644 --- a/app/src/main/java/com/keepassdroid/database/PwEntryV4.java +++ b/app/src/main/java/com/keepassdroid/database/PwEntryV4.java @@ -22,13 +22,13 @@ package com.keepassdroid.database; import com.keepassdroid.database.security.ProtectedBinary; import com.keepassdroid.database.security.ProtectedString; import com.keepassdroid.utils.SprEngine; -import com.keepassdroid.utils.SprEngineV4; import java.io.Serializable; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -43,14 +43,14 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger { public PwGroupV4 parent; public UUID uuid = PwDatabaseV4.UUID_ZERO; - public HashMap strings = new HashMap(); - public HashMap binaries = new HashMap(); + private HashMap fields = new HashMap<>(); + public HashMap binaries = new HashMap<>(); public PwIconCustom customIcon = PwIconCustom.ZERO; public String foregroundColor = ""; public String backgroupColor = ""; public String overrideURL = ""; public AutoType autoType = new AutoType(); - public ArrayList history = new ArrayList(); + public ArrayList history = new ArrayList<>(); private Date parentGroupLastMod = PwDatabaseV4.DEFAULT_NOW; private Date creation = PwDatabaseV4.DEFAULT_NOW; @@ -132,22 +132,11 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger { PwEntryV4 entry = (PwEntryV4) super.clone(deepStrings); if (deepStrings) { - entry.strings = (HashMap) strings.clone(); + entry.fields = (HashMap) fields.clone(); } return entry; } - - @SuppressWarnings("unchecked") - public PwEntryV4 cloneDeep() { - PwEntryV4 entry = (PwEntryV4) clone(true); - - entry.binaries = (HashMap) binaries.clone(); - entry.history = (ArrayList) history.clone(); - entry.autoType = (AutoType) autoType.clone(); - - return entry; - } @Override public void assign(PwEntry source) { @@ -165,7 +154,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger { private void assign(PwEntryV4 source) { parent = source.parent; uuid = source.uuid; - strings = source.strings; + fields = source.fields; binaries = source.binaries; customIcon = source.customIcon; foregroundColor = source.foregroundColor; @@ -316,7 +305,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger { } public String getString(String key) { - ProtectedString value = strings.get(key); + ProtectedString value = fields.get(key); if ( value == null ) return new String(""); @@ -325,7 +314,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger { public void setString(String key, String value, boolean protect) { ProtectedString ps = new ProtectedString(protect, value); - strings.put(key, ps); + fields.put(key, ps); } public Date getLocationChanged() { @@ -370,22 +359,26 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger { } else { return customIcon; } - - } - - public static boolean IsStandardString(String key) { - return key.equals(STR_TITLE) || key.equals(STR_USERNAME) - || key.equals(STR_PASSWORD) || key.equals(STR_URL) - || key.equals(STR_NOTES); } public void createBackup(PwDatabaseV4 db) { PwEntryV4 copy = cloneDeep(); - copy.history = new ArrayList(); + copy.history = new ArrayList<>(); history.add(copy); if (db != null) maintainBackups(db); } + + @SuppressWarnings("unchecked") + public PwEntryV4 cloneDeep() { + PwEntryV4 entry = (PwEntryV4) clone(true); + + entry.binaries = (HashMap) binaries.clone(); + entry.history = (ArrayList) history.clone(); + entry.autoType = (AutoType) autoType.clone(); + + return entry; + } private boolean maintainBackups(PwDatabaseV4 db) { boolean deleted = false; @@ -437,28 +430,71 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger { } @Override + public boolean allowExtraFields() { + return true; + } + + public Map getFields() { + return fields; + } + + @Override + public Map getExtraProtectedFields() { + Map protectedFields = super.getExtraProtectedFields(); + if (fields.size() > 0) { + for (Map.Entry pair : fields.entrySet()) { + String key = pair.getKey(); + if (!PwEntryV4.IsStandardField(key)) { + protectedFields.put(key, pair.getValue()); + } + } + } + return protectedFields; + } + + @Override public Map getExtraFields(PwDatabase pm) { - Map fields = super.getExtraFields(pm); + Map extraFields = super.getExtraFields(pm); SprEngine spr = SprEngine.getInstance(pm); - // Display custom strings - if (strings.size() > 0) { - for (Map.Entry pair : strings.entrySet()) { + // Display custom fields + if (fields.size() > 0) { + for (Map.Entry pair : fields.entrySet()) { String key = pair.getKey(); // TODO Add hidden style for protection field - if (!PwEntryV4.IsStandardString(key)) { - String text = pair.getValue().toString(); - fields.put(key, spr.compile(text, this, pm)); + if (!PwEntryV4.IsStandardField(key)) { + extraFields.put(key, spr.compile(pair.getValue().toString(), this, pm)); } } } - return fields; + return extraFields; } + + public static boolean IsStandardField(String key) { + return key.equals(STR_TITLE) || key.equals(STR_USERNAME) + || key.equals(STR_PASSWORD) || key.equals(STR_URL) + || key.equals(STR_NOTES); + } + + public void addField(String label, ProtectedString value) { + fields.put(label, value); + } + + @Override + public void removeExtraFields() { + Iterator> iter = fields.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry pair = iter.next(); + if (!PwEntryV4.IsStandardField(pair.getKey())) { + iter.remove(); + } + } + } private static final long FIXED_LENGTH_SIZE = 128; // Approximate fixed length size public long getSize() { long size = FIXED_LENGTH_SIZE; - for (Entry pair : strings.entrySet()) { + for (Entry pair : fields.entrySet()) { size += pair.getKey().length(); size += pair.getValue().length(); } diff --git a/app/src/main/java/com/keepassdroid/database/PwGroupV3.java b/app/src/main/java/com/keepassdroid/database/PwGroupV3.java index 47429267c..ed59db4d9 100644 --- a/app/src/main/java/com/keepassdroid/database/PwGroupV3.java +++ b/app/src/main/java/com/keepassdroid/database/PwGroupV3.java @@ -30,6 +30,11 @@ Copyright 2006 Bill Zwicky package com.keepassdroid.database; +import android.content.Intent; +import android.os.Bundle; + +import com.keepassdroid.utils.Types; + import java.util.Calendar; import java.util.Date; import java.util.List; diff --git a/app/src/main/java/com/keepassdroid/database/PwGroupV4.java b/app/src/main/java/com/keepassdroid/database/PwGroupV4.java index fd04519c7..c37604c9d 100644 --- a/app/src/main/java/com/keepassdroid/database/PwGroupV4.java +++ b/app/src/main/java/com/keepassdroid/database/PwGroupV4.java @@ -19,6 +19,11 @@ */ package com.keepassdroid.database; +import android.content.Intent; +import android.os.Bundle; + +import com.keepassdroid.utils.Types; + import java.util.Date; import java.util.HashMap; import java.util.List; diff --git a/app/src/main/java/com/keepassdroid/database/iterator/EntrySearchStringIteratorV4.java b/app/src/main/java/com/keepassdroid/database/iterator/EntrySearchStringIteratorV4.java index e2282d531..78f46f5ee 100644 --- a/app/src/main/java/com/keepassdroid/database/iterator/EntrySearchStringIteratorV4.java +++ b/app/src/main/java/com/keepassdroid/database/iterator/EntrySearchStringIteratorV4.java @@ -35,14 +35,14 @@ public class EntrySearchStringIteratorV4 extends EntrySearchStringIterator { public EntrySearchStringIteratorV4(PwEntryV4 entry) { this.sp = SearchParametersV4.DEFAULT; - setIterator = entry.strings.entrySet().iterator(); + setIterator = entry.getFields().entrySet().iterator(); advance(); } public EntrySearchStringIteratorV4(PwEntryV4 entry, SearchParametersV4 sp) { this.sp = sp; - setIterator = entry.strings.entrySet().iterator(); + setIterator = entry.getFields().entrySet().iterator(); advance(); } diff --git a/app/src/main/java/com/keepassdroid/database/load/ImporterV4.java b/app/src/main/java/com/keepassdroid/database/load/ImporterV4.java index e8af9d791..7c81888ab 100644 --- a/app/src/main/java/com/keepassdroid/database/load/ImporterV4.java +++ b/app/src/main/java/com/keepassdroid/database/load/ImporterV4.java @@ -862,7 +862,7 @@ public class ImporterV4 extends Importer { } else if ( ctx == KdbContext.EntryTimes && name.equalsIgnoreCase(ElemTimes) ) { return KdbContext.Entry; } else if ( ctx == KdbContext.EntryString && name.equalsIgnoreCase(ElemString) ) { - ctxEntry.strings.put(ctxStringName, ctxStringValue); + ctxEntry.addField(ctxStringName, ctxStringValue); ctxStringName = null; ctxStringValue = null; diff --git a/app/src/main/java/com/keepassdroid/database/save/PwDbV4Output.java b/app/src/main/java/com/keepassdroid/database/save/PwDbV4Output.java index 529cfa7b9..ea6ce6fd8 100644 --- a/app/src/main/java/com/keepassdroid/database/save/PwDbV4Output.java +++ b/app/src/main/java/com/keepassdroid/database/save/PwDbV4Output.java @@ -475,7 +475,7 @@ public class PwDbV4Output extends PwDbOutput { writeList(ElemTimes, entry); - writeList(entry.strings, true); + writeList(entry.getFields(), true); writeList(entry.binaries); writeList(ElemAutoType, entry.autoType); diff --git a/app/src/main/java/com/keepassdroid/view/EntryContentsView.java b/app/src/main/java/com/keepassdroid/view/EntryContentsView.java index 0f6ef6329..af878b763 100644 --- a/app/src/main/java/com/keepassdroid/view/EntryContentsView.java +++ b/app/src/main/java/com/keepassdroid/view/EntryContentsView.java @@ -132,7 +132,7 @@ public class EntryContentsView extends LinearLayout { } public void addExtraField(String title, String value) { - View view = new EntrySection(getContext(), null, title, value); + View view = new EntryNewField(getContext(), null, title, value); extrasView.addView(view); } diff --git a/app/src/main/java/com/keepassdroid/view/EntrySection.java b/app/src/main/java/com/keepassdroid/view/EntryNewField.java similarity index 85% rename from app/src/main/java/com/keepassdroid/view/EntrySection.java rename to app/src/main/java/com/keepassdroid/view/EntryNewField.java index 7ec69121a..b005cdfb4 100644 --- a/app/src/main/java/com/keepassdroid/view/EntrySection.java +++ b/app/src/main/java/com/keepassdroid/view/EntryNewField.java @@ -27,17 +27,17 @@ import android.widget.TextView; import com.kunzisoft.keepass.R; -public class EntrySection extends LinearLayout { +public class EntryNewField extends LinearLayout { - public EntrySection(Context context) { + public EntryNewField(Context context) { this(context, null); } - public EntrySection(Context context, AttributeSet attrs) { + public EntryNewField(Context context, AttributeSet attrs) { this(context, attrs, null, null); } - public EntrySection(Context context, AttributeSet attrs, String title, String value) { + public EntryNewField(Context context, AttributeSet attrs, String title, String value) { super(context, attrs); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -45,7 +45,7 @@ public class EntrySection extends LinearLayout { } protected int getLayout() { - return R.layout.entry_section; + return R.layout.entry_new_field; } protected void inflate(LayoutInflater inflater, Context context, String title, String value) { diff --git a/app/src/main/res/drawable/ic_content_copy_black_24dp.xml b/app/src/main/res/drawable/ic_content_copy_black_24dp.xml new file mode 100644 index 000000000..8a894a3bc --- /dev/null +++ b/app/src/main/res/drawable/ic_content_copy_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/entry_section.xml b/app/src/main/res/layout/entry_new_field.xml similarity index 100% rename from app/src/main/res/layout/entry_section.xml rename to app/src/main/res/layout/entry_new_field.xml