Change clones (To redefine)

This commit is contained in:
J-Jamet
2018-03-24 17:13:16 +01:00
parent b66678f028
commit ed299b35e9
15 changed files with 283 additions and 295 deletions

View File

@@ -19,10 +19,7 @@
*/ */
package com.keepassdroid.tests; package com.keepassdroid.tests;
import java.util.UUID; import com.keepassdroid.database.AutoType;
import junit.framework.TestCase;
import com.keepassdroid.database.PwEntryV4; import com.keepassdroid.database.PwEntryV4;
import com.keepassdroid.database.PwGroupV4; import com.keepassdroid.database.PwGroupV4;
import com.keepassdroid.database.PwIconCustom; import com.keepassdroid.database.PwIconCustom;
@@ -30,13 +27,17 @@ import com.keepassdroid.database.PwIconStandard;
import com.keepassdroid.database.security.ProtectedBinary; import com.keepassdroid.database.security.ProtectedBinary;
import com.keepassdroid.database.security.ProtectedString; import com.keepassdroid.database.security.ProtectedString;
import junit.framework.TestCase;
import java.util.UUID;
public class PwEntryTestV4 extends TestCase { public class PwEntryTestV4 extends TestCase {
public void testAssign() { public void testAssign() {
PwEntryV4 entry = new PwEntryV4(); PwEntryV4 entry = new PwEntryV4();
entry.setAdditional("test223"); entry.setAdditional("test223");
entry.setAutoType(entry.new AutoType()); entry.setAutoType(new AutoType());
entry.getAutoType().defaultSequence = "1324"; entry.getAutoType().defaultSequence = "1324";
entry.getAutoType().enabled = true; entry.getAutoType().enabled = true;
entry.getAutoType().obfuscationOptions = 123412432109L; entry.getAutoType().obfuscationOptions = 123412432109L;

View File

@@ -25,7 +25,6 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import com.kunzisoft.keepass.R;
import com.keepassdroid.database.Database; import com.keepassdroid.database.Database;
import com.keepassdroid.database.PwGroup; import com.keepassdroid.database.PwGroup;
import com.keepassdroid.tests.database.TestData; import com.keepassdroid.tests.database.TestData;
@@ -66,7 +65,7 @@ public class SearchTest extends AndroidTestCase {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(ctx.getString(R.string.settings_omitbackup_key), setting); editor.putBoolean("settings_omitbackup_key", setting);
editor.commit(); editor.commit();
} }

View File

@@ -38,10 +38,8 @@ import android.widget.Toast;
import com.keepassdroid.app.App; import com.keepassdroid.app.App;
import com.keepassdroid.database.Database; import com.keepassdroid.database.Database;
import com.keepassdroid.database.PwDatabase; import com.keepassdroid.database.PwDatabase;
import com.keepassdroid.database.PwDatabaseV4;
import com.keepassdroid.database.PwDate; import com.keepassdroid.database.PwDate;
import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwEntryV4;
import com.keepassdroid.database.PwGroup; import com.keepassdroid.database.PwGroup;
import com.keepassdroid.database.PwGroupId; import com.keepassdroid.database.PwGroupId;
import com.keepassdroid.database.PwIconStandard; import com.keepassdroid.database.PwIconStandard;
@@ -61,9 +59,6 @@ import com.keepassdroid.utils.Util;
import com.keepassdroid.view.EntryEditNewField; import com.keepassdroid.view.EntryEditNewField;
import com.kunzisoft.keepass.R; import com.kunzisoft.keepass.R;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@@ -246,22 +241,17 @@ public class EntryEditActivity extends LockingHideActivity
} }
protected PwEntry populateNewEntry() { protected PwEntry populateNewEntry() {
if (mEntry instanceof PwEntryV4) { PwDatabase db = App.getDB().pm;
// TODO backup
PwEntryV4 newEntry = (PwEntryV4) mEntry.clone(true);
newEntry.setHistory((ArrayList<PwEntryV4>) newEntry.getHistory().clone());
newEntry.createBackup((PwDatabaseV4) App.getDB().pm);
}
PwEntry newEntry = mEntry.clone(true); PwEntry newEntry = mEntry.clone();
newEntry.startToDecodeReference(db);
newEntry.createBackup(db);
newEntry.setLastAccessTime(new PwDate()); newEntry.setLastAccessTime(new PwDate());
newEntry.setLastModificationTime(new PwDate()); newEntry.setLastModificationTime(new PwDate());
PwDatabase db = App.getDB().pm;
newEntry.startToDecodeReference(db);
newEntry.setTitle(entryTitleView.getText().toString()); newEntry.setTitle(entryTitleView.getText().toString());
if(mSelectedIconID != -1) if(mSelectedIconID != -1)
// or TODO icon factory newEntry.setIcon(App.getDB().pm.iconFactory.getIcon(mSelectedIconID)); // or TODO icon factory newEntry.setIcon(App.getDB().pm.iconFactory.getIcon(mSelectedIconID));

View File

@@ -0,0 +1,37 @@
package com.keepassdroid.database;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class AutoType implements Cloneable, Serializable {
private static final long OBF_OPT_NONE = 0;
public boolean enabled = true;
public long obfuscationOptions = OBF_OPT_NONE;
public String defaultSequence = "";
private HashMap<String, String> windowSeqPairs = new HashMap<>();
@SuppressWarnings("unchecked")
public AutoType clone() {
AutoType auto;
try {
auto = (AutoType) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
auto.windowSeqPairs = (HashMap<String, String>) windowSeqPairs.clone();
return auto;
}
public void put(String key, String value) {
windowSeqPairs.put(key, value);
}
public Set<Map.Entry<String, String>> entrySet() {
return windowSeqPairs.entrySet();
}
}

View File

@@ -19,14 +19,14 @@
*/ */
package com.keepassdroid.database; package com.keepassdroid.database;
import com.keepassdroid.app.App;
import com.keepassdroid.utils.Types;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import com.keepassdroid.app.App;
import com.keepassdroid.utils.Types;
/** Converting from the C Date format to the Java data format is /** Converting from the C Date format to the Java data format is
* expensive when done for every record at once. I use this class to * expensive when done for every record at once. I use this class to
* allow lazy conversions between the formats. * allow lazy conversions between the formats.
@@ -115,7 +115,7 @@ public class PwDate implements Cloneable, Serializable {
} }
@Override @Override
public Object clone() { public PwDate clone() {
PwDate copy = new PwDate(); PwDate copy = new PwDate();
if ( cDateBuilt ) { if ( cDateBuilt ) {

View File

@@ -44,22 +44,23 @@ public abstract class PwEntry extends PwNode implements Cloneable {
throw new RuntimeException("Unknown PwGroup instance."); throw new RuntimeException("Unknown PwGroup instance.");
} }
} }
@Override @Override
public Object clone() { public PwEntry clone() {
PwEntry newEntry; PwEntry newEntry;
try { try {
newEntry = (PwEntry) super.clone(); newEntry = (PwEntry) super.clone();
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone should be supported"); throw new RuntimeException("Clone should be supported");
} }
return newEntry; return newEntry;
} }
public PwEntry clone(boolean deepStrings) { @Override
return (PwEntry) clone(); protected void addCloneAttributesToNewEntry(PwEntry newEntry) {
} super.addCloneAttributesToNewEntry(newEntry);
newEntry.icon = new PwIconStandard(this.icon);
}
@Override @Override
public Type getType() { public Type getType() {
@@ -171,6 +172,11 @@ public abstract class PwEntry extends PwNode implements Cloneable {
return false; return false;
} }
/**
* Create a backup of entry
*/
public void createBackup(PwDatabase db) {}
public EntrySearchStringIterator stringIterator() { public EntrySearchStringIterator stringIterator() {
return EntrySearchStringIterator.getInstance(this); return EntrySearchStringIterator.getInstance(this);
} }

View File

@@ -42,10 +42,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
package com.keepassdroid.database; package com.keepassdroid.database;
import com.keepassdroid.utils.Types;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Random;
import java.util.UUID; import java.util.UUID;
@@ -68,6 +65,7 @@ import java.util.UUID;
* @author Naomaru Itoi <nao@phoneid.org> * @author Naomaru Itoi <nao@phoneid.org>
* @author Bill Zwicky <wrzwicky@pobox.com> * @author Bill Zwicky <wrzwicky@pobox.com>
* @author Dominik Reichl <dominik.reichl@t-online.de> * @author Dominik Reichl <dominik.reichl@t-online.de>
* @author Jeremy Jamet <jeremy.jamet@kunzisoft.com>
*/ */
public class PwEntryV3 extends PwEntry { public class PwEntryV3 extends PwEntry {
@@ -81,10 +79,10 @@ public class PwEntryV3 extends PwEntry {
private PwGroupV3 parent = null; private PwGroupV3 parent = null;
private int groupId; private int groupId;
private byte[] uuid; private UUID uuid;
private String title;
private String username; private String username;
private byte[] password; private byte[] password;
private String title;
private String url; private String url;
private String additional; private String additional;
@@ -98,15 +96,74 @@ public class PwEntryV3 extends PwEntry {
} }
public PwEntryV3(PwGroupV3 p) { public PwEntryV3(PwGroupV3 p) {
parent = p; parent = p;
groupId = ((PwGroupIdV3)parent.getId()).getId(); groupId = ((PwGroupIdV3)parent.getId()).getId(); // TODO remove
uuid = UUID.randomUUID();
Random random = new Random();
uuid = new byte[16];
random.nextBytes(uuid);
} }
@Override
public void assign(PwEntry source) {
if ( ! (source instanceof PwEntryV3) ) {
throw new RuntimeException("DB version mix");
}
super.assign(source);
PwEntryV3 src = (PwEntryV3) source;
assign(src);
}
private void assign(PwEntryV3 source) {
parent = source.parent;
groupId = source.groupId;
uuid = source.uuid;
title = source.title;
username = source.username;
int passLen = source.password.length;
password = new byte[passLen];
System.arraycopy(source.password, 0, password, 0, passLen);
url = source.url;
additional = source.additional;
binaryDesc = source.binaryDesc;
if ( source.binaryData != null ) {
int descLen = source.binaryData.length;
binaryData = new byte[descLen];
System.arraycopy(source.binaryData, 0, binaryData, 0, descLen);
}
}
@Override
public PwEntryV3 clone() {
PwEntryV3 newEntry = (PwEntryV3) super.clone();
// Attributes in parent
addCloneAttributesToNewEntry(newEntry);
// Attributes here
// newEntry.parent stay the same in copy
// newEntry.groupId stay the same in copy
// newEntry.uuid stay the same in copy
// newEntry.title stay the same in copy
// newEntry.username stay the same in copy
if (password != null) {
int passLen = password.length;
password = new byte[passLen];
System.arraycopy(password, 0, newEntry.password, 0, passLen);
}
// newEntry.url stay the same in copy
// newEntry.additional stay the same in copy
// newEntry.binaryDesc stay the same in copy
if ( binaryData != null ) {
int descLen = binaryData.length;
newEntry.binaryData = new byte[descLen];
System.arraycopy(binaryData, 0, newEntry.binaryData, 0, descLen);
}
return newEntry;
}
@Override @Override
public PwGroupV3 getParent() { public PwGroupV3 getParent() {
return parent; return parent;
@@ -127,12 +184,12 @@ public class PwEntryV3 extends PwEntry {
@Override @Override
public UUID getUUID() { public UUID getUUID() {
return Types.bytestoUUID(uuid); return uuid;
} }
@Override @Override
public void setUUID(UUID u) { public void setUUID(UUID uuid) {
uuid = Types.UUIDtoBytes(u); this.uuid = uuid;
} }
@Override @Override
@@ -192,7 +249,7 @@ public class PwEntryV3 extends PwEntry {
} }
if (uuid == null) { if (uuid == null) {
uuid = Types.UUIDtoBytes(UUID.randomUUID()); uuid = UUID.randomUUID();
} }
if (title == null) { if (title == null) {
@@ -305,74 +362,4 @@ public class PwEntryV3 extends PwEntry {
return true; return true;
} }
@Override
public void assign(PwEntry source) {
if ( ! (source instanceof PwEntryV3) ) {
throw new RuntimeException("DB version mix");
}
super.assign(source);
PwEntryV3 src = (PwEntryV3) source;
assign(src);
}
private void assign(PwEntryV3 source) {
title = source.title;
url = source.url;
groupId = source.groupId;
username = source.username;
additional = source.additional;
uuid = source.uuid;
int passLen = source.password.length;
password = new byte[passLen];
System.arraycopy(source.password, 0, password, 0, passLen);
setCreationTime( (PwDate) source.getCreationTime().clone() );
setLastModificationTime( (PwDate) source.getLastModificationTime().clone() );
setLastAccessTime( (PwDate) source.getLastAccessTime().clone() );
setExpiryTime( (PwDate) source.getExpiryTime().clone() );
binaryDesc = source.binaryDesc;
if ( source.binaryData != null ) {
int descLen = source.binaryData.length;
binaryData = new byte[descLen];
System.arraycopy(source.binaryData, 0, binaryData, 0, descLen);
}
parent = source.parent;
}
@Override
public Object clone() {
PwEntryV3 newEntry = (PwEntryV3) super.clone();
if (password != null) {
int passLen = password.length;
password = new byte[passLen];
System.arraycopy(password, 0, newEntry.password, 0, passLen);
}
newEntry.setCreationTime( (PwDate) getCreationTime().clone() );
newEntry.setLastModificationTime( (PwDate) getLastModificationTime().clone() );
newEntry.setLastAccessTime( (PwDate) getLastAccessTime().clone() );
newEntry.setExpiryTime( (PwDate) getExpiryTime().clone() );
newEntry.binaryDesc = binaryDesc;
if ( binaryData != null ) {
int descLen = binaryData.length;
newEntry.binaryData = new byte[descLen];
System.arraycopy(binaryData, 0, newEntry.binaryData, 0, descLen);
}
newEntry.parent = parent;
return newEntry;
}
} }

View File

@@ -23,17 +23,16 @@ import com.keepassdroid.database.security.ProtectedBinary;
import com.keepassdroid.database.security.ProtectedString; import com.keepassdroid.database.security.ProtectedString;
import com.keepassdroid.utils.SprEngineV4; import com.keepassdroid.utils.SprEngineV4;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class PwEntryV4 extends PwEntry implements ITimeLogger { public class PwEntryV4 extends PwEntry implements ITimeLogger {
public static final String STR_TITLE = "Title"; public static final String STR_TITLE = "Title";
public static final String STR_USERNAME = "UserName"; public static final String STR_USERNAME = "UserName";
public static final String STR_PASSWORD = "Password"; public static final String STR_PASSWORD = "Password";
@@ -45,7 +44,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
private transient boolean mDecodeRef = false; private transient boolean mDecodeRef = false;
private PwGroupV4 parent; private PwGroupV4 parent;
private UUID uuid = PwDatabaseV4.UUID_ZERO; private UUID uuid = PwDatabaseV4.UUID_ZERO; // TODO move to parent
private PwIconCustom customIcon = PwIconCustom.ZERO; private PwIconCustom customIcon = PwIconCustom.ZERO;
private long usageCount = 0; private long usageCount = 0;
private PwDate parentGroupLastMod = new PwDate(); private PwDate parentGroupLastMod = new PwDate();
@@ -63,41 +62,6 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
private String additional = ""; private String additional = "";
private String tags = ""; private String tags = "";
public class AutoType implements Cloneable, Serializable {
private static final long OBF_OPT_NONE = 0;
public boolean enabled = true;
public long obfuscationOptions = OBF_OPT_NONE;
public String defaultSequence = "";
private HashMap<String, String> windowSeqPairs = new HashMap<>();
@SuppressWarnings("unchecked")
public Object clone() {
AutoType auto;
try {
auto = (AutoType) super.clone();
}
catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
auto.windowSeqPairs = (HashMap<String, String>) windowSeqPairs.clone();
return auto;
}
public void put(String key, String value) {
windowSeqPairs.put(key, value);
}
public Set<Entry<String, String>> entrySet() {
return windowSeqPairs.entrySet();
}
}
public PwEntryV4() { public PwEntryV4() {
} }
@@ -106,55 +70,63 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
uuid = UUID.randomUUID(); uuid = UUID.randomUUID();
} }
@Override
public void assign(PwEntry source) {
if ( ! (source instanceof PwEntryV4) ) {
throw new RuntimeException("DB version mix.");
}
super.assign(source);
PwEntryV4 src = (PwEntryV4) source;
parent = src.parent;
uuid = src.uuid;
customIcon = src.customIcon;
usageCount = src.usageCount;
parentGroupLastMod = src.parentGroupLastMod;
// TODO customData
@SuppressWarnings("unchecked") fields = src.fields;
@Override binaries = src.binaries;
public PwEntry clone(boolean deepStrings) { foregroundColor = src.foregroundColor;
PwEntryV4 entry = (PwEntryV4) super.clone(deepStrings); backgroupColor = src.backgroupColor;
overrideURL = src.overrideURL;
if (deepStrings) { autoType = src.autoType;
entry.fields = (HashMap<String, ProtectedString>) fields.clone(); history = src.history;
}
return entry;
}
@Override url = src.url;
public Object clone() { additional = src.additional;
PwEntryV4 newEntry = (PwEntryV4) super.clone(); tags = src.tags;
return newEntry; }
}
@Override @SuppressWarnings("unchecked")
public void assign(PwEntry source) { @Override
public PwEntryV4 clone() {
if ( ! (source instanceof PwEntryV4) ) { PwEntryV4 newEntry = (PwEntryV4) super.clone();
throw new RuntimeException("DB version mix.");
}
super.assign(source);
PwEntryV4 src = (PwEntryV4) source;
assign(src);
}
private void assign(PwEntryV4 source) { // Attributes in parent
super.assign(source); addCloneAttributesToNewEntry(newEntry);
parent = source.parent;
uuid = source.uuid; // Attributes here
fields = source.fields; // newEntry.parent stay the same in copy
binaries = source.binaries; // newEntry.uuid stay the same in copy
customIcon = source.customIcon; newEntry.customIcon = new PwIconCustom(this.customIcon);
foregroundColor = source.foregroundColor; // newEntry.usageCount stay the same in copy
backgroupColor = source.backgroupColor; newEntry.parentGroupLastMod = this.parentGroupLastMod.clone();
overrideURL = source.overrideURL; // TODO customData make copy from hashmap
autoType = source.autoType;
history = source.history; newEntry.fields = (HashMap<String, ProtectedString>) this.fields.clone();
parentGroupLastMod = source.parentGroupLastMod; newEntry.binaries = (HashMap<String, ProtectedBinary>) this.binaries.clone();
usageCount = source.usageCount; // newEntry.foregroundColor stay the same in copy
url = source.url; // newEntry.backgroupColor stay the same in copy
additional = source.additional; // newEntry.overrideURL stay the same in copy
} newEntry.autoType = autoType.clone();
newEntry.history = (ArrayList<PwEntryV4>) this.history.clone();
// newEntry.url stay the same in copy
// newEntry.additional stay the same in copy
// newEntry.tags stay the same in copy
return newEntry;
}
@Override @Override
public void startToDecodeReference(PwDatabase db) { public void startToDecodeReference(PwDatabase db) {
@@ -312,74 +284,6 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
return customIcon; return customIcon;
} }
} }
public void createBackup(PwDatabaseV4 db) {
PwEntryV4 copy = cloneDeep();
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<String, ProtectedBinary>) binaries.clone();
entry.history = (ArrayList<PwEntryV4>) history.clone();
entry.autoType = (AutoType) autoType.clone();
return entry;
}
private boolean maintainBackups(PwDatabaseV4 db) {
boolean deleted = false;
int maxItems = db.historyMaxItems;
if (maxItems >= 0) {
while (history.size() > maxItems) {
removeOldestBackup();
deleted = true;
}
}
long maxSize = db.historyMaxSize;
if (maxSize >= 0) {
while(true) {
long histSize = 0;
for (PwEntryV4 entry : history) {
histSize += entry.getSize();
}
if (histSize > maxSize) {
removeOldestBackup();
deleted = true;
} else {
break;
}
}
}
return deleted;
}
private void removeOldestBackup() {
Date min = null;
int index = -1;
for (int i = 0; i < history.size(); i++) {
PwEntry entry = history.get(i);
Date lastMod = entry.getLastModificationTime().getDate();
if ((min == null) || lastMod.before(min)) {
index = i;
min = lastMod;
}
}
if (index != -1) {
history.remove(index);
}
}
@Override @Override
public boolean allowExtraFields() { public boolean allowExtraFields() {
@@ -396,7 +300,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
if (fields.size() > 0) { if (fields.size() > 0) {
for (Map.Entry<String, ProtectedString> pair : fields.entrySet()) { for (Map.Entry<String, ProtectedString> pair : fields.entrySet()) {
String key = pair.getKey(); String key = pair.getKey();
if (!PwEntryV4.IsStandardField(key)) { if (!PwEntryV4.isStandardField(key)) {
protectedFields.put(key, pair.getValue()); protectedFields.put(key, pair.getValue());
} }
} }
@@ -413,7 +317,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
for (Map.Entry<String, ProtectedString> pair : fields.entrySet()) { for (Map.Entry<String, ProtectedString> pair : fields.entrySet()) {
String key = pair.getKey(); String key = pair.getKey();
// TODO Add hidden style for protection field // TODO Add hidden style for protection field
if (!PwEntryV4.IsStandardField(key)) { if (!PwEntryV4.isStandardField(key)) {
extraFields.put(key, spr.compile(pair.getValue().toString(), this, mDatabase)); extraFields.put(key, spr.compile(pair.getValue().toString(), this, mDatabase));
} }
} }
@@ -421,7 +325,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
return extraFields; return extraFields;
} }
public static boolean IsStandardField(String key) { private static boolean isStandardField(String key) {
return key.equals(STR_TITLE) || key.equals(STR_USERNAME) return key.equals(STR_TITLE) || key.equals(STR_USERNAME)
|| key.equals(STR_PASSWORD) || key.equals(STR_URL) || key.equals(STR_PASSWORD) || key.equals(STR_URL)
|| key.equals(STR_NOTES); || key.equals(STR_NOTES);
@@ -436,7 +340,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
Iterator<Entry<String, ProtectedString>> iter = fields.entrySet().iterator(); Iterator<Entry<String, ProtectedString>> iter = fields.entrySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
Map.Entry<String, ProtectedString> pair = iter.next(); Map.Entry<String, ProtectedString> pair = iter.next();
if (!PwEntryV4.IsStandardField(pair.getKey())) { if (!PwEntryV4.isStandardField(pair.getKey())) {
iter.remove(); iter.remove();
} }
} }
@@ -498,10 +402,6 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
return history.size(); return history.size();
} }
public static String getStrTitle() {
return STR_TITLE;
}
public String getAdditional() { public String getAdditional() {
return additional; return additional;
} }
@@ -556,6 +456,68 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
return size; return size;
} }
@Override
public void createBackup(PwDatabase db) {
super.createBackup(db);
PwEntryV4 copy = clone();
copy.history = new ArrayList<>();
history.add(copy);
if (db != null)
if (db instanceof PwDatabaseV4)
maintainBackups((PwDatabaseV4) db);
}
private boolean maintainBackups(PwDatabaseV4 db) {
boolean deleted = false;
int maxItems = db.historyMaxItems;
if (maxItems >= 0) {
while (history.size() > maxItems) {
removeOldestBackup();
deleted = true;
}
}
long maxSize = db.historyMaxSize;
if (maxSize >= 0) {
while(true) {
long histSize = 0;
for (PwEntryV4 entry : history) {
histSize += entry.getSize();
}
if (histSize > maxSize) {
removeOldestBackup();
deleted = true;
} else {
break;
}
}
}
return deleted;
}
private void removeOldestBackup() {
Date min = null;
int index = -1;
for (int i = 0; i < history.size(); i++) {
PwEntry entry = history.get(i);
Date lastMod = entry.getLastModificationTime().getDate();
if ((min == null) || lastMod.before(min)) {
index = i;
min = lastMod;
}
}
if (index != -1) {
history.remove(index);
}
}
@Override @Override
public void touch(boolean modified, boolean touchParents) { public void touch(boolean modified, boolean touchParents) {
super.touch(modified, touchParents); super.touch(modified, touchParents);
@@ -572,7 +534,6 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
if (parent != null) { if (parent != null) {
return parent.isSearchEnabled(); return parent.isSearchEnabled();
} }
return PwGroupV4.DEFAULT_SEARCHING_ENABLED; return PwGroupV4.DEFAULT_SEARCHING_ENABLED;
} }
} }

