diff --git a/src/main/java/de/slackspace/openkeepass/api/KeePassDatabaseWriter.java b/src/main/java/de/slackspace/openkeepass/api/KeePassDatabaseWriter.java index b1082b7..8a6341f 100644 --- a/src/main/java/de/slackspace/openkeepass/api/KeePassDatabaseWriter.java +++ b/src/main/java/de/slackspace/openkeepass/api/KeePassDatabaseWriter.java @@ -12,7 +12,10 @@ import de.slackspace.openkeepass.crypto.RandomGenerator; import de.slackspace.openkeepass.crypto.Salsa20; import de.slackspace.openkeepass.crypto.Sha256; +import de.slackspace.openkeepass.domain.Group; +import de.slackspace.openkeepass.domain.GroupBuilder; import de.slackspace.openkeepass.domain.KeePassFile; +import de.slackspace.openkeepass.domain.KeePassFileBuilder; import de.slackspace.openkeepass.domain.KeePassHeader; import de.slackspace.openkeepass.domain.zipper.GroupZipper; import de.slackspace.openkeepass.exception.KeePassDatabaseUnwriteableException; @@ -85,12 +88,17 @@ private ByteArrayOutputStream hashBlockStream(ByteArrayOutputStream streamToUnzi } private byte[] marshallXml(KeePassFile keePassFile, KeePassHeader header) { - KeePassFile clonedKeePassFile = new GroupZipper(keePassFile).cloneKeePassFile(); - +// KeePassFile clonedKeePassFile = new GroupZipper(keePassFile).cloneKeePassFile(); + KeePassFile clonedKeePassFile; + try { + clonedKeePassFile = (KeePassFile)keePassFile.clone(); + } catch (CloneNotSupportedException e) { + throw new IllegalStateException(e); + } ProtectedStringCrypto protectedStringCrypto = Salsa20.createInstance(header.getProtectedStreamKey()); new ProtectedValueProcessor().processProtectedValues(new EncryptionStrategy(protectedStringCrypto), clonedKeePassFile); - return new KeePassDatabaseXmlParser().toXml(keePassFile).toByteArray(); + return new KeePassDatabaseXmlParser().toXml(clonedKeePassFile).toByteArray(); } private ByteArrayOutputStream compressStream(byte[] keePassFilePayload) throws IOException { @@ -112,4 +120,9 @@ private static boolean validateKeePassFile(KeePassFile keePassFile) { return true; } + + + + + } diff --git a/src/main/java/de/slackspace/openkeepass/domain/CustomIcon.java b/src/main/java/de/slackspace/openkeepass/domain/CustomIcon.java index 7221495..a250f7d 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/CustomIcon.java +++ b/src/main/java/de/slackspace/openkeepass/domain/CustomIcon.java @@ -17,7 +17,7 @@ */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -public class CustomIcon { +public class CustomIcon implements Cloneable{ @XmlElement(name = "UUID") @XmlJavaTypeAdapter(UUIDXmlAdapter.class) @@ -80,4 +80,13 @@ public final boolean equals(Object obj) { return true; } + @Override + protected Object clone() throws CloneNotSupportedException { + CustomIcon ret = new CustomIcon(); + ret.uuid = this.uuid; + if(this.data!=null){ + ret.data = Arrays.copyOf(this.data, this.data.length); + } + return ret; + } } diff --git a/src/main/java/de/slackspace/openkeepass/domain/CustomIcons.java b/src/main/java/de/slackspace/openkeepass/domain/CustomIcons.java index a054fb5..3c44875 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/CustomIcons.java +++ b/src/main/java/de/slackspace/openkeepass/domain/CustomIcons.java @@ -15,7 +15,7 @@ */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -public class CustomIcons { +public class CustomIcons implements Cloneable{ @XmlElement(name = "Icon") private List customIconList = new ArrayList(); @@ -78,4 +78,13 @@ public final boolean equals(Object obj) { return true; } + + @Override + protected Object clone() throws CloneNotSupportedException { + CustomIcons ret = new CustomIcons(); + for( CustomIcon customIcon:this.customIconList){ + ret.customIconList.add((CustomIcon)customIcon.clone()); + } + return ret; + } } diff --git a/src/main/java/de/slackspace/openkeepass/domain/Entry.java b/src/main/java/de/slackspace/openkeepass/domain/Entry.java index 3964adc..410022d 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/Entry.java +++ b/src/main/java/de/slackspace/openkeepass/domain/Entry.java @@ -1,6 +1,7 @@ package de.slackspace.openkeepass.domain; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.UUID; @@ -19,7 +20,7 @@ */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -public class Entry implements KeePassFileElement { +public class Entry implements KeePassFileElement, Cloneable { private static final String USER_NAME = "UserName"; private static final String NOTES = "Notes"; @@ -248,4 +249,26 @@ public String toString() { return "Entry [uuid=" + uuid + ", getTitle()=" + getTitle() + ", getPassword()=" + getPassword() + ", getUsername()=" + getUsername() + "]"; } + + @Override + protected Object clone() throws CloneNotSupportedException { + Entry ret = new Entry(); + ret.uuid = this.uuid; + ret.iconId = this.iconId; + if(this.iconData!=null){ + ret.iconData = Arrays.copyOf(this.iconData, this.iconData.length); + } + ret.customIconUUID = this.customIconUUID; + + for(Property property:properties){ + ret.properties.add((Property) property.clone()); + } + if(this.history!=null){ + ret.history = (History) this.history.clone(); + } + if(this.times!=null){ + ret.times = (Times) this.times.clone(); + } + return ret; + } } diff --git a/src/main/java/de/slackspace/openkeepass/domain/Group.java b/src/main/java/de/slackspace/openkeepass/domain/Group.java index d610169..6dbea69 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/Group.java +++ b/src/main/java/de/slackspace/openkeepass/domain/Group.java @@ -1,6 +1,7 @@ package de.slackspace.openkeepass.domain; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.UUID; @@ -21,7 +22,7 @@ */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -public class Group implements KeePassFileElement { +public class Group implements KeePassFileElement, Cloneable { @XmlElement(name = "UUID") @XmlJavaTypeAdapter(UUIDXmlAdapter.class) @@ -235,4 +236,25 @@ public final boolean equals(Object obj) { return true; } + protected Object clone() throws CloneNotSupportedException { + Group ret = new Group(); + ret.uuid = this.uuid; + ret.name = this.name; + ret.iconId = this.iconId; + if(this.iconData!=null){ + ret.iconData = Arrays.copyOf(this.iconData, this.iconData.length); + } + ret.customIconUUID = this.customIconUUID; + if(this.times!=null){ + ret.times = (Times) this.times.clone(); + } + ret.isExpanded = this.isExpanded; + for(final Group g:this.getGroups()){ + ret.groups.add((Group)g.clone()); + } + for(final Entry e:this.getEntries()){ + ret.entries.add((Entry)e.clone()); + } + return ret; + } } diff --git a/src/main/java/de/slackspace/openkeepass/domain/History.java b/src/main/java/de/slackspace/openkeepass/domain/History.java index 29315af..e4248dd 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/History.java +++ b/src/main/java/de/slackspace/openkeepass/domain/History.java @@ -10,7 +10,7 @@ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -public class History { +public class History implements Cloneable{ @XmlElement(name = "Entry") private List entries = new ArrayList(); @@ -43,5 +43,14 @@ public final boolean equals(Object obj) { return false; return true; } + + @Override + protected Object clone() throws CloneNotSupportedException { + History ret = new History(); + for(Entry entry:entries){ + ret.entries.add((Entry) entry.clone()); + } + return ret; + } } diff --git a/src/main/java/de/slackspace/openkeepass/domain/KeePassFile.java b/src/main/java/de/slackspace/openkeepass/domain/KeePassFile.java index d006376..7f496cc 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/KeePassFile.java +++ b/src/main/java/de/slackspace/openkeepass/domain/KeePassFile.java @@ -18,7 +18,7 @@ */ @XmlRootElement(name = "KeePassFile") @XmlAccessorType(XmlAccessType.FIELD) -public class KeePassFile implements KeePassFileElement { +public class KeePassFile implements KeePassFileElement, Cloneable { @XmlElement(name = "Meta") private Meta meta; @@ -323,4 +323,18 @@ public boolean matches(Group item) { return null; } } + + + + @Override + public Object clone() throws CloneNotSupportedException { + KeePassFile ret = new KeePassFile(); + if(this.meta!=null){ + ret.meta = (Meta) this.meta.clone(); + } + if(this.root!=null){ + ret.root = (Group) this.root.clone(); + } + return ret; + } } diff --git a/src/main/java/de/slackspace/openkeepass/domain/Meta.java b/src/main/java/de/slackspace/openkeepass/domain/Meta.java index 7d481f0..2072110 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/Meta.java +++ b/src/main/java/de/slackspace/openkeepass/domain/Meta.java @@ -19,7 +19,7 @@ */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -public class Meta { +public class Meta implements Cloneable{ @XmlElement(name = "Generator") private String generator; @@ -211,4 +211,35 @@ public final boolean equals(Object obj) { public String toString() { return "Meta [generator=" + generator + ", databaseName=" + databaseName + ", databaseDescription=" + databaseDescription + "]"; } + + + @Override + protected Object clone() throws CloneNotSupportedException { + + Meta ret = new Meta(); + ret.generator = this.generator; + ret.databaseName = this.databaseName; + ret.databaseDescription = this.databaseDescription; + if(this.databaseNameChanged!=null){ + ret.databaseNameChanged = (Calendar)this.databaseNameChanged.clone(); + } + if(this.databaseDescriptionChanged!=null){ + ret.databaseDescriptionChanged = (Calendar)this.databaseDescriptionChanged.clone(); + } + ret.maintenanceHistoryDays = this.maintenanceHistoryDays; + ret.recycleBinUuid = this.recycleBinUuid; + + if(this.recycleBinChanged!=null){ + ret.recycleBinChanged = (Calendar)this.recycleBinChanged.clone(); + } + ret.recycleBinEnabled = this.recycleBinEnabled; + ret.historyMaxItems = this.historyMaxItems; + ret.historyMaxSize = this.historyMaxSize; + if(this.customIcons != null){ + ret.customIcons = (CustomIcons) this.customIcons.clone(); + } + return ret; + } + + } diff --git a/src/main/java/de/slackspace/openkeepass/domain/Property.java b/src/main/java/de/slackspace/openkeepass/domain/Property.java index faeb23c..feb3eb7 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/Property.java +++ b/src/main/java/de/slackspace/openkeepass/domain/Property.java @@ -12,7 +12,7 @@ */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -public class Property implements KeePassFileElement { +public class Property implements KeePassFileElement, Cloneable{ @XmlElement(name = "Key") private String key; @@ -79,5 +79,10 @@ public final boolean equals(Object obj) { return false; return true; } + + @Override + protected Object clone() throws CloneNotSupportedException { + return new Property(this.getKey(), this.getValue(), this.isProtected()); + } } diff --git a/src/main/java/de/slackspace/openkeepass/domain/Times.java b/src/main/java/de/slackspace/openkeepass/domain/Times.java index 9d439c7..1253f6a 100644 --- a/src/main/java/de/slackspace/openkeepass/domain/Times.java +++ b/src/main/java/de/slackspace/openkeepass/domain/Times.java @@ -16,7 +16,7 @@ */ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) -public class Times { +public class Times implements Cloneable{ @XmlElement(name = "LastModificationTime") private Calendar lastModificationTime; @@ -145,4 +145,28 @@ public String toString() { return "Times [lastModificationTime=" + lastModificationTime + ", creationTime=" + creationTime + "]"; } + + @Override + protected Object clone() throws CloneNotSupportedException { + Times ret = new Times(); + if(this.lastModificationTime!=null){ + ret.lastModificationTime = (Calendar)this.lastModificationTime.clone(); + } + if(this.creationTime!=null){ + ret.creationTime = (Calendar)this.creationTime.clone(); + } + if(this.lastAccessTime!=null){ + ret.lastAccessTime = (Calendar)this.lastAccessTime.clone(); + } + if(this.expiryTime!=null){ + ret.expiryTime = (Calendar)this.expiryTime.clone(); + } + ret.expires = this.expires; + ret.usageCount = this.usageCount; + + if(this.locationChanged!=null){ + ret.locationChanged = (Calendar)this.locationChanged.clone(); + } + return ret; + } }