mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix length and better streams implementation
This commit is contained in:
@@ -124,9 +124,9 @@ dependencies {
|
||||
implementation 'com.github.Kunzisoft:AndroidClearChroma:2.4'
|
||||
// Education
|
||||
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.0'
|
||||
// Apache Commons Collections
|
||||
// Apache Commons
|
||||
implementation 'commons-collections:commons-collections:3.2.2'
|
||||
// Apache Commons Codec
|
||||
implementation 'commons-io:commons-io:2.8.0'
|
||||
implementation 'commons-codec:commons-codec:1.15'
|
||||
// Icon pack
|
||||
implementation project(path: ':icon-pack-classic')
|
||||
|
||||
@@ -77,7 +77,7 @@ class EntryAttachmentsItemsAdapter(context: Context)
|
||||
holder.binaryFileTitle.setTextColor(mTitleColor)
|
||||
}
|
||||
holder.binaryFileSize.text = Formatter.formatFileSize(context,
|
||||
entryAttachmentState.attachment.binaryAttachment.length())
|
||||
entryAttachmentState.attachment.binaryAttachment.length)
|
||||
holder.binaryFileCompression.apply {
|
||||
if (entryAttachmentState.attachment.binaryAttachment.isCompressed) {
|
||||
text = CompressionAlgorithm.GZip.getName(context.resources)
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.stream.readAllBytes
|
||||
import org.apache.commons.io.output.CountingOutputStream
|
||||
import java.io.*
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
@@ -33,6 +34,8 @@ import javax.crypto.CipherOutputStream
|
||||
class BinaryAttachment : Parcelable {
|
||||
|
||||
private var dataFile: File? = null
|
||||
var length: Long = 0
|
||||
private set
|
||||
var isCompressed: Boolean = false
|
||||
private set
|
||||
var isProtected: Boolean = false
|
||||
@@ -42,10 +45,6 @@ class BinaryAttachment : Parcelable {
|
||||
private var cipherEncryption: Cipher = Cipher.getInstance(Database.LoadedKey.BINARY_CIPHER)
|
||||
private var cipherDecryption: Cipher = Cipher.getInstance(Database.LoadedKey.BINARY_CIPHER)
|
||||
|
||||
fun length(): Long {
|
||||
return dataFile?.length() ?: 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty protected binary
|
||||
*/
|
||||
@@ -53,6 +52,7 @@ class BinaryAttachment : Parcelable {
|
||||
|
||||
constructor(dataFile: File, compressed: Boolean = false, protected: Boolean = false) {
|
||||
this.dataFile = dataFile
|
||||
this.length = 0
|
||||
this.isCompressed = compressed
|
||||
this.isProtected = protected
|
||||
}
|
||||
@@ -61,6 +61,7 @@ class BinaryAttachment : Parcelable {
|
||||
parcel.readString()?.let {
|
||||
dataFile = File(it)
|
||||
}
|
||||
length = parcel.readLong()
|
||||
isCompressed = parcel.readByte().toInt() != 0
|
||||
isProtected = parcel.readByte().toInt() != 0
|
||||
isCorrupted = parcel.readByte().toInt() != 0
|
||||
@@ -68,31 +69,20 @@ class BinaryAttachment : Parcelable {
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun getInputDataStream(cipherKey: Database.LoadedKey): InputStream {
|
||||
return when {
|
||||
length() > 0 -> {
|
||||
cipherDecryption.init(Cipher.DECRYPT_MODE, cipherKey.key, cipherKey.iv)
|
||||
CipherInputStream(FileInputStream(dataFile!!), cipherDecryption)
|
||||
}
|
||||
else -> ByteArrayInputStream(ByteArray(0))
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun getUnGzipInputDataStream(cipherKey: Database.LoadedKey): InputStream {
|
||||
return if (isCompressed)
|
||||
GZIPInputStream(getInputDataStream(cipherKey))
|
||||
else
|
||||
getInputDataStream(cipherKey)
|
||||
return buildInputStream(dataFile!!, cipherKey)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun getOutputDataStream(cipherKey: Database.LoadedKey): OutputStream {
|
||||
return when {
|
||||
dataFile != null -> {
|
||||
cipherEncryption.init(Cipher.ENCRYPT_MODE, cipherKey.key, cipherKey.iv)
|
||||
CipherOutputStream(FileOutputStream(dataFile!!), cipherEncryption)
|
||||
return buildOutputStream(dataFile!!, cipherKey)
|
||||
}
|
||||
else -> throw IOException("Unable to write in an unknown file")
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun getUnGzipInputDataStream(cipherKey: Database.LoadedKey): InputStream {
|
||||
return if (isCompressed) {
|
||||
GZIPInputStream(getInputDataStream(cipherKey))
|
||||
} else {
|
||||
getInputDataStream(cipherKey)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +95,28 @@ class BinaryAttachment : Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun buildInputStream(file: File?, cipherKey: Database.LoadedKey): InputStream {
|
||||
return when {
|
||||
file != null && file.length() > 0 -> {
|
||||
cipherDecryption.init(Cipher.DECRYPT_MODE, cipherKey.key, cipherKey.iv)
|
||||
CipherInputStream(FileInputStream(file), cipherDecryption)
|
||||
}
|
||||
else -> ByteArrayInputStream(ByteArray(0))
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun buildOutputStream(file: File?, cipherKey: Database.LoadedKey): OutputStream {
|
||||
return when {
|
||||
file != null -> {
|
||||
cipherEncryption.init(Cipher.ENCRYPT_MODE, cipherKey.key, cipherKey.iv)
|
||||
BinaryCountingOutputStream(CipherOutputStream(FileOutputStream(file), cipherEncryption))
|
||||
}
|
||||
else -> throw IOException("Unable to write in an unknown file")
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun compress(cipherKey: Database.LoadedKey, bufferSize: Int = DEFAULT_BUFFER_SIZE) {
|
||||
dataFile?.let { concreteDataFile ->
|
||||
@@ -112,8 +124,7 @@ class BinaryAttachment : Parcelable {
|
||||
if (!isCompressed) {
|
||||
// Encrypt the new gzipped temp file
|
||||
val fileBinaryCompress = File(concreteDataFile.parent, concreteDataFile.name + "_temp")
|
||||
cipherEncryption.init(Cipher.ENCRYPT_MODE, cipherKey.key, cipherKey.iv)
|
||||
GZIPOutputStream(CipherOutputStream(FileOutputStream(fileBinaryCompress), cipherEncryption)).use { outputStream ->
|
||||
GZIPOutputStream(buildOutputStream(fileBinaryCompress, cipherKey)).use { outputStream ->
|
||||
getInputDataStream(cipherKey).use { inputStream ->
|
||||
inputStream.readAllBytes(bufferSize) { buffer ->
|
||||
outputStream.write(buffer)
|
||||
@@ -137,8 +148,7 @@ class BinaryAttachment : Parcelable {
|
||||
if (isCompressed) {
|
||||
// Encrypt the new ungzipped temp file
|
||||
val fileBinaryDecompress = File(concreteDataFile.parent, concreteDataFile.name + "_temp")
|
||||
cipherEncryption.init(Cipher.ENCRYPT_MODE, cipherKey.key, cipherKey.iv)
|
||||
CipherOutputStream(FileOutputStream(fileBinaryDecompress), cipherEncryption).use { outputStream ->
|
||||
buildOutputStream(fileBinaryDecompress, cipherKey).use { outputStream ->
|
||||
getUnGzipInputDataStream(cipherKey).use { inputStream ->
|
||||
inputStream.readAllBytes(bufferSize) { buffer ->
|
||||
outputStream.write(buffer)
|
||||
@@ -171,7 +181,8 @@ class BinaryAttachment : Parcelable {
|
||||
return false
|
||||
|
||||
var sameData = false
|
||||
if (dataFile != null && dataFile == other.dataFile)
|
||||
if (dataFile != null && dataFile == other.dataFile
|
||||
&& length == other.length)
|
||||
sameData = true
|
||||
|
||||
return isCompressed == other.isCompressed
|
||||
@@ -187,6 +198,7 @@ class BinaryAttachment : Parcelable {
|
||||
result = 31 * result + if (isProtected) 1 else 0
|
||||
result = 31 * result + if (isCorrupted) 1 else 0
|
||||
result = 31 * result + dataFile!!.hashCode()
|
||||
result = 31 * result + length.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -200,11 +212,25 @@ class BinaryAttachment : Parcelable {
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
dest.writeString(dataFile?.absolutePath)
|
||||
dest.writeLong(length)
|
||||
dest.writeByte((if (isCompressed) 1 else 0).toByte())
|
||||
dest.writeByte((if (isProtected) 1 else 0).toByte())
|
||||
dest.writeByte((if (isCorrupted) 1 else 0).toByte())
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom OutputStream to calculate the size of binary file
|
||||
*/
|
||||
private inner class BinaryCountingOutputStream(out: OutputStream): CountingOutputStream(out) {
|
||||
init {
|
||||
length = 0
|
||||
}
|
||||
override fun close() {
|
||||
super.close()
|
||||
length = byteCount
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val TAG = BinaryAttachment::class.java.name
|
||||
|
||||
@@ -316,7 +316,7 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
||||
var size = 0L
|
||||
for ((label, poolId) in binaries) {
|
||||
size += label.length.toLong()
|
||||
size += binaryPool[poolId]?.length() ?: 0
|
||||
size += binaryPool[poolId]?.length ?: 0
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
// Write type binary
|
||||
dataOutputStream.writeByte(DatabaseHeaderKDBX.PwDbInnerHeaderV4Fields.Binary)
|
||||
// Write size
|
||||
dataOutputStream.writeUInt(UnsignedInt.fromKotlinLong(protectedBinary.length() + 1))
|
||||
dataOutputStream.writeUInt(UnsignedInt.fromKotlinLong(protectedBinary.length + 1))
|
||||
// Write protected flag
|
||||
var flag = DatabaseHeaderKDBX.KdbxBinaryFlags.None
|
||||
if (protectedBinary.isProtected) {
|
||||
@@ -502,7 +502,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
xml.startTag(null, DatabaseKDBXXML.ElemBinary)
|
||||
xml.attribute(null, DatabaseKDBXXML.AttrId, index.toString())
|
||||
val binary = keyBinary.binary
|
||||
if (binary.length() > 0) {
|
||||
if (binary.length > 0) {
|
||||
if (binary.isCompressed) {
|
||||
xml.attribute(null, DatabaseKDBXXML.AttrCompressed, DatabaseKDBXXML.ValTrue)
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ class EntryOutputKDB {
|
||||
// Binary
|
||||
mOutputStream.write(BINARY_DATA_FIELD_TYPE)
|
||||
val binaryData = mEntry.binaryData
|
||||
val binaryDataLength = binaryData?.length() ?: 0L
|
||||
val binaryDataLength = binaryData?.length ?: 0L
|
||||
// Write data length
|
||||
mOutputStream.write(uIntTo4Bytes(UnsignedInt.fromKotlinLong(binaryDataLength)))
|
||||
// Write data
|
||||
|
||||
@@ -373,7 +373,7 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
bufferSize: Int = DEFAULT_BUFFER_SIZE,
|
||||
update: ((percent: Int)->Unit)? = null) {
|
||||
var dataDownloaded = 0L
|
||||
val fileSize = binaryAttachment.length()
|
||||
val fileSize = binaryAttachment.length
|
||||
UriUtil.getUriOutputStream(contentResolver, attachmentToUploadUri)?.use { outputStream ->
|
||||
Database.getInstance().loadedCipherKey?.let { binaryCipherKey ->
|
||||
binaryAttachment.getUnGzipInputDataStream(binaryCipherKey).use { inputStream ->
|
||||
|
||||
Reference in New Issue
Block a user