View File

@@ -35,7 +35,6 @@ public abstract class PwGroup extends PwNode {
protected List<PwGroup> childGroups = new ArrayList<>(); protected List<PwGroup> childGroups = new ArrayList<>();
protected List<PwEntry> childEntries = new ArrayList<>(); protected List<PwEntry> childEntries = new ArrayList<>();
private transient List<PwNode> children = new ArrayList<>();
public void initNewGroup(String nm, PwGroupId newId) { public void initNewGroup(String nm, PwGroupId newId) {
setId(newId); setId(newId);
@@ -101,7 +100,7 @@ public abstract class PwGroup extends PwNode {
* @return List of direct children (one level below) as PwNode * @return List of direct children (one level below) as PwNode
*/ */
public List<PwNode> getDirectChildren() { public List<PwNode> getDirectChildren() {
children.clear(); List<PwNode> children = new ArrayList<>();
children.addAll(childGroups); children.addAll(childGroups);
for(PwEntry child : childEntries) { for(PwEntry child : childEntries) {
if (!child.isMetaStream()) if (!child.isMetaStream())
@@ -110,14 +109,6 @@ public abstract class PwGroup extends PwNode {
return children; return children;
} }
/**
* Number of direct elements in Node (one level below)
* @return Size of child elements, default is 0
*/
public int numberOfDirectChildren() {
return childGroups.size() + childEntries.size();
}
public boolean isContainedIn(PwGroup container) { public boolean isContainedIn(PwGroup container) {
PwGroup cur = this; PwGroup cur = this;
while (cur != null) { while (cur != null) {

View File

@@ -3,7 +3,7 @@ package com.keepassdroid.database;
import java.io.Serializable; import java.io.Serializable;
public abstract class PwIcon implements Serializable { public abstract class PwIcon implements Serializable {
public boolean isMetaStreamIcon() { public boolean isMetaStreamIcon() {
return false; return false;
} }

View File

@@ -32,6 +32,11 @@ public class PwIconCustom extends PwIcon {
imageData = data; imageData = data;
} }
public PwIconCustom(PwIconCustom icon) {
uuid = icon.uuid;
imageData = icon.imageData;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;

View File

@@ -32,6 +32,10 @@ public class PwIconStandard extends PwIcon {
this.iconId = iconId; this.iconId = iconId;
} }
public PwIconStandard(PwIconStandard icon) {
this.iconId = icon.iconId;
}
@Override @Override
public boolean isMetaStreamIcon() { public boolean isMetaStreamIcon() {
return iconId == 0; return iconId == 0;

View File

@@ -30,10 +30,17 @@ import static com.keepassdroid.database.PwDate.PW_NEVER_EXPIRE;
*/ */
public abstract class PwNode implements ISmallTimeLogger, Serializable { public abstract class PwNode implements ISmallTimeLogger, Serializable {
private PwDate creation = new PwDate(); protected PwDate creation = new PwDate();
private PwDate lastMod = new PwDate(); protected PwDate lastMod = new PwDate();
private PwDate lastAccess = new PwDate(); protected PwDate lastAccess = new PwDate();
private PwDate expireDate = new PwDate(NEVER_EXPIRE); protected PwDate expireDate = new PwDate(NEVER_EXPIRE);
protected void addCloneAttributesToNewEntry(PwEntry newEntry) {
newEntry.creation = creation.clone();
newEntry.lastMod = lastMod.clone();
newEntry.lastAccess = lastAccess.clone();
newEntry.expireDate = expireDate.clone();
}
/** /**
* Type of available Nodes * Type of available Nodes

View File

@@ -40,7 +40,7 @@ public class UpdateEntry extends RunnableOnFinish {
// Keep backup of original values in case save fails // Keep backup of original values in case save fails
PwEntry backup; PwEntry backup;
backup = (PwEntry) mOldE.clone(); backup = mOldE.clone();
mFinish = new AfterUpdate(backup, finish); mFinish = new AfterUpdate(backup, finish);
} }

View File

@@ -40,7 +40,7 @@ import com.keepassdroid.database.PwDefsV4;
import com.keepassdroid.database.PwDeletedObject; import com.keepassdroid.database.PwDeletedObject;
import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwEntryV4; import com.keepassdroid.database.PwEntryV4;
import com.keepassdroid.database.PwEntryV4.AutoType; import com.keepassdroid.database.AutoType;
import com.keepassdroid.database.PwGroup; import com.keepassdroid.database.PwGroup;
import com.keepassdroid.database.PwGroupV4; import com.keepassdroid.database.PwGroupV4;
import com.keepassdroid.database.PwIconCustom; import com.keepassdroid.database.PwIconCustom;