Fix binary save

This commit is contained in:
J-Jamet
2021-03-23 21:00:23 +01:00
parent e10bdc1169
commit 02a779f9a2
11 changed files with 81 additions and 102 deletions

View File

@@ -229,7 +229,7 @@ class IconPickerActivity : LockingActivity() {
if (documentFile.length() > MAX_ICON_SIZE) {
iconCustomState.errorStringId = R.string.error_file_to_big
} else {
mDatabase?.buildNewCustomIcon() { customIcon, binary ->
mDatabase?.buildNewCustomIcon { customIcon, binary ->
if (customIcon != null) {
iconCustomState.iconCustom = customIcon
mDatabase?.let { database ->
@@ -241,7 +241,7 @@ class IconPickerActivity : LockingActivity() {
when {
binary == null -> {
}
binary.getSize(database.binaryCache) <= 0 -> {
binary.getSize() <= 0 -> {
}
database.isCustomIconBinaryDuplicate(binary) -> {
iconCustomState.errorStringId = R.string.error_duplicate_file

View File

@@ -69,9 +69,7 @@ class ImageViewerActivity : LockingActivity() {
supportActionBar?.title = attachment.name
val size = mDatabase?.binaryCache?.let {
attachment.binaryData.getSize(it)
} ?: 0L
val size = attachment.binaryData.getSize()
supportActionBar?.subtitle = Formatter.formatFileSize(this, size)
mDatabase?.let { database ->

View File

@@ -126,9 +126,7 @@ class EntryAttachmentsItemsAdapter(context: Context)
holder.binaryFileTitle.setTextColor(mTitleColor)
}
val size = database?.binaryCache?.let {
entryAttachmentState.attachment.binaryData.getSize(it)
} ?: 0L
val size = entryAttachmentState.attachment.binaryData.getSize()
holder.binaryFileSize.text = Formatter.formatFileSize(context, size)
holder.binaryFileCompression.apply {
if (entryAttachmentState.attachment.binaryData.isCompressed) {

View File

@@ -60,17 +60,12 @@ class BinaryByte : BinaryData {
@Throws(IOException::class)
override fun getInputDataStream(binaryCache: BinaryCache): InputStream {
return when {
getSize(binaryCache) > 0 -> {
Base64InputStream(ByteArrayInputStream(getByteArray(binaryCache)), Base64.NO_WRAP)
}
else -> ByteArrayInputStream(ByteArray(0))
}
return Base64InputStream(ByteArrayInputStream(getByteArray(binaryCache)), Base64.NO_WRAP)
}
@Throws(IOException::class)
override fun getOutputDataStream(binaryCache: BinaryCache): OutputStream {
return Base64OutputStream(ByteOutputStream(binaryCache), Base64.NO_WRAP)
return BinaryCountingOutputStream(Base64OutputStream(ByteOutputStream(binaryCache), Base64.NO_WRAP))
}
@Throws(IOException::class)
@@ -105,14 +100,6 @@ class BinaryByte : BinaryData {
return getByteArray(binaryCache).isNotEmpty()
}
override fun getSize(binaryCache: BinaryCache): Long {
return getByteArray(binaryCache).size.toLong()
}
override fun binaryHash(binaryCache: BinaryCache): Int {
return getByteArray(binaryCache).contentHashCode()
}
@Throws(IOException::class)
override fun clear(binaryCache: BinaryCache) {
binaryCache.removeByteArray(mDataByteId)

View File

@@ -23,9 +23,12 @@ import android.app.ActivityManager
import android.content.Context
import android.os.Parcel
import android.os.Parcelable
import org.apache.commons.io.output.CountingOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.nio.ByteBuffer
import java.security.MessageDigest
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
@@ -36,22 +39,30 @@ abstract class BinaryData : Parcelable {
var isProtected: Boolean = false
protected set
var isCorrupted: Boolean = false
private var mLength: Long = 0
private var mBinaryHash = 0
protected constructor(compressed: Boolean = false, protected: Boolean = false) {
this.isCompressed = compressed
this.isProtected = protected
this.mLength = 0
this.mBinaryHash = 0
}
protected constructor(parcel: Parcel) {
isCompressed = parcel.readByte().toInt() != 0
isProtected = parcel.readByte().toInt() != 0
isCorrupted = parcel.readByte().toInt() != 0
mLength = parcel.readLong()
mBinaryHash = parcel.readInt()
}
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeByte((if (isCompressed) 1 else 0).toByte())
dest.writeByte((if (isProtected) 1 else 0).toByte())
dest.writeByte((if (isCorrupted) 1 else 0).toByte())
dest.writeLong(mLength)
dest.writeInt(mBinaryHash)
}
@Throws(IOException::class)
@@ -85,13 +96,19 @@ abstract class BinaryData : Parcelable {
abstract fun decompress(binaryCache: BinaryCache)
@Throws(IOException::class)
abstract fun dataExists(binaryCache: BinaryCache): Boolean
open fun dataExists(binaryCache: BinaryCache): Boolean {
return mLength > 0
}
@Throws(IOException::class)
abstract fun getSize(binaryCache: BinaryCache): Long
fun getSize(): Long {
return mLength
}
@Throws(IOException::class)
abstract fun binaryHash(binaryCache: BinaryCache): Int
fun binaryHash(): Int {
return mBinaryHash
}
@Throws(IOException::class)
abstract fun clear(binaryCache: BinaryCache)
@@ -115,9 +132,52 @@ abstract class BinaryData : Parcelable {
var result = isCompressed.hashCode()
result = 31 * result + isProtected.hashCode()
result = 31 * result + isCorrupted.hashCode()
result = 31 * result + mLength.hashCode()
result = 31 * result + mBinaryHash
return result
}
/**
* Custom OutputStream to calculate the size and hash of binary file
*/
protected inner class BinaryCountingOutputStream(out: OutputStream): CountingOutputStream(out) {
private val mMessageDigest: MessageDigest
init {
mLength = 0
mMessageDigest = MessageDigest.getInstance("MD5")
mBinaryHash = 0
}
override fun beforeWrite(n: Int) {
super.beforeWrite(n)
mLength = byteCount
}
override fun write(idx: Int) {
super.write(idx)
mMessageDigest.update(idx.toByte())
}
override fun write(bts: ByteArray) {
super.write(bts)
mMessageDigest.update(bts)
}
override fun write(bts: ByteArray, st: Int, end: Int) {
super.write(bts, st, end)
mMessageDigest.update(bts, st, end)
}
override fun close() {
super.close()
mLength = byteCount
val bytes = mMessageDigest.digest()
mBinaryHash = ByteBuffer.wrap(bytes).int
}
}
companion object {
private val TAG = BinaryData::class.java.name

View File

@@ -25,10 +25,7 @@ import android.util.Base64
import android.util.Base64InputStream
import android.util.Base64OutputStream
import com.kunzisoft.keepass.stream.readAllBytes
import org.apache.commons.io.output.CountingOutputStream
import java.io.*
import java.nio.ByteBuffer
import java.security.MessageDigest
import java.util.zip.GZIPOutputStream
import javax.crypto.Cipher
import javax.crypto.CipherInputStream
@@ -37,8 +34,6 @@ import javax.crypto.spec.IvParameterSpec
class BinaryFile : BinaryData {
private var mLength: Long = 0
private var mBinaryHash = 0
private var mDataFile: File? = null
// Cipher to encrypt temp file
@@ -50,14 +45,10 @@ class BinaryFile : BinaryData {
constructor(dataFile: File,
compressed: Boolean = false,
protected: Boolean = false) : super(compressed, protected) {
this.mLength = 0
this.mBinaryHash = 0
this.mDataFile = dataFile
}
constructor(parcel: Parcel) : super(parcel) {
mLength = parcel.readLong()
mBinaryHash = parcel.readInt()
parcel.readString()?.let {
mDataFile = File(it)
}
@@ -65,8 +56,6 @@ class BinaryFile : BinaryData {
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
dest.writeLong(mLength)
dest.writeInt(mBinaryHash)
dest.writeString(mDataFile?.absolutePath)
}
@@ -154,15 +143,7 @@ class BinaryFile : BinaryData {
}
override fun dataExists(binaryCache: BinaryCache): Boolean {
return mDataFile != null && mLength > 0
}
override fun getSize(binaryCache: BinaryCache): Long {
return mLength
}
override fun binaryHash(binaryCache: BinaryCache): Int {
return mBinaryHash
return mDataFile != null && super.dataExists(binaryCache)
}
override fun clear(binaryCache: BinaryCache) {
@@ -185,51 +166,9 @@ class BinaryFile : BinaryData {
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + (mDataFile?.hashCode() ?: 0)
result = 31 * result + mLength.hashCode()
result = 31 * result + mBinaryHash
return result
}
/**
* Custom OutputStream to calculate the size and hash of binary file
*/
private inner class BinaryCountingOutputStream(out: OutputStream): CountingOutputStream(out) {
private val mMessageDigest: MessageDigest
init {
mLength = 0
mMessageDigest = MessageDigest.getInstance("MD5")
mBinaryHash = 0
}
override fun beforeWrite(n: Int) {
super.beforeWrite(n)
mLength = byteCount
}
override fun write(idx: Int) {
super.write(idx)
mMessageDigest.update(idx.toByte())
}
override fun write(bts: ByteArray) {
super.write(bts)
mMessageDigest.update(bts)
}
override fun write(bts: ByteArray, st: Int, end: Int) {
super.write(bts, st, end)
mMessageDigest.update(bts, st, end)
}
override fun close() {
super.close()
mLength = byteCount
val bytes = mMessageDigest.digest()
mBinaryHash = ByteBuffer.wrap(bytes).int
}
}
companion object {
private val TAG = BinaryFile::class.java.name

View File

@@ -120,11 +120,11 @@ abstract class BinaryPool<T>(private val mBinaryCache: BinaryCache) {
fun isBinaryDuplicate(binaryData: BinaryData?): Boolean {
try {
binaryData?.let {
if (it.getSize(mBinaryCache) > 0) {
val searchBinaryMD5 = it.binaryHash(mBinaryCache)
if (it.getSize() > 0) {
val searchBinaryMD5 = it.binaryHash()
var i = 0
for ((_, binary) in pool) {
if (binary.binaryHash(mBinaryCache) == searchBinaryMD5) {
if (binary.binaryHash() == searchBinaryMD5) {
i++
if (i > 1)
return true
@@ -164,10 +164,10 @@ abstract class BinaryPool<T>(private val mBinaryCache: BinaryCache) {
// Don't deduplicate
val existentBinary =
try {
if (binary.getSize(mBinaryCache) > 0) {
if (binary.getSize() > 0) {
keyBinaryList.find {
val hash0 = it.binary.binaryHash(mBinaryCache)
val hash1 = binary.binaryHash(mBinaryCache)
val hash0 = it.binary.binaryHash()
val hash1 = binary.binaryHash()
hash0 != 0 && hash1 != 0 && hash0 == hash1
}
} else {

View File

@@ -297,10 +297,7 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
var size = 0L
for ((label, poolId) in binaries) {
size += label.length.toLong()
val binarySize = mDatabase?.binaryCache?.let {
attachmentPool[poolId]?.getSize(it)
}
size += binarySize ?: 0
size += attachmentPool[poolId]?.getSize() ?: 0
}
return size
}

View File

@@ -143,7 +143,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
// Write type binary
dataOutputStream.writeByte(DatabaseHeaderKDBX.PwDbInnerHeaderV4Fields.Binary)
// Write size
dataOutputStream.writeUInt(UnsignedInt.fromKotlinLong(binary.getSize(binaryCache) + 1))
dataOutputStream.writeUInt(UnsignedInt.fromKotlinLong(binary.getSize() + 1))
// Write protected flag
var flag = DatabaseHeaderKDBX.KdbxBinaryFlags.None
if (binary.isProtected) {
@@ -499,7 +499,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
mDatabaseKDBX.attachmentPool.doForEachOrderedBinaryWithoutDuplication { index, binary ->
xml.startTag(null, DatabaseKDBXXML.ElemBinary)
xml.attribute(null, DatabaseKDBXXML.AttrId, index.toString())
if (binary.getSize(binaryCache) > 0) {
if (binary.getSize() > 0) {
if (binary.isCompressed) {
xml.attribute(null, DatabaseKDBXXML.AttrCompressed, DatabaseKDBXXML.ValTrue)
}

View File

@@ -95,7 +95,7 @@ class EntryOutputKDB(private val mDatabase: DatabaseKDB,
// Binary
mOutputStream.write(BINARY_DATA_FIELD_TYPE)
val binaryData = mEntry.getBinary(mDatabase.attachmentPool)
val binaryDataLength = binaryData?.getSize(mDatabase.binaryCache) ?: 0L
val binaryDataLength = binaryData?.getSize() ?: 0L
// Write data length
mOutputStream.write(uIntTo4Bytes(UnsignedInt.fromKotlinLong(binaryDataLength)))
// Write data

View File

@@ -40,7 +40,7 @@ object BinaryDatabaseManager {
update: ((percent: Int)->Unit)? = null,
canceled: ()-> Boolean = { false },
bufferSize: Int = DEFAULT_BUFFER_SIZE) {
val fileSize = binaryData.getSize(binaryCache)
val fileSize = binaryData.getSize()
var dataDownloaded = 0L
binaryData.getUnGzipInputDataStream(binaryCache).use { inputStream ->
inputStream.readAllBytes(bufferSize, canceled) { buffer ->