Refactor database elements

This commit is contained in:
J-Jamet
2019-04-24 20:38:13 +02:00
parent 5705d367ed
commit 9e79da0efc
15 changed files with 347 additions and 492 deletions

View File

@@ -1,6 +1,6 @@
/*
* 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
@@ -25,7 +25,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import android.webkit.URLUtil;
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine;
import com.kunzisoft.keepass.crypto.keyDerivation.KdfFactory;
import com.kunzisoft.keepass.database.EntryHandler;
@@ -44,28 +43,23 @@ import com.kunzisoft.keepass.icons.IconDrawableFactory;
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater;
import com.kunzisoft.keepass.utils.EmptyUtils;
import com.kunzisoft.keepass.utils.UriUtil;
import org.apache.commons.io.FileUtils;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.SyncFailedException;
import javax.annotation.Nullable;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
public class Database {
private static final String TAG = Database.class.getName();
private PwDatabase pwDatabase = null;
private PwDatabaseV3 pwDatabaseV3 = null;
private PwDatabaseV4 pwDatabaseV4 = null;
private PwVersion version = null;
private Uri mUri = null;
private SearchDbHelper searchHelper = null;
private boolean readOnly = false;
@@ -80,14 +74,31 @@ public class Database {
public Database(String databasePath) {
// TODO Test with kdb extension
if (isKDBExtension(databasePath)) {
this.pwDatabase = new PwDatabaseV3();
this.pwDatabaseV3 = new PwDatabaseV3();
this.pwDatabase = pwDatabaseV3;
} else {
PwDatabaseV4 databaseV4 = new PwDatabaseV4();
databaseV4.setRootGroup(
new PwGroupV4(dbNameFromPath(databasePath),
databaseV4.getIconFactory().getFolderIcon())
);
this.pwDatabase = databaseV4;
PwGroupV4 groupV4 = new PwGroupV4();
this.pwDatabaseV4 = new PwDatabaseV4();
groupV4.setTitle(dbNameFromPath(databasePath));
groupV4.setIconStandard(pwDatabaseV4.getIconFactory().getFolderIcon());
this.pwDatabaseV4.setRootGroup(groupV4);
this.pwDatabase = pwDatabaseV4;
}
this.version = pwDatabase.getVersion();
}
private void retrieveDatabaseVersioned(PwDatabase pwDatabase) {
this.version = pwDatabase.getVersion();
switch (version) {
case V3:
pwDatabaseV3 = (PwDatabaseV3) pwDatabase;
break;
case V4:
pwDatabaseV4 = (PwDatabaseV4) pwDatabase;
break;
}
}
@@ -187,17 +198,11 @@ public class Database {
bis.reset(); // Return to the start
pwDatabase = databaseImporter.openDatabase(bis, password, keyFileInputStream, progressTaskUpdater);
retrieveDatabaseVersioned(pwDatabase);
if ( pwDatabase != null ) {
try {
passwordEncodingError = !pwDatabase.validatePasswordEncoding(password);
switch (pwDatabase.getVersion()) {
case V3:
searchHelper = new SearchDbHelper.SearchDbHelperV3(ctx);
break;
case V4:
searchHelper = new SearchDbHelper.SearchDbHelperV4(ctx);
break;
}
searchHelper = new SearchDbHelper(ctx);
loaded = true;
} catch (Exception e) {
Log.e(TAG, "Load can't be performed with this Database version", e);
@@ -211,22 +216,12 @@ public class Database {
}
public PwGroupInterface search(String str, int max) {
if (searchHelper == null) { return null; }
try {
switch (pwDatabase.getVersion()) {
case V3:
return ((SearchDbHelper.SearchDbHelperV3) searchHelper).search(((PwDatabaseV3) pwDatabase), str, max);
case V4:
return ((SearchDbHelper.SearchDbHelperV4) searchHelper).search(((PwDatabaseV4) pwDatabase), str, max);
}
} catch (Exception e) {
Log.e(TAG, "Search can't be performed with this SearchHelper", e);
}
return null;
if (searchHelper == null)
return null;
return searchHelper.search(pwDatabase, str, max);
}
public Cursor searchEntry(String query) {
PwVersion version = pwDatabase.getVersion();
switch (version) {
case V3:
EntryCursorV3 cursorV3 = new EntryCursorV3();
@@ -262,7 +257,7 @@ public class Database {
PwIconFactory iconFactory = pwDatabase.getIconFactory();
PwEntryInterface pwEntry = createEntry();
try {
switch (pwDatabase.getVersion()) {
switch (version) {
case V3:
((EntryCursorV3) cursor).populateEntry((PwEntryV3) pwEntry, iconFactory);
break;
@@ -339,8 +334,8 @@ public class Database {
public void closeAndClear(Context context) {
drawFactory.clearCache();
// Delete the cache of the database if present
if (pwDatabase != null)
pwDatabase.clearCache();
if (pwDatabaseV4 != null)
pwDatabaseV4.clearCache();
// In all cases, delete all the files in the temp dir
try {
FileUtils.cleanDirectory(context.getFilesDir());
@@ -349,17 +344,19 @@ public class Database {
}
pwDatabase = null;
pwDatabaseV3 = null;
pwDatabaseV4 = null;
mUri = null;
loaded = false;
passwordEncodingError = false;
}
public String getVersion() {
return pwDatabase.getVersion().toString();
return version.toString();
}
public boolean containsName() {
switch (pwDatabase.getVersion()) {
switch (version) {
default:
return false;
case V4:
@@ -368,26 +365,25 @@ public class Database {
}
public String getName() {
switch (pwDatabase.getVersion()) {
switch (version) {
default:
return "";
case V4:
return ((PwDatabaseV4) pwDatabase).getName();
return pwDatabaseV4.getName();
}
}
public void assignName(String name) {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
PwDatabaseV4 databaseV4 = ((PwDatabaseV4) pwDatabase);
databaseV4.setName(name);
databaseV4.setNameChanged(new PwDate());
pwDatabaseV4.setName(name);
pwDatabaseV4.setNameChanged(new PwDate());
break;
}
}
public boolean containsDescription() {
switch (pwDatabase.getVersion()) {
switch (version) {
default:
return false;
case V4:
@@ -396,36 +392,36 @@ public class Database {
}
public String getDescription() {
switch (pwDatabase.getVersion()) {
switch (version) {
default:
return "";
case V4:
return ((PwDatabaseV4) pwDatabase).getDescription();
return pwDatabaseV4.getDescription();
}
}
public void assignDescription(String description) {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
((PwDatabaseV4) pwDatabase).setDescription(description);
((PwDatabaseV4) pwDatabase).setDescriptionChanged(new PwDate());
pwDatabaseV4.setDescription(description);
pwDatabaseV4.setDescriptionChanged(new PwDate());
}
}
public String getDefaultUsername() {
switch (pwDatabase.getVersion()) {
switch (version) {
default:
return "";
case V4:
return ((PwDatabaseV4) pwDatabase).getDefaultUserName();
return pwDatabaseV4.getDefaultUserName();
}
}
public void setDefaultUsername(String username) {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
((PwDatabaseV4) pwDatabase).setDefaultUserName(username);
((PwDatabaseV4) pwDatabase).setDefaultUserNameChanged(new PwDate());
pwDatabaseV4.setDefaultUserName(username);
pwDatabaseV4.setDefaultUserNameChanged(new PwDate());
}
}
@@ -442,11 +438,11 @@ public class Database {
}
public void assignEncryptionAlgorithm(PwEncryptionAlgorithm algorithm) {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
((PwDatabaseV4) pwDatabase).setEncryptionAlgorithm(algorithm);
((PwDatabaseV4) pwDatabase).setDataEngine(algorithm.getCipherEngine());
((PwDatabaseV4) pwDatabase).setDataCipher(algorithm.getDataCipher());
pwDatabaseV4.setEncryptionAlgorithm(algorithm);
pwDatabaseV4.setDataEngine(algorithm.getCipherEngine());
pwDatabaseV4.setDataCipher(algorithm.getDataCipher());
}
}
@@ -455,7 +451,7 @@ public class Database {
}
public List<KdfEngine> getAvailableKdfEngines() {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
return KdfFactory.kdfListV4;
case V3:
@@ -469,9 +465,9 @@ public class Database {
}
public KdfEngine getKdfEngine() {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
KdfEngine kdfEngine = ((PwDatabaseV4) pwDatabase).getKdfEngine();
KdfEngine kdfEngine = pwDatabaseV4.getKdfEngine();
if (kdfEngine == null)
return KdfFactory.aesKdf;
return kdfEngine;
@@ -482,12 +478,11 @@ public class Database {
}
public void assignKdfEngine(KdfEngine kdfEngine) {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
PwDatabaseV4 db = ((PwDatabaseV4) pwDatabase);
if (db.getKdfParameters() == null
|| !db.getKdfParameters().getUUID().equals(kdfEngine.getDefaultParameters().getUUID()))
db.setKdfParameters(kdfEngine.getDefaultParameters());
if (pwDatabaseV4.getKdfParameters() == null
|| !pwDatabaseV4.getKdfParameters().getUUID().equals(kdfEngine.getDefaultParameters().getUUID()))
pwDatabaseV4.setKdfParameters(kdfEngine.getDefaultParameters());
setNumberKeyEncryptionRounds(kdfEngine.getDefaultKeyRounds());
setMemoryUsage(kdfEngine.getDefaultMemoryUsage());
setParallelism(kdfEngine.getDefaultParallelism());
@@ -520,17 +515,17 @@ public class Database {
}
public long getMemoryUsage() {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
return ((PwDatabaseV4) pwDatabase).getMemoryUsage();
return pwDatabaseV4.getMemoryUsage();
}
return KdfEngine.UNKNOW_VALUE;
}
public void setMemoryUsage(long memory) {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
((PwDatabaseV4) pwDatabase).setMemoryUsage(memory);
pwDatabaseV4.setMemoryUsage(memory);
}
}
@@ -539,17 +534,17 @@ public class Database {
}
public int getParallelism() {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
return ((PwDatabaseV4) pwDatabase).getParallelism();
return pwDatabaseV4.getParallelism();
}
return KdfEngine.UNKNOW_VALUE;
}
public void setParallelism(int parallelism) {
switch (pwDatabase.getVersion()) {
switch (version) {
case V4:
((PwDatabaseV4) pwDatabase).setParallelism(parallelism);
pwDatabaseV4.setParallelism(parallelism);
}
}
@@ -576,7 +571,7 @@ public class Database {
public PwEntryInterface createEntry() {
try {
switch (pwDatabase.getVersion()) {
switch (version) {
case V3:
return new PwEntryV3();
case V4:
@@ -591,7 +586,7 @@ public class Database {
public PwGroupInterface createGroup() {
PwGroupInterface newPwGroup = null;
try {
switch (pwDatabase.getVersion()) {
switch (version) {
case V3:
newPwGroup = new PwGroupV3();
case V4:
@@ -644,43 +639,9 @@ public class Database {
}
}
public boolean canRecycle(PwEntryInterface entry) {
try {
pwDatabase.canRecycle(entry);
} catch (Exception e) {
Log.e(TAG, "This version of PwEntry can't be recycled", e);
}
return false;
}
public boolean canRecycle(PwGroupInterface group) {
try {
pwDatabase.canRecycle(group);
} catch (Exception e) {
Log.e(TAG, "This version of PwGroup can't be recycled", e);
}
return false;
}
public void recycle(PwEntryInterface entry) {
try {
pwDatabase.recycle(entry);
} catch (Exception e) {
Log.e(TAG, "This version of PwEntry can't be recycled", e);
}
}
public void recycle(PwGroupInterface group) {
try {
pwDatabase.recycle(group);
} catch (Exception e) {
Log.e(TAG, "This version of PwGroup can't be recycled", e);
}
}
public void updateEntry(PwEntryInterface oldEntry, PwEntryInterface newEntry) {
try {
switch (pwDatabase.getVersion()) {
switch (version) {
case V3:
((PwEntryV3) oldEntry).updateWith((PwEntryV3) newEntry);
break;
@@ -695,7 +656,7 @@ public class Database {
public void updateGroup(PwGroupInterface oldGroup, PwGroupInterface newGroup) {
try {
switch (pwDatabase.getVersion()) {
switch (version) {
case V3:
((PwGroupV3) oldGroup).updateWith((PwGroupV3) newGroup);
break;
@@ -716,12 +677,12 @@ public class Database {
public @Nullable PwEntryInterface copyEntry(PwEntryInterface entryToCopy, PwGroupInterface newParent) {
try {
PwEntryInterface entryCopied = null;
switch (pwDatabase.getVersion()) {
switch (version) {
case V3:
entryCopied = ((PwEntryV3) entryToCopy).clone();
entryCopied = entryToCopy.duplicate();
break;
case V4:
entryCopied = ((PwEntryV4) entryToCopy).clone();
entryCopied = entryToCopy.duplicate();
break;
}
entryCopied.setNodeId(new PwNodeIdUUID());
@@ -745,98 +706,143 @@ public class Database {
}
public void deleteEntry(PwEntryInterface entry) {
try {
PwGroupInterface parent = entry.getParent();
removeEntryFrom(entry, parent);
} catch (Exception e) {
Log.e(TAG, "This version of PwEntry can't be deleted", e);
}
removeEntryFrom(entry, entry.getParent());
}
public void deleteGroup(PwGroupInterface group) {
try {
PwGroupInterface.doForEachChildAndForRoot(group,
new EntryHandler<PwEntryInterface>() {
@Override
public boolean operate(PwEntryInterface entry) {
deleteEntry(entry);
return true;
}
},
new GroupHandler<PwGroupInterface>() {
@Override
public boolean operate(PwGroupInterface group) {
PwGroupInterface parent = group.getParent();
removeGroupFrom(group, parent);
return true;
}
});
} catch (Exception e) {
Log.e(TAG, "This version of PwGroup can't be deleted", e);
}
PwGroupInterface.doForEachChildAndForRoot(group,
new EntryHandler<PwEntryInterface>() {
@Override
public boolean operate(PwEntryInterface entry) {
deleteEntry(entry);
return true;
}
},
new GroupHandler<PwGroupInterface>() {
@Override
public boolean operate(PwGroupInterface group) {
PwGroupInterface parent = group.getParent();
removeGroupFrom(group, parent);
return true;
}
});
}
public void undoDeleteEntry(PwEntryInterface entry, PwGroupInterface parent) {
pwDatabase.undoDeleteEntryFrom(entry, parent);
}
public void undoDeleteGroup(PwGroupInterface group, PwGroupInterface parent) {
pwDatabase.undoDeleteGroup(group, parent);
}
/**
* Determine if RecycleBin is available or not for this version of database
* @return true if RecycleBin available
*/
public boolean isRecycleBinAvailable() {
return pwDatabase.isRecycleBinAvailable();
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
return true;
}
}
return false;
}
public boolean isRecycleBinEnabled() {
return pwDatabase.isRecycleBinEnabled();
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
return pwDatabaseV4.isRecycleBinEnabled();
}
}
return false;
}
public PwGroupInterface getRecycleBin() {
switch (pwDatabase.getVersion()) {
case V4:
return ((PwDatabaseV4) pwDatabase).getRecycleBin();
}
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
return pwDatabaseV4.getRecycleBin();
}
}
return null;
}
public boolean canRecycle(PwEntryInterface entry) {
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
return pwDatabaseV4.canRecycle(entry);
}
}
return false;
}
public boolean canRecycle(PwGroupInterface group) {
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
return pwDatabaseV4.canRecycle(group);
}
}
return false;
}
public void recycle(PwEntryInterface entry) {
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
pwDatabaseV4.recycle(entry);
break;
}
}
}
public void recycle(PwGroupInterface group) {
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
pwDatabaseV4.recycle(group);
break;
}
}
}
public void undoRecycle(PwEntryInterface entry, PwGroupInterface parent) {
try {
pwDatabase.undoRecycle(entry, parent);
} catch (Exception e) {
Log.e(TAG, "This version of database can't undo Recycle of this version of PwEntry", e);
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
pwDatabaseV4.undoRecycle(entry, parent);
break;
}
}
}
public void undoRecycle(PwGroupInterface group, PwGroupInterface parent) {
try {
pwDatabase.undoRecycle(group, parent);
} catch (Exception e) {
Log.e(TAG, "This version of database can't undo Recycle of this version of PwGroup", e);
}
}
public void undoDeleteEntry(PwEntryInterface entry, PwGroupInterface parent) {
try {
pwDatabase.undoDeleteEntryFrom(entry, parent);
} catch (Exception e) {
Log.e(TAG, "This version of database can't undo the deletion of this version of PwEntry", e);
}
}
public void undoDeleteGroup(PwGroupInterface group, PwGroupInterface parent) {
try {
pwDatabase.undoDeleteGroup(group, parent);
} catch (Exception e) {
Log.e(TAG, "This version of database can't undo the deletion of this version of PwGroup", e);
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
pwDatabaseV4.undoRecycle(group, parent);
break;
}
}
}
public void startManageEntry(PwEntryInterface entry) {
if (pwDatabase != null) {
switch (pwDatabase.getVersion()) {
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
((PwEntryV4) entry).startToManageFieldReferences((PwDatabaseV4) pwDatabase);
((PwEntryV4) entry).startToManageFieldReferences(pwDatabaseV4);
break;
}
}
}
public void stopManageEntry(PwEntryInterface entry) {
if (pwDatabase != null) {
switch (pwDatabase.getVersion()) {
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
((PwEntryV4) entry).stopToManageFieldReferences();
break;
@@ -845,10 +851,10 @@ public class Database {
}
public void createBackupOf(PwEntryInterface entry) {
if (pwDatabase != null) {
switch (pwDatabase.getVersion()) {
if (pwDatabaseV4 != null) {
switch (version) {
case V4:
((PwEntryV4) entry).createBackup((PwDatabaseV4) pwDatabase);
((PwEntryV4) entry).createBackup(pwDatabaseV4);
break;
}
}

View File

@@ -355,68 +355,7 @@ public abstract class PwDatabase {
public abstract boolean isBackup(PwGroupInterface group);
/*
* -------------------------------------
* RecycleBin
* -------------------------------------
*/
/**
* Determine if RecycleBin is available or not for this version of database
* @return true if RecycleBin enable
*/
protected boolean isRecycleBinAvailable() {
return false;
}
/**
* Determine if RecycleBin is enable or not
* @return true if RecycleBin enable, false if is not available or not enable
*/
protected boolean isRecycleBinEnabled() {
return false;
}
/**
* Define if a Group must be delete or recycle
* @param group Group to remove
* @return true if group can be recycle, false elsewhere
*/
protected boolean canRecycle(PwGroupInterface group) {
return false;
}
/**
* Define if an Entry must be delete or recycle
* @param entry Entry to remove
* @return true if entry can be recycle, false elsewhere
*/
protected boolean canRecycle(PwEntryInterface entry) {
return false;
}
protected void recycle(PwGroupInterface group) {
// Assume calls to this are protected by calling inRecyleBin
throw new RuntimeException("Call not valid for .kdb databases.");
}
protected void recycle(PwEntryInterface entry) {
// Assume calls to this are protected by calling inRecyleBin
throw new RuntimeException("Call not valid for .kdb databases.");
}
protected void undoRecycle(PwGroupInterface group, PwGroupInterface origParent) {
throw new RuntimeException("Call not valid for .kdb databases.");
}
protected void undoRecycle(PwEntryInterface entry, PwGroupInterface origParent) {
throw new RuntimeException("Call not valid for .kdb databases.");
}
public boolean isGroupSearchable(PwGroupInterface group, boolean omitBackup) {
return group != null;
}
public abstract void clearCache();
}

View File

@@ -177,7 +177,6 @@ public class PwDatabaseV3 extends PwDatabase {
}
group = group.getParent();
}
return false;
}
@@ -186,10 +185,6 @@ public class PwDatabaseV3 extends PwDatabase {
if (!super.isGroupSearchable(group, omitBackup)) {
return false;
}
return !(omitBackup && isBackup(group));
}
@Override
public void clearCache() {}
}

View File

@@ -20,7 +20,7 @@
package com.kunzisoft.keepass.database.element;
import android.util.Log;
import biz.source_code.base64Coder.Base64Coder;
import com.kunzisoft.keepass.collections.VariantDictionary;
import com.kunzisoft.keepass.crypto.CryptoUtil;
import com.kunzisoft.keepass.crypto.engine.AesEngine;
@@ -28,37 +28,19 @@ import com.kunzisoft.keepass.crypto.engine.CipherEngine;
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine;
import com.kunzisoft.keepass.crypto.keyDerivation.KdfFactory;
import com.kunzisoft.keepass.crypto.keyDerivation.KdfParameters;
import com.kunzisoft.keepass.database.BinaryPool;
import com.kunzisoft.keepass.database.EntryHandler;
import com.kunzisoft.keepass.database.GroupHandler;
import com.kunzisoft.keepass.database.MemoryProtectionConfig;
import com.kunzisoft.keepass.database.PwCompressionAlgorithm;
import com.kunzisoft.keepass.database.*;
import com.kunzisoft.keepass.database.exception.InvalidKeyFileException;
import com.kunzisoft.keepass.database.exception.UnknownKDF;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.w3c.dom.*;
import javax.annotation.Nullable;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import biz.source_code.base64Coder.Base64Coder;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
public class PwDatabaseV4 extends PwDatabase {
@@ -536,7 +518,9 @@ public class PwDatabaseV4 extends PwDatabase {
if (getRecycleBin() == null) {
// Create recycle bin
PwGroupV4 recycleBin = new PwGroupV4(RECYCLEBIN_NAME, iconFactory.getTrashIcon());
PwGroupV4 recycleBin = new PwGroupV4();
recycleBin.setTitle(RECYCLEBIN_NAME);
recycleBin.setIconStandard(iconFactory.getTrashIcon());
recycleBin.setEnableAutoType(false);
recycleBin.setEnableSearching(false);
recycleBin.setExpanded(false);
@@ -554,12 +538,10 @@ public class PwDatabaseV4 extends PwDatabase {
this.recycleBinUUID = recycleBinUUID;
}
@Override
public boolean isRecycleBinAvailable() {
return true;
}
@Override
/**
* Determine if RecycleBin is enable or not
* @return true if RecycleBin enable, false if is not available or not enable
*/
public boolean isRecycleBinEnabled() {
return recycleBinEnabled;
}
@@ -577,7 +559,11 @@ public class PwDatabaseV4 extends PwDatabase {
this.recycleBinChanged = recycleBinChanged;
}
@Override
/**
* Define if a Group must be delete or recycle
* @param group Group to remove
* @return true if group can be recycle, false elsewhere
*/
public boolean canRecycle(PwGroupInterface group) {
if (!recycleBinEnabled) {
return false;
@@ -586,7 +572,11 @@ public class PwDatabaseV4 extends PwDatabase {
return (recycle == null) || (!group.isContainedIn(recycle));
}
@Override
/**
* Define if an Entry must be delete or recycle
* @param entry Entry to remove
* @return true if entry can be recycle, false elsewhere
*/
public boolean canRecycle(PwEntryInterface entry) {
if (!recycleBinEnabled) {
return false;
@@ -595,7 +585,6 @@ public class PwDatabaseV4 extends PwDatabase {
return (parent != null) && canRecycle(parent);
}
@Override
public void recycle(PwGroupInterface group) {
ensureRecycleBin();
@@ -608,7 +597,6 @@ public class PwDatabaseV4 extends PwDatabase {
// TODO ? group.touchLocation();
}
@Override
public void recycle(PwEntryInterface entry) {
ensureRecycleBin();
@@ -621,7 +609,6 @@ public class PwDatabaseV4 extends PwDatabase {
entry.touchLocation();
}
@Override
public void undoRecycle(PwGroupInterface group, PwGroupInterface origParent) {
PwGroupInterface recycleBin = getRecycleBin();
@@ -630,7 +617,6 @@ public class PwDatabaseV4 extends PwDatabase {
addGroupTo(group, origParent);
}
@Override
public void undoRecycle(PwEntryInterface entry, PwGroupInterface origParent) {
PwGroupInterface recycleBin = getRecycleBin();
@@ -693,7 +679,6 @@ public class PwDatabaseV4 extends PwDatabase {
if (!super.isGroupSearchable(group, omitBackup)) {
return false;
}
return group.isSearchingEnabled();
}
@@ -702,7 +687,6 @@ public class PwDatabaseV4 extends PwDatabase {
return true;
}
@Override
public void clearCache() {
binPool.clear();
}

View File

@@ -134,7 +134,7 @@ public class PwEntryV3 extends PwNode<UUID> implements PwEntryInterface {
};
public void updateWith(PwEntryV3 source) {
super.assign(source);
super.updateWith(source);
title = source.title;
username = source.username;
int passLen = source.password.length;

View File

@@ -122,7 +122,7 @@ public class PwEntryV4 extends PwNode<UUID> implements ITimeLogger, PwEntryInte
};
public void updateWith(PwEntryV4 source) {
super.assign(source);
super.updateWith(source);
customIcon = source.customIcon;
usageCount = source.usageCount;
parentGroupLastMod = source.parentGroupLastMod;

View File

@@ -0,0 +1,98 @@
package com.kunzisoft.keepass.database.element;
import android.os.Parcel;
import java.util.ArrayList;
import java.util.List;
public abstract class PwGroup<Id> extends PwNode<Id> implements PwGroupInterface {
private String title = "";
transient private List<PwGroupInterface> childGroups = new ArrayList<>();
transient private List<PwEntryInterface> childEntries = new ArrayList<>();
public PwGroup() {
super();
}
public PwGroup(Parcel in) {
super(in);
title = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(title);
}
protected void updateWith(PwGroup source) {
super.updateWith(source);
title = source.title;
}
@Override
public String getTitle() {
return title;
}
@Override
public void setTitle(String name) {
this.title = name;
}
@Override
public List<PwGroupInterface> getChildGroups() {
return childGroups;
}
@Override
public List<PwEntryInterface> getChildEntries() {
return childEntries;
}
@Override
public void addChildGroup(PwGroupInterface group) {
this.childGroups.add(group);
}
@Override
public void addChildEntry(PwEntryInterface entry) {
this.childEntries.add(entry);
}
@Override
public void removeChildGroup(PwGroupInterface group) {
this.childGroups.remove(group);
}
@Override
public void removeChildEntry(PwEntryInterface entry) {
this.childEntries.remove(entry);
}
@Override
public int getLevel() {
return -1;
}
@Override
public void setLevel(int level) {
// Do nothing here
}
@Override
public List<PwNodeInterface> getChildrenWithoutMetastream() {
List<PwNodeInterface> children = new ArrayList<>(childGroups);
for(PwEntryInterface child : childEntries) {
if (!child.isMetaStream())
children.add(child);
}
return children;
}
@Override
public String toString() {
return getTitle();
}
}

View File

@@ -25,8 +25,6 @@ public interface PwGroupInterface extends PwNodeInterface {
void removeChildEntry(PwEntryInterface entry);
boolean containsParent();
/**
* Filter MetaStream entries and return children
* @return List of direct children (one level below) as PwNode

View File

@@ -22,17 +22,8 @@ package com.kunzisoft.keepass.database.element;
import android.os.Parcel;
import java.util.ArrayList;
import java.util.List;
public class PwGroupV3 extends PwGroup<Integer> {
public class PwGroupV3 extends PwNode<Integer> implements PwGroupInterface {
// TODO verify children not needed
transient private List<PwGroupInterface> childGroups = new ArrayList<>();
transient private List<PwEntryInterface> childEntries = new ArrayList<>();
// for tree traversing
private String title = "";
private int level = 0; // short
/** Used by KeePass internally, don't use */
private int flags;
@@ -48,7 +39,6 @@ public class PwGroupV3 extends PwNode<Integer> implements PwGroupInterface {
public PwGroupV3(Parcel in) {
super(in);
title = in.readString();
level = in.readInt();
flags = in.readInt();
}
@@ -56,7 +46,6 @@ public class PwGroupV3 extends PwNode<Integer> implements PwGroupInterface {
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(title);
dest.writeInt(level);
dest.writeInt(flags);
}
@@ -74,8 +63,7 @@ public class PwGroupV3 extends PwNode<Integer> implements PwGroupInterface {
};
protected void updateWith(PwGroupV3 source) {
super.assign(source);
title = source.title;
super.updateWith(source);
level = source.level;
flags = source.flags;
}
@@ -137,61 +125,6 @@ public class PwGroupV3 extends PwNode<Integer> implements PwGroupInterface {
this.flags = flags;
}
@Override
public String toString() {
return getTitle();
}
@Override
public String getTitle() {
return title;
}
@Override
public void setTitle(String title) {
this.title = title;
}
@Override
public List<PwGroupInterface> getChildGroups() {
return childGroups;
}
@Override
public List<PwEntryInterface> getChildEntries() {
return childEntries;
}
@Override
public void addChildGroup(PwGroupInterface group) {
this.childGroups.add(group);
}
@Override
public void addChildEntry(PwEntryInterface entry) {
this.childEntries.add(entry);
}
@Override
public void removeChildGroup(PwGroupInterface group) {
this.childGroups.remove(group);
}
@Override
public void removeChildEntry(PwEntryInterface entry) {
this.childEntries.remove(entry);
}
@Override
public List<PwNodeInterface> getChildrenWithoutMetastream() {
List<PwNodeInterface> children = new ArrayList<>(childGroups);
for(PwEntryInterface child : childEntries) {
if (!child.isMetaStream())
children.add(child);
}
return children;
}
@Override
public boolean allowAddEntryIfIsRoot() {
return false;

View File

@@ -20,24 +20,16 @@
package com.kunzisoft.keepass.database.element;
import android.os.Parcel;
import com.kunzisoft.keepass.database.ITimeLogger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class PwGroupV4 extends PwNode<UUID> implements ITimeLogger, PwGroupInterface {
public class PwGroupV4 extends PwGroup<UUID> implements ITimeLogger {
public static final boolean DEFAULT_SEARCHING_ENABLED = true;
// TODO verify children not needed
transient private List<PwGroupInterface> childGroups = new ArrayList<>();
transient private List<PwEntryInterface> childEntries = new ArrayList<>();
private String title = "";
private PwIconCustom customIcon = PwIconCustom.ZERO;
private long usageCount = 0;
private PwDate locationChangeDate = new PwDate();
@@ -58,16 +50,9 @@ public class PwGroupV4 extends PwNode<UUID> implements ITimeLogger, PwGroupInter
public PwGroupV4() {
super();
}
public PwGroupV4(String title, PwIconStandard icon) {
super();
this.title = title;
this.icon = icon;
}
public PwGroupV4(Parcel in) {
super(in);
title = in.readString();
customIcon = in.readParcelable(PwIconCustom.class.getClassLoader());
usageCount = in.readLong();
locationChangeDate = in.readParcelable(PwDate.class.getClassLoader());
@@ -86,7 +71,6 @@ public class PwGroupV4 extends PwNode<UUID> implements ITimeLogger, PwGroupInter
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(title);
dest.writeParcelable(customIcon, flags);
dest.writeLong(usageCount);
dest.writeParcelable(locationChangeDate, flags);
@@ -113,8 +97,7 @@ public class PwGroupV4 extends PwNode<UUID> implements ITimeLogger, PwGroupInter
};
protected void updateWith(PwGroupV4 source) {
super.assign(source);
title = source.title;
super.updateWith(source);
customIcon = source.customIcon;
usageCount = source.usageCount;
locationChangeDate = source.locationChangeDate;
@@ -297,66 +280,6 @@ public class PwGroupV4 extends PwNode<UUID> implements ITimeLogger, PwGroupInter
return true;
}
@Override
public String getTitle() {
return title;
}
@Override
public void setTitle(String name) {
this.title = name;
}
@Override
public List<PwGroupInterface> getChildGroups() {
return childGroups;
}
@Override
public List<PwEntryInterface> getChildEntries() {
return childEntries;
}
@Override
public int getLevel() {
return -1; // TODO Level
}
@Override
public void setLevel(int level) {
// Do nothing here
}
@Override
public void addChildGroup(PwGroupInterface group) {
this.childGroups.add(group);
}
@Override
public void addChildEntry(PwEntryInterface entry) {
this.childEntries.add(entry);
}
@Override
public void removeChildGroup(PwGroupInterface group) {
this.childGroups.remove(group);
}
@Override
public void removeChildEntry(PwEntryInterface entry) {
this.childEntries.remove(entry);
}
@Override
public List<PwNodeInterface> getChildrenWithoutMetastream() {
List<PwNodeInterface> children = new ArrayList<>(childGroups);
for(PwEntryInterface child : childEntries) {
if (!child.isMetaStream())
children.add(child);
}
return children;
}
@Override
public boolean allowAddEntryIfIsRoot() {
return true;

View File

@@ -82,7 +82,7 @@ public abstract class PwNode<IdType> implements PwNodeInterface, Parcelable, Clo
return 0;
}
protected void assign(PwNode source) {
protected void updateWith(PwNode source) {
this.nodeId = source.nodeId;
this.parent = source.parent;
this.icon = source.icon;

View File

@@ -37,6 +37,8 @@ public interface PwNodeInterface extends SmallTimeInterface, Parcelable {
*/
void setParent(PwGroupInterface prt);
boolean containsParent();
void touch(boolean modified, boolean touchParents);
boolean isContainedIn(PwGroupInterface container);

View File

@@ -29,24 +29,20 @@ import java.io.IOException;
import java.io.InputStream;
public class ImporterFactory {
public static Importer createImporter(InputStream is, File streamDir) throws InvalidDBSignatureException, IOException {
return createImporter(is, streamDir,false);
}
public static Importer createImporter(InputStream is, File streamDir, boolean debug) throws InvalidDBSignatureException, IOException {
int sig1 = LEDataInputStream.readInt(is);
int sig2 = LEDataInputStream.readInt(is);
if ( PwDbHeaderV3.matchesHeader(sig1, sig2) ) {
if (debug) {
return new ImporterV3Debug();
}
return new ImporterV3();
} else if ( PwDbHeaderV4.matchesHeader(sig1, sig2) ) {
return new ImporterV4(streamDir);
}
public static Importer createImporter(InputStream is, File streamDir, boolean debug) throws InvalidDBSignatureException, IOException {
int sig1 = LEDataInputStream.readInt(is);
int sig2 = LEDataInputStream.readInt(is);
throw new InvalidDBSignatureException();
}
if ( PwDbHeaderV3.matchesHeader(sig1, sig2) ) {
if (debug) {
return new ImporterV3Debug();
}
return new ImporterV3();
} else if ( PwDbHeaderV4.matchesHeader(sig1, sig2) ) {
return new ImporterV4(streamDir);
}
throw new InvalidDBSignatureException();
}
}

View File

@@ -22,13 +22,10 @@ package com.kunzisoft.keepass.database.search;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.kunzisoft.keepass.R;
import com.kunzisoft.keepass.database.EntryHandler;
import com.kunzisoft.keepass.database.GroupHandler;
import com.kunzisoft.keepass.database.element.PwDatabase;
import com.kunzisoft.keepass.database.element.PwDatabaseV3;
import com.kunzisoft.keepass.database.element.PwDatabaseV4;
import com.kunzisoft.keepass.database.element.PwEntryInterface;
import com.kunzisoft.keepass.database.element.PwGroupInterface;
import com.kunzisoft.keepass.database.iterator.EntrySearchStringIterator;
@@ -36,21 +33,21 @@ import com.kunzisoft.keepass.database.iterator.EntrySearchStringIterator;
import java.util.Iterator;
import java.util.Locale;
public class SearchDbHelper<PwDatabaseVersion extends PwDatabase> {
public class SearchDbHelper {
private final Context mCtx;
private final Context mContext;
private int incrementEntry = 0;
public SearchDbHelper(Context ctx) {
this.mCtx = ctx;
public SearchDbHelper(Context context) {
this.mContext = context;
}
private boolean omitBackup() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mCtx);
return prefs.getBoolean(mCtx.getString(R.string.omitbackup_key), mCtx.getResources().getBoolean(R.bool.omitbackup_default));
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
return prefs.getBoolean(mContext.getString(R.string.omitbackup_key), mContext.getResources().getBoolean(R.bool.omitbackup_default));
}
public PwGroupInterface search(PwDatabaseVersion pm, String qStr, int max) {
public PwGroupInterface search(PwDatabase pm, String qStr, int max) {
PwGroupInterface searchGroup = pm.createGroup();
searchGroup.setTitle("\"" + qStr + "\"");
@@ -101,19 +98,4 @@ public class SearchDbHelper<PwDatabaseVersion extends PwDatabase> {
}
return false;
}
public static class SearchDbHelperV3 extends SearchDbHelper<PwDatabaseV3>{
public SearchDbHelperV3(Context ctx) {
super(ctx);
}
}
public static class SearchDbHelperV4 extends SearchDbHelper<PwDatabaseV4>{
public SearchDbHelperV4(Context ctx) {
super(ctx);
}
}
}

View File

@@ -347,7 +347,6 @@ public class NestedSettingsFragment extends PreferenceFragmentCompat
// TODO Recycle
dbGeneralPrefCategory.removePreference(recycleBinPref); // To delete
if (database.isRecycleBinAvailable()) {
recycleBinPref.setChecked(database.isRecycleBinEnabled());
recycleBinPref.setEnabled(false);
} else {