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