mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Change save binaries compression for database 3.1 & 4
This commit is contained in:
@@ -72,6 +72,14 @@ class BinaryAttachment : Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun getUnGzipInputDataStream(): InputStream {
|
||||
return if (isCompressed)
|
||||
GZIPInputStream(getInputDataStream())
|
||||
else
|
||||
getInputDataStream()
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun getOutputDataStream(): OutputStream {
|
||||
return when {
|
||||
@@ -110,7 +118,7 @@ class BinaryAttachment : Parcelable {
|
||||
if (isCompressed) {
|
||||
val fileBinaryDecompress = File(concreteDataFile.parent, concreteDataFile.name + "_temp")
|
||||
FileOutputStream(fileBinaryDecompress).use { outputStream ->
|
||||
GZIPInputStream(getInputDataStream()).use { inputStream ->
|
||||
getUnGzipInputDataStream().use { inputStream ->
|
||||
inputStream.readBytes(bufferSize) { buffer ->
|
||||
outputStream.write(buffer)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class BinaryPool {
|
||||
binaryAttachment.clear()
|
||||
}
|
||||
|
||||
fun findUnusedKey(): Int {
|
||||
private fun findUnusedKey(): Int {
|
||||
var unusedKey = 0
|
||||
while (pool[unusedKey] != null)
|
||||
unusedKey++
|
||||
|
||||
@@ -233,9 +233,11 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
|
||||
var data = ByteArray(0)
|
||||
if (size > 0) {
|
||||
if (fieldId != DatabaseHeaderKDBX.PwDbInnerHeaderV4Fields.Binary)
|
||||
if (fieldId != DatabaseHeaderKDBX.PwDbInnerHeaderV4Fields.Binary) {
|
||||
// TODO OOM here
|
||||
data = dataInputStream.readBytes(size)
|
||||
}
|
||||
}
|
||||
|
||||
var result = true
|
||||
when (fieldId) {
|
||||
@@ -249,12 +251,11 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
header.innerRandomStreamKey = data
|
||||
}
|
||||
DatabaseHeaderKDBX.PwDbInnerHeaderV4Fields.Binary -> {
|
||||
val byteLength = size - 1
|
||||
// Read in a file
|
||||
val protectedFlag = dataInputStream.readBytes(1)[0].toInt() != 0
|
||||
// Unknown compression at this level
|
||||
val compression = mDatabase.compressionAlgorithm == CompressionAlgorithm.GZip
|
||||
val protectedBinary = mDatabase.buildNewBinary(cacheDirectory, protectedFlag, compression)
|
||||
val byteLength = size - 1
|
||||
// No compression at this level
|
||||
val protectedBinary = mDatabase.buildNewBinary(cacheDirectory, protectedFlag, false)
|
||||
protectedBinary.getOutputDataStream().use { outputStream ->
|
||||
dataInputStream.readBytes(byteLength, DatabaseKDBX.BUFFER_SIZE_BYTES) { buffer ->
|
||||
outputStream.write(buffer)
|
||||
@@ -940,27 +941,28 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
|
||||
// Reference Id to a binary already present in binary pool
|
||||
val ref = xpp.getAttributeValue(null, DatabaseKDBXXML.AttrRef)
|
||||
if (ref != null) {
|
||||
xpp.next() // Consume end tag
|
||||
|
||||
val id = Integer.parseInt(ref)
|
||||
return mDatabase.binaryPool[id]
|
||||
}
|
||||
|
||||
// New id to a binary
|
||||
val key = xpp.getAttributeValue(null, DatabaseKDBXXML.AttrId)
|
||||
return if (key != null) {
|
||||
|
||||
return when {
|
||||
ref != null -> {
|
||||
xpp.next() // Consume end tag
|
||||
val id = Integer.parseInt(ref)
|
||||
mDatabase.binaryPool[id]
|
||||
}
|
||||
key != null -> {
|
||||
createBinary(key.toIntOrNull(), xpp)
|
||||
}
|
||||
|
||||
else -> {
|
||||
// New binary to retrieve
|
||||
else {
|
||||
createBinary(null, xpp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class, XmlPullParserException::class)
|
||||
private fun createBinary(binaryId: Int?, xpp: XmlPullParser): BinaryAttachment? {
|
||||
var compressed: Boolean = mDatabase.compressionAlgorithm == CompressionAlgorithm.GZip
|
||||
var compressed = false
|
||||
var protected = false
|
||||
|
||||
if (xpp.attributeCount > 0) {
|
||||
@@ -980,7 +982,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
return null
|
||||
val data = Base64.decode(base64, BASE_64_FLAG)
|
||||
|
||||
// Force compression in this specific case
|
||||
// Build the new binary and compress
|
||||
val binaryAttachment = mDatabase.buildNewBinary(cacheDirectory, protected, compressed, binaryId)
|
||||
binaryAttachment.getOutputDataStream().use { outputStream ->
|
||||
outputStream.write(data)
|
||||
|
||||
@@ -54,13 +54,16 @@ class DatabaseInnerHeaderOutputKDBX(private val database: DatabaseKDBX,
|
||||
}
|
||||
|
||||
dataOutputStream.write(DatabaseHeaderKDBX.PwDbInnerHeaderV4Fields.Binary.toInt())
|
||||
dataOutputStream.writeInt(protectedBinary.length().toInt() + 1) // TODO verify
|
||||
dataOutputStream.writeInt(protectedBinary.length().toInt() + 1)
|
||||
dataOutputStream.write(flag.toInt())
|
||||
|
||||
protectedBinary.getInputDataStream().readBytes(BUFFER_SIZE_BYTES) { buffer ->
|
||||
// if was compressed in cache, uncompress it
|
||||
protectedBinary.getUnGzipInputDataStream().use { inputStream ->
|
||||
inputStream.readBytes(BUFFER_SIZE_BYTES) { buffer ->
|
||||
dataOutputStream.write(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataOutputStream.write(DatabaseHeaderKDBX.PwDbInnerHeaderV4Fields.EndOfHeader.toInt())
|
||||
dataOutputStream.writeInt(0)
|
||||
|
||||
@@ -55,7 +55,6 @@ import java.io.OutputStream
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.CipherOutputStream
|
||||
@@ -422,7 +421,6 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
private fun writeBinary(binary : BinaryAttachment) {
|
||||
val binaryLength = binary.length()
|
||||
if (binaryLength > 0) {
|
||||
|
||||
if (binary.isProtected) {
|
||||
xml.attribute(null, DatabaseKDBXXML.AttrProtected, DatabaseKDBXXML.ValTrue)
|
||||
|
||||
@@ -433,21 +431,11 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
xml.text(charArray, 0, charArray.size)
|
||||
}
|
||||
} else {
|
||||
// Force binary compression from database (compression was harmonized during import)
|
||||
if (mDatabaseKDBX.compressionAlgorithm === CompressionAlgorithm.GZip) {
|
||||
if (binary.isCompressed) {
|
||||
xml.attribute(null, DatabaseKDBXXML.AttrCompressed, DatabaseKDBXXML.ValTrue)
|
||||
}
|
||||
|
||||
// Force decompression in this specific case
|
||||
val binaryInputStream = if (mDatabaseKDBX.compressionAlgorithm == CompressionAlgorithm.None
|
||||
&& binary.isCompressed) {
|
||||
GZIPInputStream(binary.getInputDataStream())
|
||||
} else {
|
||||
binary.getInputDataStream()
|
||||
}
|
||||
|
||||
// Write the XML
|
||||
binaryInputStream.readBytes(BUFFER_SIZE_BYTES) { buffer ->
|
||||
binary.getInputDataStream().readBytes(BUFFER_SIZE_BYTES) { buffer ->
|
||||
val charArray = String(Base64.encode(buffer, BASE_64_FLAG)).toCharArray()
|
||||
xml.text(charArray, 0, charArray.size)
|
||||
}
|
||||
@@ -560,23 +548,15 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
|
||||
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
|
||||
private fun writeEntryBinaries(binaries: LinkedHashMap<String, Int>) {
|
||||
binaries.forEach {
|
||||
for ((label, poolId) in binaries) {
|
||||
xml.startTag(null, DatabaseKDBXXML.ElemBinary)
|
||||
xml.startTag(null, DatabaseKDBXXML.ElemKey)
|
||||
xml.text(safeXmlString(it.key))
|
||||
xml.text(safeXmlString(label))
|
||||
xml.endTag(null, DatabaseKDBXXML.ElemKey)
|
||||
|
||||
xml.startTag(null, DatabaseKDBXXML.ElemValue)
|
||||
xml.attribute(null, DatabaseKDBXXML.AttrRef, it.value.toString())
|
||||
/*
|
||||
// By default use only pool data in head to save binaries
|
||||
val ref = mDatabaseKDBX.binaryPool.findKey(it.binaryAttachment)
|
||||
if (ref != null) {
|
||||
xml.attribute(null, DatabaseKDBXXML.AttrRef, ref.toString())
|
||||
} else {
|
||||
writeBinary(it.binaryAttachment)
|
||||
}
|
||||
*/
|
||||
// Use only pool data in Meta to save binaries
|
||||
xml.attribute(null, DatabaseKDBXXML.AttrRef, poolId.toString())
|
||||
xml.endTag(null, DatabaseKDBXXML.ElemValue)
|
||||
|
||||
xml.endTag(null, DatabaseKDBXXML.ElemBinary)
|
||||
|
||||
@@ -362,11 +362,7 @@ class AttachmentFileNotificationService: LockNotificationService() {
|
||||
var dataDownloaded = 0L
|
||||
val fileSize = binaryAttachment.length()
|
||||
UriUtil.getUriOutputStream(contentResolver, attachmentToUploadUri)?.use { outputStream ->
|
||||
if (binaryAttachment.isCompressed) {
|
||||
GZIPInputStream(binaryAttachment.getInputDataStream())
|
||||
} else {
|
||||
binaryAttachment.getInputDataStream()
|
||||
}.use { inputStream ->
|
||||
binaryAttachment.getUnGzipInputDataStream().use { inputStream ->
|
||||
inputStream.readBytes(bufferSize) { buffer ->
|
||||
outputStream.write(buffer)
|
||||
dataDownloaded += buffer.size
|
||||
|
||||
Reference in New Issue
Block a user