mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Upgrade Importer V3
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user