Kotlinized PwNode PwEntry PwGroup

This commit is contained in:
J-Jamet
2019-06-02 02:41:51 +02:00
parent 575e967627
commit 17ec357c1b
26 changed files with 917 additions and 1313 deletions

View File

@@ -45,7 +45,7 @@ public class PwEntryTestV4 extends TestCase {
entry.getAutoType().obfuscationOptions = 123412432109L;
entry.getAutoType().put("key", "value");
entry.setBackgroupColor("blue");
entry.setBackgroundColor("blue");
entry.putProtectedBinary("key1", new ProtectedBinary(false, new byte[] {0,1}));
entry.setIconCustom(new PwIconCustom(UUID.randomUUID(), new byte[0]));
entry.setForegroundColor("red");

View File

@@ -21,6 +21,7 @@ package com.kunzisoft.keepass.database;
import android.os.Parcel;
import android.os.Parcelable;
import com.kunzisoft.keepass.database.security.ProtectedString;
import com.kunzisoft.keepass.utils.MemUtil;

View File

@@ -7,8 +7,8 @@ public class EntryCursorV3 extends EntryCursor<PwEntryV3> {
public void addEntry(PwEntryV3 entry) {
addRow(new Object[] {entryId,
entry.getNodeId().getId().getMostSignificantBits(),
entry.getNodeId().getId().getLeastSignificantBits(),
entry.getId().getMostSignificantBits(),
entry.getId().getLeastSignificantBits(),
entry.getTitle(),
entry.getIcon().getIconId(),
PwDatabase.UUID_ZERO.getMostSignificantBits(),

View File

@@ -17,8 +17,8 @@ public class EntryCursorV4 extends EntryCursor<PwEntryV4> {
public void addEntry(PwEntryV4 entry) {
addRow(new Object[] {entryId,
entry.getNodeId().getId().getMostSignificantBits(),
entry.getNodeId().getId().getLeastSignificantBits(),
entry.getId().getMostSignificantBits(),
entry.getId().getLeastSignificantBits(),
entry.getTitle(),
entry.getIcon().getIconId(),
entry.getIconCustom().getUuid().getMostSignificantBits(),

View File

@@ -64,9 +64,9 @@ class Database {
var loaded = false
val iconFactory: PwIconFactory?
val iconFactory: PwIconFactory
get() {
return pwDatabaseV3?.getIconFactory() ?: pwDatabaseV4?.getIconFactory()
return pwDatabaseV3?.getIconFactory() ?: pwDatabaseV4?.getIconFactory() ?: PwIconFactory()
}
val name: String
@@ -189,7 +189,7 @@ class Database {
val databaseV4 = PwDatabaseV4()
val groupV4 = databaseV4.createGroup()
groupV4.title = dbNameFromPath(databasePath)
groupV4.setIconStandard(databaseV4.getIconFactory().folderIcon)
groupV4.icon = databaseV4.getIconFactory().folderIcon
databaseV4.rootGroup = groupV4
setDatabaseV4(databaseV4)
}
@@ -499,7 +499,14 @@ class Database {
}
fun createEntry(): EntryVersioned? {
pwDatabaseV3 ?: pwDatabaseV4?.let { database ->
pwDatabaseV3?.let { database ->
return EntryVersioned(database.createEntry()).apply {
database.newEntryId()?.let {
nodeId = it
}
}
}
pwDatabaseV4?.let { database ->
return EntryVersioned(database.createEntry()).apply {
database.newEntryId()?.let {
nodeId = it
@@ -511,7 +518,14 @@ class Database {
}
fun createGroup(): GroupVersioned? {
pwDatabaseV3 ?: pwDatabaseV4?.let { database ->
pwDatabaseV3?.let { database ->
return GroupVersioned(database.createGroup()).apply {
database.newGroupId()?.let {
setNodeId(it)
}
}
}
pwDatabaseV4?.let { database ->
return GroupVersioned(database.createGroup()).apply {
database.newGroupId()?.let {
setNodeId(it)
@@ -545,21 +559,25 @@ class Database {
fun addEntryTo(entry: EntryVersioned, parent: GroupVersioned) {
pwDatabaseV3?.addEntryTo(entry.pwEntryV3, parent.pwGroupV3)
pwDatabaseV4?.addEntryTo(entry.pwEntryV4, parent.pwGroupV4)
entry.afterAssignNewParent()
}
fun removeEntryFrom(entry: EntryVersioned, parent: GroupVersioned) {
pwDatabaseV3?.removeEntryFrom(entry.pwEntryV3, parent.pwGroupV3)
pwDatabaseV4?.removeEntryFrom(entry.pwEntryV4, parent.pwGroupV4)
entry.afterAssignNewParent()
}
fun addGroupTo(group: GroupVersioned, parent: GroupVersioned) {
pwDatabaseV3?.addGroupTo(group.pwGroupV3, parent.pwGroupV3)
pwDatabaseV4?.addGroupTo(group.pwGroupV4, parent.pwGroupV4)
group.afterAssignNewParent()
}
fun removeGroupFrom(group: GroupVersioned, parent: GroupVersioned) {
pwDatabaseV3?.removeGroupFrom(group.pwGroupV3, parent.pwGroupV3)
pwDatabaseV4?.removeGroupFrom(group.pwGroupV4, parent.pwGroupV4)
group.afterAssignNewParent()
}
/**

View File

@@ -15,8 +15,12 @@ class EntryVersioned : NodeVersioned, PwEntryInterface<GroupVersioned> {
private set
fun updateWith(entry: EntryVersioned) {
this.pwEntryV3?.updateWith(entry.pwEntryV3)
this.pwEntryV4?.updateWith(entry.pwEntryV4)
entry.pwEntryV3?.let {
this.pwEntryV3?.updateWith(it)
}
entry.pwEntryV4?.let {
this.pwEntryV4?.updateWith(it)
}
}
/**
@@ -71,7 +75,16 @@ class EntryVersioned : NodeVersioned, PwEntryInterface<GroupVersioned> {
}
override var icon: PwIcon
get() = pwEntryV3?.icon ?: pwEntryV4?.icon ?: PwIconStandard()
get() {
var iconGet: PwIcon? = pwEntryV3?.icon
if (iconGet == null)
iconGet = pwEntryV4?.iconCustom
if (iconGet == null || iconGet.isUnknown)
iconGet = pwEntryV4?.icon
if (iconGet == null)
PwIconStandard()
return iconGet!!
}
set(value) {
pwEntryV3?.icon = value
pwEntryV4?.icon = value
@@ -99,13 +112,24 @@ class EntryVersioned : NodeVersioned, PwEntryInterface<GroupVersioned> {
return pwEntryV3?.containsParent() ?: pwEntryV4?.containsParent() ?: false
}
override fun afterAssignNewParent() {
pwEntryV4?.afterChangeParent()
}
override fun touch(modified: Boolean, touchParents: Boolean) {
pwEntryV3?.touch(modified, touchParents)
pwEntryV4?.touch(modified, touchParents)
}
override fun isContainedIn(container: GroupVersioned): Boolean {
return pwEntryV3?.isContainedIn(container.pwGroupV3) ?: pwEntryV4?.isContainedIn(container.pwGroupV4) ?: false
var contained: Boolean? = false
container.pwGroupV3?.let {
contained = pwEntryV3?.isContainedIn(it)
}
container.pwGroupV4?.let {
contained = pwEntryV4?.isContainedIn(it)
}
return contained ?: false
}
override val isSearchingEnabled: Boolean
@@ -174,11 +198,6 @@ class EntryVersioned : NodeVersioned, PwEntryInterface<GroupVersioned> {
pwEntryV4?.notes = value
}
override fun touchLocation() {
pwEntryV3?.touchLocation()
pwEntryV4?.touchLocation()
}
private fun isTan(): Boolean {
return title == PMS_TAN_ENTRY && username.isNotEmpty()
}
@@ -210,6 +229,12 @@ class EntryVersioned : NodeVersioned, PwEntryInterface<GroupVersioned> {
------------
*/
var iconCustom: PwIconCustom
get() = pwEntryV4?.iconCustom ?: PwIconCustom.ZERO
set(value) {
pwEntryV4?.iconCustom = value
}
/**
* Retrieve extra fields to show, key is the label, value is the value of field
* @return Map of label/value
@@ -308,7 +333,7 @@ class EntryVersioned : NodeVersioned, PwEntryInterface<GroupVersioned> {
return arrayOfNulls(size)
}
val PMS_TAN_ENTRY = "<TAN>"
const val PMS_TAN_ENTRY = "<TAN>"
/**
* {@inheritDoc}

View File

@@ -13,8 +13,12 @@ class GroupVersioned : NodeVersioned, PwGroupInterface<GroupVersioned, EntryVers
private set
fun updateWith(group: GroupVersioned) {
this.pwGroupV3?.updateWith(group.pwGroupV3)
this.pwGroupV4?.updateWith(group.pwGroupV4)
group.pwGroupV3?.let {
this.pwGroupV3?.updateWith(it)
}
group.pwGroupV4?.let {
this.pwGroupV4?.updateWith(it)
}
}
/**
@@ -105,13 +109,25 @@ class GroupVersioned : NodeVersioned, PwGroupInterface<GroupVersioned, EntryVers
return pwGroupV3?.containsParent() ?: pwGroupV4?.containsParent() ?: false
}
override fun afterAssignNewParent() {
pwGroupV3?.afterAssignNewParent()
pwGroupV4?.afterAssignNewParent()
}
override fun touch(modified: Boolean, touchParents: Boolean) {
pwGroupV3?.touch(modified, touchParents)
pwGroupV4?.touch(modified, touchParents)
}
override fun isContainedIn(container: GroupVersioned): Boolean {
return pwGroupV3?.isContainedIn(container.pwGroupV3) ?: pwGroupV4?.isContainedIn(container.pwGroupV4) ?: false
var contained: Boolean? = null
container.pwGroupV3?.let {
contained = pwGroupV3?.isContainedIn(it)
}
container.pwGroupV4?.let {
contained = pwGroupV4?.isContainedIn(it)
}
return contained ?: false
}
override val isSearchingEnabled: Boolean
@@ -268,10 +284,6 @@ class GroupVersioned : NodeVersioned, PwGroupInterface<GroupVersioned, EntryVers
pwGroupV4?.nodeId = id
}
fun setIconStandard(icon: PwIconStandard) {
pwGroupV4?.setIconStandard(icon)
}
fun setEnableAutoType(enableAutoType: Boolean?) {
pwGroupV4?.enableAutoType = enableAutoType
}

View File

@@ -529,13 +529,13 @@ public class PwDatabaseV4 extends PwDatabase<PwGroupV4, PwEntryV4> {
PwGroupV4 recycleBin = createGroup();
recycleBin.setTitle(RECYCLEBIN_NAME);
recycleBin.setIconStandard(iconFactory.getTrashIcon());
recycleBin.setIcon(iconFactory.getTrashIcon());
recycleBin.setEnableAutoType(false);
recycleBin.setEnableSearching(false);
recycleBin.setExpanded(false);
addGroupTo(recycleBin, rootGroup);
recycleBinUUID = recycleBin.getNodeId().getId();
recycleBinUUID = recycleBin.getId();
}
}
@@ -601,7 +601,7 @@ public class PwDatabaseV4 extends PwDatabase<PwGroupV4, PwEntryV4> {
addGroupTo(group, getRecycleBin());
// TODO ? group.touchLocation();
// TODO ? group.afterChangeParent();
}
public void recycle(PwEntryV4 entry) {
@@ -611,7 +611,7 @@ public class PwDatabaseV4 extends PwDatabase<PwGroupV4, PwEntryV4> {
addEntryTo(entry, getRecycleBin());
entry.touchLocation();
entry.afterChangeParent();
}
public void undoRecycle(PwGroupV4 group, PwGroupV4 origParent) {
@@ -639,13 +639,13 @@ public class PwDatabaseV4 extends PwDatabase<PwGroupV4, PwEntryV4> {
@Override
public void removeEntryFrom(PwEntryV4 entryToRemove, PwGroupV4 parent) {
super.removeEntryFrom(entryToRemove, parent);
deletedObjects.add(new PwDeletedObject(entryToRemove.getNodeId().getId()));
deletedObjects.add(new PwDeletedObject(entryToRemove.getId()));
}
@Override
public void undoDeleteEntryFrom(PwEntryV4 entry, PwGroupV4 origParent) {
super.undoDeleteEntryFrom(entry, origParent);
deletedObjects.remove(new PwDeletedObject(entry.getNodeId().getId()));
deletedObjects.remove(new PwDeletedObject(entry.getId()));
}
public PwGroupV4 getRecycleBin() { // TODO delete recycle bin preference

View File

@@ -9,6 +9,4 @@ interface PwEntryInterface<ParentGroup> : PwNodeInterface<ParentGroup> {
var url: String
var notes: String
fun touchLocation()
}

View File

@@ -1,299 +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 3 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 <http://www.gnu.org/licenses/>.
*
This file was derived from
Copyright 2007 Naomaru Itoi <nao@phoneid.org>
This file was derived from
Java clone of KeePass - A KeePass file viewer for Java
Copyright 2006 Bill Zwicky <billzwicky@users.sourceforge.net>
This program 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; version 2
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.kunzisoft.keepass.database.element;
import android.os.Parcel;
import android.support.annotation.NonNull;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.UUID;
/**
* Structure containing information about one entry.
*
* <PRE>
* One entry: [FIELDTYPE(FT)][FIELDSIZE(FS)][FIELDDATA(FD)]
* [FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)]...
*
* [ 2 bytes] FIELDTYPE
* [ 4 bytes] FIELDSIZE, size of FIELDDATA in bytes
* [ n bytes] FIELDDATA, n = FIELDSIZE
*
* Notes:
* - Strings are stored in UTF-8 encoded form and are null-terminated.
* - FIELDTYPE can be one of the FT_ constants.
* </PRE>
*
* @author Naomaru Itoi <nao@phoneid.org>
* @author Bill Zwicky <wrzwicky@pobox.com>
* @author Dominik Reichl <dominik.reichl@t-online.de>
* @author Jeremy Jamet <jeremy.jamet@kunzisoft.com>
*/
public class PwEntryV3 extends PwEntry<PwGroupV3, PwEntryV3> {
/** Size of byte buffer needed to hold this struct. */
private static final String PMS_ID_BINDESC = "bin-stream";
private static final String PMS_ID_TITLE = "Meta-Info";
private static final String PMS_ID_USER = "SYSTEM";
private static final String PMS_ID_URL = "$";
private String title = "";
private String username = "";
private byte[] password = new byte[0];
private String url = "";
private String additional = "";
/** A string describing what is in pBinaryData */
private String binaryDesc = "";
private byte[] binaryData = new byte[0];
@NonNull
@Override
protected PwNodeId<UUID> initNodeId() {
return new PwNodeIdUUID();
}
@NonNull
@Override
protected PwNodeId<UUID> copyNodeId(@NonNull PwNodeId<UUID> nodeId) {
return new PwNodeIdUUID(nodeId.getId());
}
public PwEntryV3() {
super();
}
public PwEntryV3(Parcel parcel) {
super(parcel);
title = parcel.readString();
username = parcel.readString();
parcel.readByteArray(password);
url = parcel.readString();
additional = parcel.readString();
binaryDesc = parcel.readString();
parcel.readByteArray(binaryData);
}
@Override
protected PwGroupV3 readParentParcelable(Parcel parcel) {
return parcel.readParcelable(PwGroupV3.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(title);
dest.writeString(username);
dest.writeByteArray(password);
dest.writeString(url);
dest.writeString(additional);
dest.writeString(binaryDesc);
dest.writeByteArray(binaryData);
}
public static final Creator<PwEntryV3> CREATOR = new Creator<PwEntryV3>() {
@Override
public PwEntryV3 createFromParcel(Parcel in) {
return new PwEntryV3(in);
}
@Override
public PwEntryV3[] newArray(int size) {
return new PwEntryV3[size];
}
};
public void updateWith(PwEntryV3 source) {
super.updateWith(source);
title = source.title;
username = source.username;
if (source.password != null) {
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 Type getType() {
return Type.ENTRY;
}
@Override
public String getUsername() {
return username;
}
@Override
public void setUsername(String user) {
username = user;
}
@Override
public String getTitle() {
return title;
}
@Override
public void setTitle(String title) {
this.title = title;
}
@Override
public String getNotes() {
return additional;
}
@Override
public void setNotes(String notes) {
additional = notes;
}
@Override
public String getUrl() {
return url;
}
@Override
public void setUrl(String url) {
this.url = url;
}
/**
* @return the actual password byte array.
*/
@Override
public String getPassword() {
return new String(password);
}
public byte[] getPasswordBytes() {
return password;
}
/**
* fill byte array
*/
private static void fill(byte[] array, byte value) {
for (int i=0; i<array.length; i++)
array[i] = value;
}
/** Securely erase old password before copying new. */
public void setPassword( byte[] buf, int offset, int len ) {
fill(password, (byte)0);
password = new byte[len];
System.arraycopy( buf, offset, password, 0, len );
}
@Override
public void setPassword(String pass) {
byte[] password;
try {
password = pass.getBytes("UTF-8");
setPassword(password, 0, password.length);
} catch (UnsupportedEncodingException e) {
password = pass.getBytes();
setPassword(password, 0, password.length);
}
}
/**
* @return the actual binaryData byte array.
*/
public byte[] getBinaryData() {
return binaryData;
}
/** Securely erase old data before copying new. */
public void setBinaryData( byte[] buf, int offset, int len ) {
if( binaryData != null ) {
fill( binaryData, (byte)0 );
binaryData = null;
}
binaryData = new byte[len];
System.arraycopy( buf, offset, binaryData, 0, len );
}
public String getBinaryDesc() {
return binaryDesc;
}
public void setBinaryDesc(String binaryDesc) {
this.binaryDesc = binaryDesc;
}
// Determine if this is a MetaStream entry
public boolean isMetaStream() {
if (Arrays.equals(binaryData, new byte[0])) return false;
if (additional.isEmpty()) return false;
if (!binaryDesc.equals(PMS_ID_BINDESC)) return false;
if (title.isEmpty()) return false;
if (!title.equals(PMS_ID_TITLE)) return false;
if (username.isEmpty()) return false;
if (!username.equals(PMS_ID_USER)) return false;
if (url.isEmpty()) return false;
if (!url.equals(PMS_ID_URL)) return false;
return getIcon().isMetaStreamIcon();
}
@Override
public boolean isSearchingEnabled() {
return false;
}
@Override
public void touchLocation() {}
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright 2019 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 3 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 <http://www.gnu.org/licenses/>.
*/
package com.kunzisoft.keepass.database.element
import android.os.Parcel
import android.os.Parcelable
import java.io.UnsupportedEncodingException
import java.util.Arrays
import java.util.UUID
/**
* Structure containing information about one entry.
*
* <PRE>
* One entry: [FIELDTYPE(FT)][FIELDSIZE(FS)][FIELDDATA(FD)]
* [FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)]...
*
* [ 2 bytes] FIELDTYPE
* [ 4 bytes] FIELDSIZE, size of FIELDDATA in bytes
* [ n bytes] FIELDDATA, n = FIELDSIZE
*
* Notes:
* - Strings are stored in UTF-8 encoded form and are null-terminated.
* - FIELDTYPE can be one of the FT_ constants.
</PRE> *
*
* @author Naomaru Itoi <nao></nao>@phoneid.org>
* @author Bill Zwicky <wrzwicky></wrzwicky>@pobox.com>
* @author Dominik Reichl <dominik.reichl></dominik.reichl>@t-online.de>
* @author Jeremy Jamet <jeremy.jamet></jeremy.jamet>@kunzisoft.com>
*/
class PwEntryV3 : PwEntry<PwGroupV3, PwEntryV3> {
/** A string describing what is in pBinaryData */
var binaryDesc = ""
/**
* @return the actual binaryData byte array.
*/
var binaryData: ByteArray = ByteArray(0)
private set
// Determine if this is a MetaStream entry
val isMetaStream: Boolean
get() {
if (Arrays.equals(binaryData, ByteArray(0))) return false
if (notes.isEmpty()) return false
if (binaryDesc != PMS_ID_BINDESC) return false
if (title.isEmpty()) return false
if (title != PMS_ID_TITLE) return false
if (username.isEmpty()) return false
if (username != PMS_ID_USER) return false
if (url.isEmpty()) return false
return if (url != PMS_ID_URL) false else icon.isMetaStreamIcon
}
override fun initNodeId(): PwNodeId<UUID> {
return PwNodeIdUUID()
}
override fun copyNodeId(nodeId: PwNodeId<UUID>): PwNodeId<UUID> {
return PwNodeIdUUID(nodeId.id)
}
constructor() : super()
constructor(parcel: Parcel) : super(parcel) {
title = parcel.readString()
username = parcel.readString()
parcel.readByteArray(passwordBytes)
url = parcel.readString()
notes = parcel.readString()
binaryDesc = parcel.readString()
parcel.readByteArray(binaryData)
}
override fun readParentParcelable(parcel: Parcel): PwGroupV3 {
return parcel.readParcelable(PwGroupV3::class.java.classLoader)
}
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeString(title)
dest.writeString(username)
dest.writeByteArray(passwordBytes)
dest.writeString(url)
dest.writeString(notes)
dest.writeString(binaryDesc)
dest.writeByteArray(binaryData)
}
fun updateWith(source: PwEntryV3) {
super.updateWith(source)
title = source.title
username = source.username
val passLen = source.passwordBytes.size
passwordBytes = ByteArray(passLen)
System.arraycopy(source.passwordBytes, 0, passwordBytes, 0, passLen)
url = source.url
notes = source.notes
binaryDesc = source.binaryDesc
val descLen = source.binaryData.size
binaryData = ByteArray(descLen)
System.arraycopy(source.binaryData, 0, binaryData, 0, descLen)
}
override var username = ""
var passwordBytes: ByteArray = ByteArray(0)
private set
/** Securely erase old password before copying new. */
fun setPassword(buf: ByteArray, offset: Int, len: Int) {
fill(passwordBytes, 0.toByte())
passwordBytes = ByteArray(len)
System.arraycopy(buf, offset, passwordBytes, 0, len)
}
/**
* @return the actual password byte array.
*/
override var password: String
get() = String(passwordBytes)
set(pass) {
var password: ByteArray
try {
password = pass.toByteArray(charset("UTF-8"))
setPassword(password, 0, password.size)
} catch (e: UnsupportedEncodingException) {
password = pass.toByteArray()
setPassword(password, 0, password.size)
}
}
override var url = ""
override var notes = ""
override var title = ""
override val type: Type
get() = Type.ENTRY
override val isSearchingEnabled: Boolean
get() = false
fun setBinaryData(buf: ByteArray, offset: Int, len: Int) {
/** Securely erase old data before copying new. */
fill(binaryData, 0.toByte())
binaryData = ByteArray(len)
System.arraycopy(buf, offset, binaryData, 0, len)
}
companion object {
/** Size of byte buffer needed to hold this struct. */
private const val PMS_ID_BINDESC = "bin-stream"
private const val PMS_ID_TITLE = "Meta-Info"
private const val PMS_ID_USER = "SYSTEM"
private const val PMS_ID_URL = "$"
@JvmField
val CREATOR: Parcelable.Creator<PwEntryV3> = object : Parcelable.Creator<PwEntryV3> {
override fun createFromParcel(`in`: Parcel): PwEntryV3 {
return PwEntryV3(`in`)
}
override fun newArray(size: Int): Array<PwEntryV3?> {
return arrayOfNulls(size)
}
}
/**
* fill byte array
*/
private fun fill(array: ByteArray, value: Byte) {
for (i in array.indices)
array[i] = value
}
}
}

View File

@@ -1,503 +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 3 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 <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.database.element;
import android.os.Parcel;
import android.support.annotation.NonNull;
import com.kunzisoft.keepass.database.AutoType;
import com.kunzisoft.keepass.database.ExtraFields;
import com.kunzisoft.keepass.database.security.ProtectedBinary;
import com.kunzisoft.keepass.database.security.ProtectedString;
import com.kunzisoft.keepass.utils.MemUtil;
import com.kunzisoft.keepass.utils.SprEngineV4;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
public class PwEntryV4 extends PwEntry<PwGroupV4, PwEntryV4> implements NodeV4Interface {
public static final String STR_TITLE = "Title";
public static final String STR_USERNAME = "UserName";
public static final String STR_PASSWORD = "Password";
public static final String STR_URL = "URL";
public static final String STR_NOTES = "Notes";
// To decode each field not parcelable
private transient PwDatabaseV4 mDatabase = null;
private transient boolean mDecodeRef = false;
private PwIconCustom customIcon = PwIconCustom.Companion.getZERO();
private long usageCount = 0;
private PwDate parentGroupLastMod = new PwDate();
private Map<String, String> customData = new HashMap<>();
private ExtraFields fields = new ExtraFields();
private HashMap<String, ProtectedBinary> binaries = new HashMap<>();
private String foregroundColor = "";
private String backgroupColor = "";
private String overrideURL = "";
private AutoType autoType = new AutoType();
private ArrayList<PwEntryV4> history = new ArrayList<>();
private String url = "";
private String additional = "";
private String tags = "";
@NonNull
@Override
protected PwNodeId<UUID> initNodeId() {
return new PwNodeIdUUID();
}
@NonNull
@Override
protected PwNodeId<UUID> copyNodeId(@NonNull PwNodeId<UUID> nodeId) {
return new PwNodeIdUUID(nodeId.getId());
}
public PwEntryV4() {
super();
}
public PwEntryV4(Parcel parcel) {
super(parcel);
customIcon = parcel.readParcelable(PwIconCustom.class.getClassLoader());
usageCount = parcel.readLong();
parentGroupLastMod = parcel.readParcelable(PwDate.class.getClassLoader());
customData = MemUtil.readStringParcelableMap(parcel);
fields = parcel.readParcelable(ExtraFields.class.getClassLoader());
// TODO binaries = MemUtil.readStringParcelableMap(parcel, ProtectedBinary.class);
foregroundColor = parcel.readString();
backgroupColor = parcel.readString();
overrideURL = parcel.readString();
autoType = parcel.readParcelable(AutoType.class.getClassLoader());
history = parcel.readArrayList(PwEntryV4.class.getClassLoader()); // TODO verify
url = parcel.readString();
additional = parcel.readString();
tags = parcel.readString();
}
@Override
protected PwGroupV4 readParentParcelable(Parcel parcel) {
return parcel.readParcelable(PwGroupV4.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(customIcon, flags);
dest.writeLong(usageCount);
dest.writeParcelable(parentGroupLastMod, flags);
MemUtil.writeStringParcelableMap(dest, customData);
dest.writeParcelable(fields, flags);
// TODO MemUtil.writeStringParcelableMap(dest, flags, binaries);
dest.writeString(foregroundColor);
dest.writeString(backgroupColor);
dest.writeString(overrideURL);
dest.writeParcelable(autoType, flags);
dest.writeList(history);
dest.writeString(url);
dest.writeString(additional);
dest.writeString(tags);
}
public static final Creator<PwEntryV4> CREATOR = new Creator<PwEntryV4>() {
@Override
public PwEntryV4 createFromParcel(Parcel in) {
return new PwEntryV4(in);
}
@Override
public PwEntryV4[] newArray(int size) {
return new PwEntryV4[size];
}
};
/**
* Update with deep copy of each entry element
* @param source
*/
public void updateWith(PwEntryV4 source) {
super.updateWith(source);
customIcon = new PwIconCustom(source.customIcon);
usageCount = source.usageCount;
parentGroupLastMod = new PwDate(source.parentGroupLastMod);
// Add all custom elements in map
customData.clear();
for (Map.Entry<String, String> entry : source.customData.entrySet()) {
customData.put(entry.getKey(), entry.getValue());
}
fields = new ExtraFields(source.fields);
for (Map.Entry<String, ProtectedBinary> entry: source.binaries.entrySet()) {
binaries.put(entry.getKey(), new ProtectedBinary(entry.getValue()));
}
foregroundColor = source.foregroundColor;
backgroupColor = source.backgroupColor;
overrideURL = source.overrideURL;
autoType = new AutoType(source.autoType);
history.clear();
history.addAll(source.history);
url = source.url;
additional = source.additional;
tags = source.tags;
}
@NonNull
@Override
public Type getType() {
return Type.ENTRY;
}
public void startToManageFieldReferences(PwDatabaseV4 db) {
this.mDatabase = db;
this.mDecodeRef = true;
}
public void stopToManageFieldReferences() {
this.mDatabase = null;
this.mDecodeRef = false;
}
/**
* Decode a reference key woth the SprEngineV4
* @param decodeRef
* @param key
* @return
*/
private String decodeRefKey(boolean decodeRef, String key) {
String text = getProtectedStringValue(key);
if (decodeRef) {
if (mDatabase == null)
return text;
return new SprEngineV4().compile(text, this, mDatabase);
}
return text;
}
@NonNull
@Override
public String getUsername() {
return decodeRefKey(mDecodeRef, STR_USERNAME);
}
@NonNull
@Override
public String getTitle() {
return decodeRefKey(mDecodeRef, STR_TITLE);
}
@NonNull
@Override
public String getPassword() {
return decodeRefKey(mDecodeRef, STR_PASSWORD);
}
@Override
public void setTitle(@NonNull String title) {
boolean protect = (mDatabase != null) && mDatabase.getMemoryProtection().protectTitle;
setProtectedString(STR_TITLE, title, protect);
}
@Override
public void setUsername(@NonNull String user) {
boolean protect = (mDatabase != null) && mDatabase.getMemoryProtection().protectUserName;
setProtectedString(STR_USERNAME, user, protect);
}
@Override
public void setPassword(@NonNull String pass) {
boolean protect = (mDatabase != null) && mDatabase.getMemoryProtection().protectPassword;
setProtectedString(STR_PASSWORD, pass, protect);
}
@Override
public void setUrl(@NonNull String url) {
boolean protect = (mDatabase != null) && mDatabase.getMemoryProtection().protectUrl;
setProtectedString(STR_URL, url, protect);
}
@Override
public void setNotes(@NonNull String notes) {
boolean protect = (mDatabase != null) && mDatabase.getMemoryProtection().protectNotes;
setProtectedString(STR_NOTES, notes, protect);
}
public String getProtectedStringValue(String key) {
return fields.getProtectedStringValue(key);
}
public void setProtectedString(String key, String value, boolean protect) {
fields.putProtectedString(key, value, protect);
}
public PwDate getLocationChanged() {
return parentGroupLastMod;
}
public long getUsageCount() {
return usageCount;
}
public void setLocationChanged(PwDate date) {
parentGroupLastMod = date;
}
public void setUsageCount(long count) {
usageCount = count;
}
@NonNull
@Override
public String getNotes() {
return decodeRefKey(mDecodeRef, STR_NOTES);
}
@NonNull
@Override
public String getUrl() {
return decodeRefKey(mDecodeRef, STR_URL);
}
@NonNull
@Override
public PwIcon getIcon() {
if (customIcon == null || customIcon.isUnknown()) {
return super.getIcon();
} else {
return customIcon;
}
}
@Override
public void setIcon(@NonNull PwIcon icon) {
if (icon instanceof PwIconStandard)
setIconStandard((PwIconStandard) icon);
if (icon instanceof PwIconCustom)
setIconCustom((PwIconCustom) icon);
}
public PwIconCustom getIconCustom() {
return customIcon;
}
public void setIconCustom(PwIconCustom icon) {
this.customIcon = icon;
}
public PwIcon getIconStandard() {
return getIcon();
}
public void setIconStandard(PwIconStandard icon) {
super.setIcon(icon);
this.customIcon = PwIconCustom.Companion.getZERO();
}
public boolean allowExtraFields() {
return true;
}
@NonNull
public ExtraFields getFields() {
return fields;
}
public boolean containsCustomFields() {
return getFields().containsCustomFields();
}
public boolean containsCustomFieldsProtected() {
return getFields().containsCustomFieldsProtected();
}
public boolean containsCustomFieldsNotProtected() {
return getFields().containsCustomFieldsNotProtected();
}
public void addExtraField(String label, ProtectedString value) {
fields.putProtectedString(label, value);
}
public void removeAllCustomFields() {
fields.removeAllCustomFields();
}
public HashMap<String, ProtectedBinary> getBinaries() {
return binaries;
}
public void putProtectedBinary(String key, ProtectedBinary value) {
binaries.put(key, value);
}
public String getForegroundColor() {
return foregroundColor;
}
public void setForegroundColor(String color) {
this.foregroundColor = color;
}
public String getBackgroupColor() {
return backgroupColor;
}
public void setBackgroupColor(String color) {
this.backgroupColor = color;
}
public String getOverrideURL() {
return overrideURL;
}
public void setOverrideURL(String overrideURL) {
this.overrideURL = overrideURL;
}
public AutoType getAutoType() {
return autoType;
}
public void setAutoType(AutoType autoType) {
this.autoType = autoType;
}
public ArrayList<PwEntryV4> getHistory() {
return history;
}
public void setHistory(ArrayList<PwEntryV4> history) {
this.history = history;
}
public void addToHistory(PwEntryV4 entry) {
history.add(entry);
}
public int sizeOfHistory() {
return history.size();
}
public String getAdditional() {
return additional;
}
public void setAdditional(String additional) {
this.additional = additional;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public void putCustomData(String key, String value) {
customData.put(key, value);
}
public boolean containsCustomData() {
return customData.size() > 0;
}
private static final long FIXED_LENGTH_SIZE = 128; // Approximate fixed length size
public long getSize() {
long size = FIXED_LENGTH_SIZE;
for (Entry<String, ProtectedString> pair : fields.getListOfAllFields().entrySet()) {
size += pair.getKey().length();
size += pair.getValue().length();
}
for (Entry<String, ProtectedBinary> pair : binaries.entrySet()) {
size += pair.getKey().length();
size += pair.getValue().length();
}
size += autoType.defaultSequence.length();
for (Entry<String, String> pair : autoType.entrySet()) {
size += pair.getKey().length();
size += pair.getValue().length();
}
for (PwEntryV4 entry : history) {
size += entry.getSize();
}
size += overrideURL.length();
size += tags.length();
return size;
}
public void addEntryToHistory(PwEntryV4 entry) {
history.add(entry);
}
public void removeOldestEntryFromHistory() {
Date min = null;
int index = -1;
for (int i = 0; i < history.size(); i++) {
PwEntryV4 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
public void touch(boolean modified, boolean touchParents) {
super.touch(modified, touchParents);
++usageCount;
}
@Override
public void touchLocation() {
parentGroupLastMod = new PwDate();
}
@Override
public boolean isSearchingEnabled() {
if (getParent() != null) {
return getParent().isSearchingEnabled();
}
return true;
}
/**
* If it's a node with only meta information like Meta-info SYSTEM Database Color
* @return false by default, true if it's a meta stream
*/
public boolean isMetaStream() {
return false;
}
}

View File

@@ -0,0 +1,325 @@
/*
* Copyright 2019 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 3 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 <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.database.element
import android.os.Parcel
import android.os.Parcelable
import com.kunzisoft.keepass.database.AutoType
import com.kunzisoft.keepass.database.ExtraFields
import com.kunzisoft.keepass.database.security.ProtectedBinary
import com.kunzisoft.keepass.database.security.ProtectedString
import com.kunzisoft.keepass.utils.MemUtil
import com.kunzisoft.keepass.utils.SprEngineV4
import java.util.*
class PwEntryV4 : PwEntry<PwGroupV4, PwEntryV4>, NodeV4Interface {
// To decode each field not parcelable
@Transient
private var mDatabase: PwDatabaseV4? = null
@Transient
private var mDecodeRef = false
var iconCustom = PwIconCustom.ZERO
private var customData = HashMap<String, String>()
var fields = ExtraFields()
private set
val binaries = HashMap<String, ProtectedBinary>()
var foregroundColor = ""
var backgroundColor = ""
var overrideURL = ""
var autoType = AutoType()
var history = ArrayList<PwEntryV4>()
var additional = ""
var tags = ""
val size: Long
get() {
var size = FIXED_LENGTH_SIZE
for ((key, value) in fields.listOfAllFields) {
size += key.length.toLong()
size += value.length().toLong()
}
for ((key, value) in binaries) {
size += key.length.toLong()
size += value.length()
}
size += autoType.defaultSequence.length.toLong()
for ((key, value) in autoType.entrySet()) {
size += key.length.toLong()
size += value.length.toLong()
}
for (entry in history) {
size += entry.size
}
size += overrideURL.length.toLong()
size += tags.length.toLong()
return size
}
constructor() : super()
constructor(parcel: Parcel) : super(parcel) {
iconCustom = parcel.readParcelable(PwIconCustom::class.java.classLoader)
usageCount = parcel.readLong()
locationChanged = parcel.readParcelable(PwDate::class.java.classLoader)
customData = MemUtil.readStringParcelableMap(parcel)
fields = parcel.readParcelable(ExtraFields::class.java.classLoader)
// TODO binaries = MemUtil.readStringParcelableMap(parcel, ProtectedBinary.class);
foregroundColor = parcel.readString()
backgroundColor = parcel.readString()
overrideURL = parcel.readString()
autoType = parcel.readParcelable(AutoType::class.java.classLoader)
parcel.readTypedList(history, CREATOR)
url = parcel.readString()
additional = parcel.readString()
tags = parcel.readString()
}
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeParcelable(iconCustom, flags)
dest.writeLong(usageCount)
dest.writeParcelable(locationChanged, flags)
MemUtil.writeStringParcelableMap(dest, customData)
dest.writeParcelable(fields, flags)
// TODO MemUtil.writeStringParcelableMap(dest, flags, binaries);
dest.writeString(foregroundColor)
dest.writeString(backgroundColor)
dest.writeString(overrideURL)
dest.writeParcelable(autoType, flags)
dest.writeTypedList(history)
dest.writeString(url)
dest.writeString(additional)
dest.writeString(tags)
}
/**
* Update with deep copy of each entry element
* @param source
*/
fun updateWith(source: PwEntryV4) {
super.updateWith(source)
iconCustom = PwIconCustom(source.iconCustom)
usageCount = source.usageCount
locationChanged = PwDate(source.locationChanged)
// Add all custom elements in map
customData.clear()
for ((key, value) in source.customData) {
customData[key] = value
}
fields = ExtraFields(source.fields)
for ((key, value) in source.binaries) {
binaries[key] = ProtectedBinary(value)
}
foregroundColor = source.foregroundColor
backgroundColor = source.backgroundColor
overrideURL = source.overrideURL
autoType = AutoType(source.autoType)
history.clear()
history.addAll(source.history)
url = source.url
additional = source.additional
tags = source.tags
}
fun startToManageFieldReferences(db: PwDatabaseV4) {
this.mDatabase = db
this.mDecodeRef = true
}
fun stopToManageFieldReferences() {
this.mDatabase = null
this.mDecodeRef = false
}
override fun initNodeId(): PwNodeId<UUID> {
return PwNodeIdUUID()
}
override fun copyNodeId(nodeId: PwNodeId<UUID>): PwNodeId<UUID> {
return PwNodeIdUUID(nodeId.id)
}
override fun readParentParcelable(parcel: Parcel): PwGroupV4 {
return parcel.readParcelable(PwGroupV4::class.java.classLoader)
}
/**
* Decode a reference key woth the SprEngineV4
* @param decodeRef
* @param key
* @return
*/
private fun decodeRefKey(decodeRef: Boolean, key: String): String {
val text = fields.getProtectedStringValue(key)
return if (decodeRef) {
if (mDatabase == null) text else SprEngineV4().compile(text, this, mDatabase)
} else text
}
override var title: String
get() = decodeRefKey(mDecodeRef, STR_TITLE)
set(value) {
val protect = mDatabase != null && mDatabase!!.memoryProtection.protectTitle
fields.putProtectedString(STR_TITLE, value, protect)
}
override val type: Type
get() = Type.ENTRY
override val isSearchingEnabled: Boolean
get() = parent?.isSearchingEnabled ?: true
override var username: String
get() = decodeRefKey(mDecodeRef, STR_USERNAME)
set(value) {
val protect = mDatabase != null && mDatabase!!.memoryProtection.protectUserName
fields.putProtectedString(STR_USERNAME, value, protect)
}
override var password: String
get() = decodeRefKey(mDecodeRef, STR_PASSWORD)
set(value) {
val protect = mDatabase != null && mDatabase!!.memoryProtection.protectPassword
fields.putProtectedString(STR_PASSWORD, value, protect)
}
override var url
get() = decodeRefKey(mDecodeRef, STR_URL)
set(value) {
val protect = mDatabase != null && mDatabase!!.memoryProtection.protectUrl
fields.putProtectedString(STR_URL, value, protect)
}
override var notes: String
get() = decodeRefKey(mDecodeRef, STR_NOTES)
set(value) {
val protect = mDatabase != null && mDatabase!!.memoryProtection.protectNotes
fields.putProtectedString(STR_NOTES, value, protect)
}
override var usageCount: Long = 0
override var locationChanged = PwDate()
fun afterChangeParent() {
locationChanged = PwDate()
}
fun allowExtraFields(): Boolean {
return true
}
fun containsCustomFields(): Boolean {
return fields.containsCustomFields()
}
fun containsCustomFieldsProtected(): Boolean {
return fields.containsCustomFieldsProtected()
}
fun containsCustomFieldsNotProtected(): Boolean {
return fields.containsCustomFieldsNotProtected()
}
fun addExtraField(label: String, value: ProtectedString) {
fields.putProtectedString(label, value)
}
fun removeAllCustomFields() {
fields.removeAllCustomFields()
}
fun putProtectedBinary(key: String, value: ProtectedBinary) {
binaries[key] = value
}
fun addToHistory(entry: PwEntryV4) {
history.add(entry)
}
fun sizeOfHistory(): Int {
return history.size
}
fun putCustomData(key: String, value: String) {
customData[key] = value
}
fun containsCustomData(): Boolean {
return customData.size > 0
}
fun addEntryToHistory(entry: PwEntryV4) {
history.add(entry)
}
fun removeOldestEntryFromHistory() {
var min: Date? = null
var index = -1
for (i in history.indices) {
val entry = history[i]
val lastMod = entry.lastModificationTime.date
if (min == null || lastMod.before(min)) {
index = i
min = lastMod
}
}
if (index != -1) {
history.removeAt(index)
}
}
override fun touch(modified: Boolean, touchParents: Boolean) {
super.touch(modified, touchParents)
++usageCount
}
companion object {
const val STR_TITLE = "Title"
const val STR_USERNAME = "UserName"
const val STR_PASSWORD = "Password"
const val STR_URL = "URL"
const val STR_NOTES = "Notes"
@JvmField
val CREATOR: Parcelable.Creator<PwEntryV4> = object : Parcelable.Creator<PwEntryV4> {
override fun createFromParcel(parcel: Parcel): PwEntryV4 {
return PwEntryV4(parcel)
}
override fun newArray(size: Int): Array<PwEntryV4?> {
return arrayOfNulls(size)
}
}
private const val FIXED_LENGTH_SIZE: Long = 128 // Approximate fixed length size
}
}

View File

@@ -1,125 +0,0 @@
/*
* Copyright 2019 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 3 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 <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.database.element;
import android.os.Parcel;
import android.support.annotation.NonNull;
public class PwGroupV3 extends PwGroup<Integer, PwGroupV3, PwEntryV3> {
private int level = 0; // short
/** Used by KeePass internally, don't use */
private int flags;
@NonNull
@Override
protected PwNodeId<Integer> initNodeId() {
return new PwNodeIdInt();
}
@NonNull
@Override
protected PwNodeId<Integer> copyNodeId(@NonNull PwNodeId<Integer> nodeId) {
return new PwNodeIdInt(nodeId.getId());
}
public PwGroupV3() {
super();
}
public PwGroupV3(Parcel in) {
super(in);
level = in.readInt();
flags = in.readInt();
}
@Override
protected PwGroupV3 readParentParcelable(Parcel parcel) {
return parcel.readParcelable(PwGroupV3.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(level);
dest.writeInt(flags);
}
public static final Creator<PwGroupV3> CREATOR = new Creator<PwGroupV3>() {
@Override
public PwGroupV3 createFromParcel(Parcel in) {
return new PwGroupV3(in);
}
@Override
public PwGroupV3[] newArray(int size) {
return new PwGroupV3[size];
}
};
protected void updateWith(PwGroupV3 source) {
super.updateWith(source);
level = source.level;
flags = source.flags;
}
@Override
public Type getType() {
return Type.GROUP;
}
public void setParent(PwGroupV3 parent) {
super.setParent(parent);
try {
level = parent.getLevel() + 1;
} catch (ClassCastException ignored) {}
}
@Override
public boolean isSearchingEnabled() {
return false;
}
public void setGroupId(int groupId) {
this.setNodeId(new PwNodeIdInt(groupId));
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int getFlags() {
return flags;
}
public void setFlags(int flags) {
this.flags = flags;
}
@Override
public boolean allowAddEntryIfIsRoot() {
return false;
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2019 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 3 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 <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.database.element
import android.os.Parcel
import android.os.Parcelable
class PwGroupV3 : PwGroup<Int, PwGroupV3, PwEntryV3> {
var level = 0 // short
/** Used by KeePass internally, don't use */
var flags: Int = 0
constructor() : super()
constructor(parcel: Parcel) : super(parcel) {
level = parcel.readInt()
flags = parcel.readInt()
}
override fun readParentParcelable(parcel: Parcel): PwGroupV3 {
return parcel.readParcelable(PwGroupV3::class.java.classLoader)
}
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeInt(level)
dest.writeInt(flags)
}
fun updateWith(source: PwGroupV3) {
super.updateWith(source)
level = source.level
flags = source.flags
}
override val type: Type
get() = Type.GROUP
override val isSearchingEnabled: Boolean
get() = false
override fun initNodeId(): PwNodeId<Int> {
return PwNodeIdInt()
}
override fun copyNodeId(nodeId: PwNodeId<Int>): PwNodeId<Int> {
return PwNodeIdInt(nodeId.id)
}
override fun afterAssignNewParent() {
if (parent != null)
level = parent!!.level + 1
}
fun setGroupId(groupId: Int) {
this.nodeId = PwNodeIdInt(groupId)
}
override fun allowAddEntryIfIsRoot(): Boolean {
return false
}
companion object {
@JvmField
val CREATOR: Parcelable.Creator<PwGroupV3> = object : Parcelable.Creator<PwGroupV3> {
override fun createFromParcel(parcel: Parcel): PwGroupV3 {
return PwGroupV3(parcel)
}
override fun newArray(size: Int): Array<PwGroupV3?> {
return arrayOfNulls(size)
}
}
}
}

View File

@@ -1,267 +0,0 @@
/*
* Copyright 2019 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 3 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 <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.database.element;
import android.os.Parcel;
import android.support.annotation.NonNull;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class PwGroupV4 extends PwGroup<UUID, PwGroupV4, PwEntryV4> implements NodeV4Interface {
private PwIconCustom customIcon = PwIconCustom.Companion.getZERO();
private long usageCount = 0;
private PwDate locationChangeDate = new PwDate();
private Map<String, String> customData = new HashMap<>();
private boolean expires = false;
private String notes = "";
private boolean isExpanded = true;
private String defaultAutoTypeSequence = "";
private Boolean enableAutoType = null;
private Boolean enableSearching = null;
private UUID lastTopVisibleEntry = PwDatabase.UUID_ZERO;
@NonNull
@Override
protected PwNodeId<UUID> initNodeId() {
return new PwNodeIdUUID();
}
@NonNull
@Override
protected PwNodeId<UUID> copyNodeId(@NonNull PwNodeId<UUID> nodeId) {
return new PwNodeIdUUID(nodeId.getId());
}
public PwGroupV4() {
super();
}
public PwGroupV4(Parcel in) {
super(in);
customIcon = in.readParcelable(PwIconCustom.class.getClassLoader());
usageCount = in.readLong();
locationChangeDate = in.readParcelable(PwDate.class.getClassLoader());
// TODO customData = MemUtil.readStringParcelableMap(in);
expires = in.readByte() != 0;
notes = in.readString();
isExpanded = in.readByte() != 0;
defaultAutoTypeSequence = in.readString();
byte autoTypeByte = in.readByte();
enableAutoType = (autoTypeByte == -1) ? null : autoTypeByte != 0;
byte enableSearchingByte = in.readByte();
enableSearching = (enableSearchingByte == -1) ? null : enableSearchingByte != 0;
lastTopVisibleEntry = (UUID) in.readSerializable();
}
@Override
protected PwGroupV4 readParentParcelable(Parcel parcel) {
return parcel.readParcelable(PwGroupV4.class.getClassLoader());
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(customIcon, flags);
dest.writeLong(usageCount);
dest.writeParcelable(locationChangeDate, flags);
// TODO MemUtil.writeStringParcelableMap(dest, customData);
dest.writeByte((byte) (expires ? 1 : 0));
dest.writeString(notes);
dest.writeByte((byte) (isExpanded ? 1 : 0));
dest.writeString(defaultAutoTypeSequence);
dest.writeByte((byte) (enableAutoType == null ? -1 : (enableAutoType ? 1 : 0)));
dest.writeByte((byte) (enableAutoType == null ? -1 : (enableAutoType ? 1 : 0)));
dest.writeSerializable(lastTopVisibleEntry);
}
public static final Creator<PwGroupV4> CREATOR = new Creator<PwGroupV4>() {
@Override
public PwGroupV4 createFromParcel(Parcel in) {
return new PwGroupV4(in);
}
@Override
public PwGroupV4[] newArray(int size) {
return new PwGroupV4[size];
}
};
protected void updateWith(PwGroupV4 source) {
super.updateWith(source);
customIcon = new PwIconCustom(source.customIcon);
usageCount = source.usageCount;
locationChangeDate = new PwDate(source.locationChangeDate);
// Add all custom elements in map
customData.clear();
for (Map.Entry<String, String> entry : source.customData.entrySet()) {
customData.put(entry.getKey(), entry.getValue());
}
expires = source.expires;
notes = source.notes;
isExpanded = source.isExpanded;
defaultAutoTypeSequence = source.defaultAutoTypeSequence;
enableAutoType = source.enableAutoType;
enableSearching = source.enableSearching;
lastTopVisibleEntry = source.lastTopVisibleEntry;
}
@NonNull
@Override
public Type getType() {
return Type.GROUP;
}
@Override
public void setParent(PwGroupV4 parent) {
super.setParent(parent);
locationChangeDate = new PwDate();
}
@Override
public PwDate getLocationChanged() {
return locationChangeDate;
}
@Override
public void setLocationChanged(PwDate date) {
locationChangeDate = date;
}
@Override
public long getUsageCount() {
return usageCount;
}
@Override
public void setUsageCount(long count) {
usageCount = count;
}
@Override
public boolean isExpires() {
return expires;
}
@Override
public void setExpires(boolean exp) {
expires = exp;
}
@NonNull
@Override
public PwIcon getIcon() {
if (customIcon == null || customIcon.isUnknown()) { // TODO Encapsulate with PwEntryV4
return super.getIcon();
} else {
return customIcon;
}
}
public PwIconCustom getIconCustom() {
return customIcon;
}
public void setIconCustom(PwIconCustom icon) {
this.customIcon = icon;
}
public PwIcon getIconStandard() {
return getIcon();
}
public void setIconStandard(PwIconStandard icon) { // TODO Encapsulate with PwEntryV4
super.setIcon(icon);
this.customIcon = PwIconCustom.Companion.getZERO();
}
public void putCustomData(String key, String value) {
customData.put(key, value);
}
public boolean containsCustomData() {
return customData.size() > 0;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public boolean isExpanded() {
return isExpanded;
}
public void setExpanded(boolean expanded) {
isExpanded = expanded;
}
public String getDefaultAutoTypeSequence() {
return defaultAutoTypeSequence;
}
public void setDefaultAutoTypeSequence(String defaultAutoTypeSequence) {
this.defaultAutoTypeSequence = defaultAutoTypeSequence;
}
public Boolean getEnableAutoType() {
return enableAutoType;
}
public void setEnableAutoType(Boolean enableAutoType) {
this.enableAutoType = enableAutoType;
}
public Boolean getEnableSearching() {
return enableSearching;
}
public void setEnableSearching(Boolean enableSearching) {
this.enableSearching = enableSearching;
}
public UUID getLastTopVisibleEntry() {
return lastTopVisibleEntry;
}
public void setLastTopVisibleEntry(UUID lastTopVisibleEntry) {
this.lastTopVisibleEntry = lastTopVisibleEntry;
}
@Override
public boolean isSearchingEnabled() {
if (getParent() != null) {
return getParent().isSearchingEnabled();
}
return true;
}
@Override
public boolean allowAddEntryIfIsRoot() {
return true;
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright 2019 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 3 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 <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.database.element
import android.os.Parcel
import android.os.Parcelable
import java.util.HashMap
import java.util.UUID
class PwGroupV4 : PwGroup<UUID, PwGroupV4, PwEntryV4>, NodeV4Interface {
var iconCustom = PwIconCustom.ZERO
private val customData = HashMap<String, String>()
var notes = ""
var isExpanded = true
var defaultAutoTypeSequence = ""
var enableAutoType: Boolean? = null
var enableSearching: Boolean? = null
var lastTopVisibleEntry: UUID = PwDatabase.UUID_ZERO
override val type: Type
get() = Type.GROUP
override val isSearchingEnabled: Boolean
get() = parent?.isSearchingEnabled ?: true
override fun initNodeId(): PwNodeId<UUID> {
return PwNodeIdUUID()
}
override fun copyNodeId(nodeId: PwNodeId<UUID>): PwNodeId<UUID> {
return PwNodeIdUUID(nodeId.id)
}
constructor() : super()
constructor(parcel: Parcel) : super(parcel) {
iconCustom = parcel.readParcelable(PwIconCustom::class.java.classLoader)
usageCount = parcel.readLong()
locationChanged = parcel.readParcelable(PwDate::class.java.classLoader)
// TODO customData = MemUtil.readStringParcelableMap(in);
notes = parcel.readString()
isExpanded = parcel.readByte().toInt() != 0
defaultAutoTypeSequence = parcel.readString()
enableAutoType = parcel.readByte().toInt() != 0
enableSearching = parcel.readByte().toInt() != 0
lastTopVisibleEntry = parcel.readSerializable() as UUID
}
override fun readParentParcelable(parcel: Parcel): PwGroupV4 {
return parcel.readParcelable(PwGroupV4::class.java.classLoader)
}
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeParcelable(iconCustom, flags)
dest.writeLong(usageCount)
dest.writeParcelable(locationChanged, flags)
// TODO MemUtil.writeStringParcelableMap(dest, customData);
dest.writeString(notes)
dest.writeByte((if (isExpanded) 1 else 0).toByte())
dest.writeString(defaultAutoTypeSequence)
dest.writeByte((if (enableAutoType == null) -1 else if (enableAutoType!!) 1 else 0).toByte())
dest.writeByte((if (enableSearching == null) -1 else if (enableSearching!!) 1 else 0).toByte())
dest.writeSerializable(lastTopVisibleEntry)
}
fun updateWith(source: PwGroupV4) {
super.updateWith(source)
iconCustom = PwIconCustom(source.iconCustom)
usageCount = source.usageCount
locationChanged = PwDate(source.locationChanged)
// Add all custom elements in map
customData.clear()
for ((key, value) in source.customData) {
customData[key] = value
}
notes = source.notes
isExpanded = source.isExpanded
defaultAutoTypeSequence = source.defaultAutoTypeSequence
enableAutoType = source.enableAutoType
enableSearching = source.enableSearching
lastTopVisibleEntry = source.lastTopVisibleEntry
}
override var usageCount: Long = 0
override var locationChanged = PwDate()
override fun afterAssignNewParent() {
locationChanged = PwDate()
}
fun putCustomData(key: String, value: String) {
customData[key] = value
}
fun containsCustomData(): Boolean {
return customData.size > 0
}
override fun allowAddEntryIfIsRoot(): Boolean {
return true
}
companion object {
@JvmField
val CREATOR: Parcelable.Creator<PwGroupV4> = object : Parcelable.Creator<PwGroupV4> {
override fun createFromParcel(parcel: Parcel): PwGroupV4 {
return PwGroupV4(parcel)
}
override fun newArray(size: Int): Array<PwGroupV4?> {
return arrayOfNulls(size)
}
}
}
}

View File

@@ -23,11 +23,9 @@ import android.os.Parcelable
abstract class PwIcon protected constructor() : Parcelable {
abstract val isMetaStreamIcon: Boolean
abstract val isUnknown: Boolean
abstract val iconId: Int
abstract val isUnknown: Boolean
abstract val isMetaStreamIcon: Boolean
override fun describeContents(): Int {
return 0

View File

@@ -30,15 +30,6 @@ class PwIconCustom : PwIcon {
@Transient
var imageData: ByteArray = ByteArray(0)
override val isMetaStreamIcon: Boolean
get() = false
override val isUnknown: Boolean
get() = this == ZERO
override val iconId: Int
get() = PwIcon.UNKNOWN
constructor(uuid: UUID, data: ByteArray) : super() {
this.uuid = uuid
this.imageData = data
@@ -82,6 +73,15 @@ class PwIconCustom : PwIcon {
return uuid == other.uuid
}
override val iconId: Int
get() = UNKNOWN
override val isUnknown: Boolean
get() = this == ZERO
override val isMetaStreamIcon: Boolean
get() = false
companion object {
val ZERO = PwIconCustom(PwDatabase.UUID_ZERO, ByteArray(0))

View File

@@ -23,13 +23,6 @@ import android.os.Parcel
import android.os.Parcelable
class PwIconStandard : PwIcon {
override val iconId: Int
override val isUnknown: Boolean
get() = iconId == PwIcon.UNKNOWN
override val isMetaStreamIcon: Boolean
get() = iconId == 0
constructor() {
this.iconId = KEY
@@ -69,6 +62,14 @@ class PwIconStandard : PwIcon {
return iconId == other.iconId
}
override val iconId: Int
override val isUnknown: Boolean
get() = iconId == UNKNOWN
override val isMetaStreamIcon: Boolean
get() = iconId == 0
companion object {
const val KEY = 0

View File

@@ -31,37 +31,29 @@ abstract class PwNode<IdType, Parent : PwGroupInterface<Parent, Entry>, Entry :
var nodeId: PwNodeId<IdType> = this.initNodeId()
private var mParent: Parent? = null
private var mIcon: PwIcon = PwIconStandard()
private var mCreationDate = PwDate()
private var mLastModificationDate = PwDate()
private var mLastAccessDate = PwDate()
private var mExpireDate = PwDate.PW_NEVER_EXPIRE
protected abstract fun initNodeId(): PwNodeId<IdType>
protected abstract fun copyNodeId(nodeId: PwNodeId<IdType>): PwNodeId<IdType>
protected abstract fun readParentParcelable(parcel: Parcel): Parent
val id: IdType
get() = nodeId.id
protected constructor()
protected constructor(parcel: Parcel) {
this.nodeId = parcel.readParcelable(PwNodeId::class.java.classLoader)
this.mParent = this.readParentParcelable(parcel)
this.mIcon = parcel.readParcelable(PwIconStandard::class.java.classLoader)
this.mCreationDate = parcel.readParcelable(PwDate::class.java.classLoader)
this.mLastModificationDate = parcel.readParcelable(PwDate::class.java.classLoader)
this.mLastAccessDate = parcel.readParcelable(PwDate::class.java.classLoader)
this.mExpireDate = parcel.readParcelable(PwDate::class.java.classLoader)
this.parent = this.readParentParcelable(parcel)
this.icon = parcel.readParcelable(PwIconStandard::class.java.classLoader)
this.creationTime = parcel.readParcelable(PwDate::class.java.classLoader)
this.lastModificationTime = parcel.readParcelable(PwDate::class.java.classLoader)
this.lastAccessTime = parcel.readParcelable(PwDate::class.java.classLoader)
this.expiryTime = parcel.readParcelable(PwDate::class.java.classLoader)
}
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeParcelable(nodeId, flags)
dest.writeParcelable(mParent, flags)
dest.writeParcelable(mIcon, flags)
dest.writeParcelable(mCreationDate, flags)
dest.writeParcelable(mLastModificationDate, flags)
dest.writeParcelable(mLastAccessDate, flags)
dest.writeParcelable(mExpireDate, flags)
dest.writeParcelable(parent, flags)
dest.writeParcelable(icon, flags)
dest.writeParcelable(creationTime, flags)
dest.writeParcelable(lastModificationTime, flags)
dest.writeParcelable(lastAccessTime, flags)
dest.writeParcelable(expiryTime, flags)
}
override fun describeContents(): Int {
@@ -70,47 +62,36 @@ abstract class PwNode<IdType, Parent : PwGroupInterface<Parent, Entry>, Entry :
protected fun updateWith(source: PwNode<IdType, Parent, Entry>) {
this.nodeId = copyNodeId(source.nodeId)
this.mParent = source.parent
this.mIcon = source.icon
this.mCreationDate = PwDate(source.mCreationDate)
this.mLastModificationDate = PwDate(source.mLastModificationDate)
this.mLastAccessDate = PwDate(source.mLastAccessDate)
this.mExpireDate = PwDate(source.mExpireDate)
this.parent = source.parent
this.icon = source.icon
this.creationTime = PwDate(source.creationTime)
this.lastModificationTime = PwDate(source.lastModificationTime)
this.lastAccessTime = PwDate(source.lastAccessTime)
this.expiryTime = PwDate(source.expiryTime)
}
val id: IdType
get() = nodeId.id
protected abstract fun initNodeId(): PwNodeId<IdType>
protected abstract fun copyNodeId(nodeId: PwNodeId<IdType>): PwNodeId<IdType>
protected abstract fun readParentParcelable(parcel: Parcel): Parent
override var parent: Parent?
get() = mParent
set(value) { mParent = value }
final override var parent: Parent? = null
override var icon: PwIcon
get() = mIcon
set(value) { mIcon = value }
final override var icon: PwIcon = PwIconStandard()
override var creationTime: PwDate
get() = mCreationDate
set(value) { mCreationDate = value }
final override var creationTime: PwDate = PwDate()
override var lastModificationTime: PwDate
get() = mLastModificationDate
set(value) { mLastModificationDate = value }
final override var lastModificationTime: PwDate = PwDate()
override var lastAccessTime: PwDate
get() = mLastAccessDate
set(value) { mLastAccessDate = value }
final override var lastAccessTime: PwDate = PwDate()
override var expiryTime: PwDate
get() = mExpireDate
set(value) { mExpireDate = value }
final override var expiryTime: PwDate = PwDate.PW_NEVER_EXPIRE
override var isExpires: Boolean
final override var isExpires: Boolean
// If expireDate is before NEVER_EXPIRE date less 1 month (to be sure)
get() = mExpireDate.date.before(LocalDate.fromDateFields(PwDate.NEVER_EXPIRE).minusMonths(1).toDate())
get() = expiryTime.date.before(LocalDate.fromDateFields(PwDate.NEVER_EXPIRE).minusMonths(1).toDate())
set(value) {
if (!value) {
mExpireDate = PwDate.PW_NEVER_EXPIRE
expiryTime = PwDate.PW_NEVER_EXPIRE
}
}
@@ -121,6 +102,8 @@ abstract class PwNode<IdType, Parent : PwGroupInterface<Parent, Entry>, Entry :
return parent != null
}
override fun afterAssignNewParent() {}
override fun isContainedIn(container: Parent): Boolean {
var cur = this.parent
while (cur != null) {

View File

@@ -25,6 +25,8 @@ interface PwNodeInterface<ParentGroup> : NodeTimeInterface, Parcelable {
fun containsParent(): Boolean
fun afterAssignNewParent()
fun isContainedIn(container: ParentGroup): Boolean
fun touch(modified: Boolean, touchParents: Boolean)

View File

@@ -531,7 +531,7 @@ public class ImporterV4 extends Importer<PwDatabaseV4> {
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemNotes) ) {
ctxGroup.setNotes(ReadString(xpp));
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemIcon) ) {
ctxGroup.setIconStandard(mDatabase.getIconFactory().getIcon((int)ReadUInt(xpp, 0)));
ctxGroup.setIcon(mDatabase.getIconFactory().getIcon((int)ReadUInt(xpp, 0)));
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemCustomIconID) ) {
ctxGroup.setIconCustom(mDatabase.getIconFactory().getIcon(ReadUuid(xpp)));
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemTimes) ) {
@@ -590,13 +590,13 @@ public class ImporterV4 extends Importer<PwDatabaseV4> {
ctxEntry.setNodeId(new PwNodeIdUUID(ReadUuid(xpp)));
mDatabase.addEntryIndex(ctxEntry);
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemIcon) ) {
ctxEntry.setIconStandard(mDatabase.getIconFactory().getIcon((int)ReadUInt(xpp, 0)));
ctxEntry.setIcon(mDatabase.getIconFactory().getIcon((int)ReadUInt(xpp, 0)));
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemCustomIconID) ) {
ctxEntry.setIconCustom(mDatabase.getIconFactory().getIcon(ReadUuid(xpp)));
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemFgColor) ) {
ctxEntry.setForegroundColor(ReadString(xpp));
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemBgColor) ) {
ctxEntry.setBackgroupColor(ReadString(xpp));
ctxEntry.setBackgroundColor(ReadString(xpp));
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemOverrideUrl) ) {
ctxEntry.setOverrideURL(ReadString(xpp));
} else if ( name.equalsIgnoreCase(PwDatabaseV4XML.ElemTags) ) {
@@ -789,7 +789,7 @@ public class ImporterV4 extends Importer<PwDatabaseV4> {
return KdbContext.CustomData;
} else if ( ctx == KdbContext.Group && name.equalsIgnoreCase(PwDatabaseV4XML.ElemGroup) ) {
if ( ctxGroup.getNodeId() == null || ctxGroup.getNodeId().getId().equals(PwDatabase.UUID_ZERO) ) {
if ( ctxGroup.getId().equals(PwDatabase.UUID_ZERO) ) {
ctxGroup.setNodeId(mDatabase.newGroupId());
mDatabase.addGroupIndex(ctxGroup);
}
@@ -818,7 +818,7 @@ public class ImporterV4 extends Importer<PwDatabaseV4> {
return KdbContext.GroupCustomData;
} else if ( ctx == KdbContext.Entry && name.equalsIgnoreCase(PwDatabaseV4XML.ElemEntry) ) {
if ( ctxEntry.getNodeId() == null || ctxEntry.getNodeId().getId().equals(PwDatabase.UUID_ZERO) ) {
if ( ctxEntry.getId().equals(PwDatabase.UUID_ZERO) ) {
ctxEntry.setNodeId(mDatabase.newEntryId());
mDatabase.addEntryIndex(ctxEntry);
}
@@ -1132,6 +1132,5 @@ public class ImporterV4 extends Importer<PwDatabaseV4> {
}
return null;
}
}

View File

@@ -314,7 +314,7 @@ public class PwDbV4Output extends PwDbOutput<PwDbHeaderV4> {
writeObject(PwDatabaseV4XML.ElemUuid, group.getId());
writeObject(PwDatabaseV4XML.ElemName, group.getTitle());
writeObject(PwDatabaseV4XML.ElemNotes, group.getNotes());
writeObject(PwDatabaseV4XML.ElemIcon, group.getIconStandard().getIconId());
writeObject(PwDatabaseV4XML.ElemIcon, group.getIcon().getIconId());
if (!group.getIconCustom().equals(PwIconCustom.Companion.getZERO())) {
writeObject(PwDatabaseV4XML.ElemCustomIconID, group.getIconCustom().getUuid());
@@ -338,15 +338,15 @@ public class PwDbV4Output extends PwDbOutput<PwDbHeaderV4> {
xml.startTag(null, PwDatabaseV4XML.ElemEntry);
writeObject(PwDatabaseV4XML.ElemUuid, entry.getNodeId().getId());
writeObject(PwDatabaseV4XML.ElemIcon, entry.getIconStandard().getIconId());
writeObject(PwDatabaseV4XML.ElemUuid, entry.getId());
writeObject(PwDatabaseV4XML.ElemIcon, entry.getIcon().getIconId());
if (!entry.getIconCustom().equals(PwIconCustom.Companion.getZERO())) {
writeObject(PwDatabaseV4XML.ElemCustomIconID, entry.getIconCustom().getUuid());
}
writeObject(PwDatabaseV4XML.ElemFgColor, entry.getForegroundColor());
writeObject(PwDatabaseV4XML.ElemBgColor, entry.getBackgroupColor());
writeObject(PwDatabaseV4XML.ElemBgColor, entry.getBackgroundColor());
writeObject(PwDatabaseV4XML.ElemOverrideUrl, entry.getOverrideURL());
writeObject(PwDatabaseV4XML.ElemTags, entry.getTags());

View File

@@ -74,12 +74,12 @@ public class PwEntryOutputV3 {
// UUID
mOS.write(UUID_FIELD_TYPE);
mOS.write(UUID_FIELD_SIZE);
mOS.write(Types.UUIDtoBytes(mPE.getNodeId().getId()));
mOS.write(Types.UUIDtoBytes(mPE.getId()));
// Group ID
mOS.write(GROUPID_FIELD_TYPE);
mOS.write(LONG_FOUR);
mOS.write(LEDataOutputStream.writeIntBuf(mPE.getParent().getNodeId().getId()));
mOS.write(LEDataOutputStream.writeIntBuf(mPE.getParent().getId()));
// Image ID
mOS.write(IMAGEID_FIELD_TYPE);

View File

@@ -88,7 +88,7 @@ public class EntrySearchHandlerV4 extends NodeHandler<PwEntryV4> {
private boolean searchID(PwEntryV4 entry) {
if (mSearchParametersV4.getSearchInUUIDs()) {
String hex = UuidUtil.toHexString(entry.getNodeId().getId());
String hex = UuidUtil.toHexString(entry.getId());
return StringUtil.INSTANCE.indexOfIgnoreCase(hex, mSearchParametersV4.getSearchString(), Locale.ENGLISH) >= 0;
}