Upgrade Importer V3

This commit is contained in:
J-Jamet
2019-11-13 15:57:52 +01:00
parent 075a16c1c3
commit b3f232c840
5 changed files with 99 additions and 155 deletions

View File

@@ -21,11 +21,7 @@ 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
import java.util.*
/**
* Structure containing information about one entry.
@@ -56,12 +52,11 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
* @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 (binaryData.contentEquals(ByteArray(0))) return false
if (notes.isEmpty()) return false
if (binaryDesc != PMS_ID_BINDESC) return false
if (title.isEmpty()) return false
@@ -85,10 +80,11 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
constructor(parcel: Parcel) : super(parcel) {
title = parcel.readString() ?: title
username = parcel.readString() ?: username
parcel.readByteArray(passwordBytes)
password = parcel.readString() ?: password
url = parcel.readString() ?: url
notes = parcel.readString() ?: notes
binaryDesc = parcel.readString() ?: binaryDesc
binaryData = ByteArray(parcel.readInt())
parcel.readByteArray(binaryData)
}
@@ -104,10 +100,11 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
super.writeToParcel(dest, flags)
dest.writeString(title)
dest.writeString(username)
dest.writeByteArray(passwordBytes)
dest.writeString(password)
dest.writeString(url)
dest.writeString(notes)
dest.writeString(binaryDesc)
dest.writeInt(binaryData.size)
dest.writeByteArray(binaryData)
}
@@ -115,11 +112,7 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
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)
password = source.password
url = source.url
notes = source.notes
binaryDesc = source.binaryDesc
@@ -131,32 +124,10 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
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 password = ""
override var url = ""
@@ -167,13 +138,6 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
override val type: Type
get() = Type.ENTRY
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. */
@@ -184,21 +148,13 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
@JvmField
val CREATOR: Parcelable.Creator<PwEntryV3> = object : Parcelable.Creator<PwEntryV3> {
override fun createFromParcel(`in`: Parcel): PwEntryV3 {
return PwEntryV3(`in`)
override fun createFromParcel(parcel: Parcel): PwEntryV3 {
return PwEntryV3(parcel)
}
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

@@ -80,6 +80,7 @@ class ProtectedBinary : Parcelable {
private constructor(parcel: Parcel) {
isProtected = parcel.readByte().toInt() != 0
data = ByteArray(parcel.readInt())
parcel.readByteArray(data)
dataFile = File(parcel.readString())
size = parcel.readInt()
@@ -130,8 +131,9 @@ class ProtectedBinary : Parcelable {
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeByte((if (isProtected) 1 else 0).toByte())
dest.writeInt(data?.size ?: 0)
dest.writeByteArray(data)
dest.writeString(dataFile!!.absolutePath)
dest.writeString(dataFile?.absolutePath)
dest.writeInt(size)
}

View File

@@ -328,14 +328,14 @@ class ImporterV3 : Importer<PwDatabaseV3>() {
0x0004 -> ent.title = Types.readCString(buf, offsetMutable)
0x0005 -> ent.url = Types.readCString(buf, offsetMutable)
0x0006 -> ent.username = Types.readCString(buf, offsetMutable)
0x0007 -> ent.setPassword(buf, offsetMutable, Types.strlen(buf, offsetMutable))
0x0007 -> ent.password = Types.readPassword(buf, offsetMutable)
0x0008 -> ent.notes = Types.readCString(buf, offsetMutable)
0x0009 -> ent.creationTime = PwDate(buf, offsetMutable)
0x000A -> ent.lastModificationTime = PwDate(buf, offsetMutable)
0x000B -> ent.lastAccessTime = PwDate(buf, offsetMutable)
0x000C -> ent.expiryTime = PwDate(buf, offsetMutable)
0x000D -> ent.binaryDesc = Types.readCString(buf, offsetMutable)
0x000E -> ent.setBinaryData(buf, offsetMutable, fieldSize)
0x000E -> ent.binaryData = Types.readBytes(buf, offsetMutable, fieldSize)
}// Ignore field
}

View File

@@ -30,7 +30,7 @@ class PwEntryOutputV3
/**
* Output the PwGroupV3 to the stream
*/
(private val mPE: PwEntryV3, private val mOS: OutputStream) {
(private val mEntry: PwEntryV3, private val mOutputStream: OutputStream) {
/**
* Returns the number of bytes written by the stream
* @return Number of bytes written
@@ -45,98 +45,82 @@ class PwEntryOutputV3
length += 134 // Length of fixed size fields
// UUID
mOS.write(UUID_FIELD_TYPE)
mOS.write(UUID_FIELD_SIZE)
mOS.write(Types.UUIDtoBytes(mPE.id))
mOutputStream.write(UUID_FIELD_TYPE)
mOutputStream.write(UUID_FIELD_SIZE)
mOutputStream.write(Types.UUIDtoBytes(mEntry.id))
// Group ID
mOS.write(GROUPID_FIELD_TYPE)
mOS.write(LONG_FOUR)
mOS.write(LEDataOutputStream.writeIntBuf(mPE.parent!!.id))
mOutputStream.write(GROUPID_FIELD_TYPE)
mOutputStream.write(LONG_FOUR)
mOutputStream.write(LEDataOutputStream.writeIntBuf(mEntry.parent!!.id))
// Image ID
mOS.write(IMAGEID_FIELD_TYPE)
mOS.write(LONG_FOUR)
mOS.write(LEDataOutputStream.writeIntBuf(mPE.icon.iconId))
mOutputStream.write(IMAGEID_FIELD_TYPE)
mOutputStream.write(LONG_FOUR)
mOutputStream.write(LEDataOutputStream.writeIntBuf(mEntry.icon.iconId))
// Title
//byte[] title = mPE.title.getBytes("UTF-8");
mOS.write(TITLE_FIELD_TYPE)
val titleLen = Types.writeCString(mPE.title, mOS)
length += titleLen.toLong()
//byte[] title = mEntry.title.getBytes("UTF-8");
mOutputStream.write(TITLE_FIELD_TYPE)
length += Types.writeCString(mEntry.title, mOutputStream).toLong()
// URL
mOS.write(URL_FIELD_TYPE)
val urlLen = Types.writeCString(mPE.url, mOS)
length += urlLen.toLong()
mOutputStream.write(URL_FIELD_TYPE)
length += Types.writeCString(mEntry.url, mOutputStream).toLong()
// Username
mOS.write(USERNAME_FIELD_TYPE)
val userLen = Types.writeCString(mPE.username, mOS)
length += userLen.toLong()
mOutputStream.write(USERNAME_FIELD_TYPE)
length += Types.writeCString(mEntry.username, mOutputStream).toLong()
// Password
val password = mPE.passwordBytes
mOS.write(PASSWORD_FIELD_TYPE)
mOS.write(LEDataOutputStream.writeIntBuf(password.size + 1))
mOS.write(password)
mOS.write(0)
length += (password.size + 1).toLong()
mOutputStream.write(PASSWORD_FIELD_TYPE)
length += Types.writePassword(mEntry.password, mOutputStream).toLong()
// Additional
mOS.write(ADDITIONAL_FIELD_TYPE)
val addlLen = Types.writeCString(mPE.notes, mOS)
length += addlLen.toLong()
mOutputStream.write(ADDITIONAL_FIELD_TYPE)
length += Types.writeCString(mEntry.notes, mOutputStream).toLong()
// Create date
writeDate(CREATE_FIELD_TYPE, mPE.creationTime.byteArrayDate)
writeDate(CREATE_FIELD_TYPE, mEntry.creationTime.byteArrayDate)
// Modification date
writeDate(MOD_FIELD_TYPE, mPE.lastModificationTime.byteArrayDate)
writeDate(MOD_FIELD_TYPE, mEntry.lastModificationTime.byteArrayDate)
// Access date
writeDate(ACCESS_FIELD_TYPE, mPE.lastAccessTime.byteArrayDate)
writeDate(ACCESS_FIELD_TYPE, mEntry.lastAccessTime.byteArrayDate)
// Expiration date
writeDate(EXPIRE_FIELD_TYPE, mPE.expiryTime.byteArrayDate)
writeDate(EXPIRE_FIELD_TYPE, mEntry.expiryTime.byteArrayDate)
// Binary desc
mOS.write(BINARY_DESC_FIELD_TYPE)
val descLen = Types.writeCString(mPE.binaryDesc, mOS)
length += descLen.toLong()
// Binary data
val dataLen = writeByteArray(mPE.binaryData)
length += dataLen.toLong()
// Binary
writeBinary(mEntry.binaryData)
// End
mOS.write(END_FIELD_TYPE)
mOS.write(ZERO_FIELD_SIZE)
}
@Throws(IOException::class)
private fun writeByteArray(data: ByteArray?): Int {
val dataLen: Int = data?.size ?: 0
mOS.write(BINARY_DATA_FIELD_TYPE)
mOS.write(LEDataOutputStream.writeIntBuf(dataLen))
if (data != null) {
mOS.write(data)
}
return dataLen
mOutputStream.write(END_FIELD_TYPE)
mOutputStream.write(ZERO_FIELD_SIZE)
}
@Throws(IOException::class)
private fun writeDate(type: ByteArray, date: ByteArray?) {
mOS.write(type)
mOS.write(DATE_FIELD_SIZE)
mOutputStream.write(type)
mOutputStream.write(DATE_FIELD_SIZE)
if (date != null) {
mOS.write(date)
mOutputStream.write(date)
} else {
mOS.write(ZERO_FIVE)
mOutputStream.write(ZERO_FIVE)
}
}
@Throws(IOException::class)
private fun writeBinary(data: ByteArray?) {
mOutputStream.write(BINARY_DESC_FIELD_TYPE)
length += Types.writeCString(mEntry.binaryDesc, mOutputStream).toLong()
val dataLen: Int = data?.size ?: 0
mOutputStream.write(BINARY_DATA_FIELD_TYPE)
length += Types.writeBytes(data, dataLen, mOutputStream)
}
companion object {
// Constants
val UUID_FIELD_TYPE:ByteArray = LEDataOutputStream.writeUShortBuf(1)

View File

@@ -46,7 +46,7 @@ import com.kunzisoft.keepass.stream.LEDataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.UUID;
@@ -59,16 +59,20 @@ public class Types {
public static long ULONG_MAX_VALUE = -1;
private static Charset defaultCharset = Charset.forName("UTF-8");
private static final byte[] CRLFbuf = { 0x0D, 0x0A };
private static final String CRLF = new String(CRLFbuf);
private static final String SEP = System.getProperty("line.separator");
private static final boolean REPLACE = !SEP.equals(CRLF);
/** Read an unsigned byte */
public static int readUByte( byte[] buf, int offset ) {
return ((int)buf[offset] & 0xFF);
}
/** Write an unsigned byte
*
* @param val
* @param buf
* @param offset
/**
* Write an unsigned byte
*/
public static void writeUByte(int val, byte[] buf, int offset) {
buf[offset] = (byte)(val & 0xFF);
@@ -85,42 +89,16 @@ public class Types {
/**
* Return len of null-terminated string (i.e. distance to null)
* within a byte buffer.
*
* @param buf
* @param offset
* @return
*/
public static int strlen( byte[] buf, int offset ) {
private static int strlen( byte[] buf, int offset ) {
int len = 0;
while( buf[offset + len] != 0 )
len++;
return len;
}
/**
* Copy a sequence of bytes into a new array.
*
* @param b - source array
* @param offset - first byte
* @param len - number of bytes
* @return new byte[len]
*/
public static byte[] extract( byte[] b, int offset, int len ) {
byte[] b2 = new byte[len];
System.arraycopy( b, offset, b2, 0, len );
return b2;
}
private static final byte[] CRLFbuf = { 0x0D, 0x0A };
private static final String CRLF = new String(CRLFbuf);
private static final String SEP = System.getProperty("line.separator");
private static final boolean REPLACE = ! SEP.equals(CRLF);
public static String readCString(byte[] buf, int offset) throws UnsupportedEncodingException {
String jstring = new String(buf, offset, strlen(buf, offset), "UTF-8");
public static String readCString(byte[] buf, int offset) {
String jstring = new String(buf, offset, strlen(buf, offset), defaultCharset);
if ( REPLACE ) {
jstring = jstring.replace(CRLF, SEP);
@@ -141,7 +119,7 @@ public class Types {
str = str.replace(SEP, CRLF);
}
byte[] initial = str.getBytes("UTF-8");
byte[] initial = str.getBytes(defaultCharset);
int length = initial.length+1;
os.write(LEDataOutputStream.writeIntBuf(length));
@@ -151,6 +129,33 @@ public class Types {
return length;
}
public static String readPassword(byte[] buf, int offset) {
return new String(buf, offset, strlen(buf, offset), defaultCharset);
}
public static int writePassword(String str, OutputStream os) throws IOException {
byte[] initial = str.getBytes(defaultCharset);
int length = initial.length+1;
os.write(LEDataOutputStream.writeIntBuf(length));
os.write(initial);
os.write(0x00);
return length;
}
public static byte[] readBytes(byte[] buf, int offset, int len) {
byte[] binaryData = new byte[len];
System.arraycopy(buf, offset, binaryData, 0, len);
return binaryData;
}
public static int writeBytes(byte[] data, int dataLen, OutputStream os ) throws IOException {
os.write(LEDataOutputStream.writeIntBuf(dataLen));
if (data != null) {
os.write(data);
}
return dataLen;
}
public static UUID bytestoUUID(byte[] buf) {
return bytestoUUID(buf, 0);
}
@@ -167,15 +172,12 @@ public class Types {
}
return new UUID(msb, lsb);
}
public static byte[] UUIDtoBytes(UUID uuid) {
byte[] buf = new byte[16];
LEDataOutputStream.writeLong(uuid.getMostSignificantBits(), buf, 0);
LEDataOutputStream.writeLong(uuid.getLeastSignificantBits(), buf, 8);
return buf;
}