mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Refactor binary class
This commit is contained in:
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.database.element
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
import com.kunzisoft.keepass.utils.MemoryUtil
|
||||
import com.kunzisoft.keepass.utils.ParcelableUtil
|
||||
|
||||
import java.util.HashMap
|
||||
|
||||
@@ -48,7 +48,7 @@ class AutoType : Parcelable {
|
||||
this.enabled = parcel.readByte().toInt() != 0
|
||||
this.obfuscationOptions = parcel.readLong()
|
||||
this.defaultSequence = parcel.readString() ?: defaultSequence
|
||||
this.windowSeqPairs = MemoryUtil.readStringParcelableMap(parcel)
|
||||
this.windowSeqPairs = ParcelableUtil.readStringParcelableMap(parcel)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
@@ -59,7 +59,7 @@ class AutoType : Parcelable {
|
||||
dest.writeByte((if (enabled) 1 else 0).toByte())
|
||||
dest.writeLong(obfuscationOptions)
|
||||
dest.writeString(defaultSequence)
|
||||
MemoryUtil.writeStringParcelableMap(dest, windowSeqPairs)
|
||||
ParcelableUtil.writeStringParcelableMap(dest, windowSeqPairs)
|
||||
}
|
||||
|
||||
fun put(key: String, value: String) {
|
||||
|
||||
@@ -508,5 +508,7 @@ class PwDatabaseV4 : PwDatabase<UUID, UUID, PwGroupV4, PwEntryV4> {
|
||||
private const val KeyDataElementName = "Data"
|
||||
|
||||
const val BASE_64_FLAG = Base64.DEFAULT
|
||||
|
||||
const val BUFFER_SIZE_BYTES = 3 * 128
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedBinary
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
import com.kunzisoft.keepass.utils.MemoryUtil
|
||||
import com.kunzisoft.keepass.utils.ParcelableUtil
|
||||
import java.util.*
|
||||
|
||||
class PwEntryV4 : PwEntry<UUID, UUID, PwGroupV4, PwEntryV4>, PwNodeV4Interface {
|
||||
@@ -96,9 +96,9 @@ class PwEntryV4 : PwEntry<UUID, UUID, PwGroupV4, PwEntryV4>, PwNodeV4Interface {
|
||||
iconCustom = parcel.readParcelable(PwIconCustom::class.java.classLoader) ?: iconCustom
|
||||
usageCount = parcel.readLong()
|
||||
locationChanged = parcel.readParcelable(PwDate::class.java.classLoader) ?: locationChanged
|
||||
customData = MemoryUtil.readStringParcelableMap(parcel)
|
||||
fields = MemoryUtil.readStringParcelableMap(parcel, ProtectedString::class.java)
|
||||
// TODO binaries = MemoryUtil.readStringParcelableMap(parcel, ProtectedBinary.class);
|
||||
customData = ParcelableUtil.readStringParcelableMap(parcel)
|
||||
fields = ParcelableUtil.readStringParcelableMap(parcel, ProtectedString::class.java)
|
||||
// TODO binaries = ParcelableUtil.readStringParcelableMap(parcel, ProtectedBinary.class);
|
||||
foregroundColor = parcel.readString() ?: foregroundColor
|
||||
backgroundColor = parcel.readString() ?: backgroundColor
|
||||
overrideURL = parcel.readString() ?: overrideURL
|
||||
@@ -114,9 +114,9 @@ class PwEntryV4 : PwEntry<UUID, UUID, PwGroupV4, PwEntryV4>, PwNodeV4Interface {
|
||||
dest.writeParcelable(iconCustom, flags)
|
||||
dest.writeLong(usageCount)
|
||||
dest.writeParcelable(locationChanged, flags)
|
||||
MemoryUtil.writeStringParcelableMap(dest, customData)
|
||||
MemoryUtil.writeStringParcelableMap(dest, flags, fields)
|
||||
// TODO MemoryUtil.writeStringParcelableMap(dest, flags, binaries);
|
||||
ParcelableUtil.writeStringParcelableMap(dest, customData)
|
||||
ParcelableUtil.writeStringParcelableMap(dest, flags, fields)
|
||||
// TODO ParcelableUtil.writeStringParcelableMap(dest, flags, binaries);
|
||||
dest.writeString(foregroundColor)
|
||||
dest.writeString(backgroundColor)
|
||||
dest.writeString(overrideURL)
|
||||
|
||||
@@ -69,7 +69,7 @@ class PwGroupV4 : PwGroup<UUID, UUID, PwGroupV4, PwEntryV4>, PwNodeV4Interface {
|
||||
iconCustom = parcel.readParcelable(PwIconCustom::class.java.classLoader) ?: iconCustom
|
||||
usageCount = parcel.readLong()
|
||||
locationChanged = parcel.readParcelable(PwDate::class.java.classLoader) ?: locationChanged
|
||||
// TODO customData = MemoryUtil.readStringParcelableMap(in);
|
||||
// TODO customData = ParcelableUtil.readStringParcelableMap(in);
|
||||
notes = parcel.readString() ?: notes
|
||||
isExpanded = parcel.readByte().toInt() != 0
|
||||
defaultAutoTypeSequence = parcel.readString() ?: defaultAutoTypeSequence
|
||||
@@ -93,7 +93,7 @@ class PwGroupV4 : PwGroup<UUID, UUID, PwGroupV4, PwEntryV4>, PwNodeV4Interface {
|
||||
dest.writeParcelable(iconCustom, flags)
|
||||
dest.writeLong(usageCount)
|
||||
dest.writeParcelable(locationChanged, flags)
|
||||
// TODO MemoryUtil.writeStringParcelableMap(dest, customData);
|
||||
// TODO ParcelableUtil.writeStringParcelableMap(dest, customData);
|
||||
dest.writeString(notes)
|
||||
dest.writeByte((if (isExpanded) 1 else 0).toByte())
|
||||
dest.writeString(defaultAutoTypeSequence)
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.kunzisoft.keepass.crypto.StreamCipherFactory
|
||||
import com.kunzisoft.keepass.crypto.engine.CipherEngine
|
||||
import com.kunzisoft.keepass.database.element.*
|
||||
import com.kunzisoft.keepass.database.element.PwDatabaseV4.Companion.BASE_64_FLAG
|
||||
import com.kunzisoft.keepass.database.element.PwDatabaseV4.Companion.BUFFER_SIZE_BYTES
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedBinary
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
import com.kunzisoft.keepass.database.exception.*
|
||||
@@ -37,7 +38,6 @@ import com.kunzisoft.keepass.stream.HmacBlockInputStream
|
||||
import com.kunzisoft.keepass.stream.LEDataInputStream
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import com.kunzisoft.keepass.utils.MemoryUtil
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.spongycastle.crypto.StreamCipher
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
@@ -968,7 +968,7 @@ class ImporterV4(private val streamDir: File,
|
||||
return ProtectedBinary()
|
||||
val data = Base64.decode(base64, BASE_64_FLAG)
|
||||
|
||||
return if (!compressed && data.size <= MemoryUtil.BUFFER_SIZE_BYTES) {
|
||||
return if (!compressed && data.size <= BUFFER_SIZE_BYTES) {
|
||||
// Small data, don't need a file
|
||||
ProtectedBinary(protected, data)
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 Brian Pellin.
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
@@ -20,50 +20,70 @@
|
||||
package com.kunzisoft.keepass.database.file.save
|
||||
|
||||
import com.kunzisoft.keepass.database.element.PwDatabaseV4
|
||||
import com.kunzisoft.keepass.database.element.PwDatabaseV4.Companion.BUFFER_SIZE_BYTES
|
||||
import com.kunzisoft.keepass.database.file.PwDbHeaderV4
|
||||
import com.kunzisoft.keepass.stream.ActionReadBytes
|
||||
import com.kunzisoft.keepass.stream.LEDataOutputStream
|
||||
import com.kunzisoft.keepass.utils.MemoryUtil
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import kotlin.experimental.or
|
||||
|
||||
class PwDbInnerHeaderOutputV4(private val db: PwDatabaseV4, private val header: PwDbHeaderV4, os: OutputStream) {
|
||||
class PwDbInnerHeaderOutputV4(private val database: PwDatabaseV4,
|
||||
private val header: PwDbHeaderV4,
|
||||
outputStream: OutputStream) {
|
||||
|
||||
private val los: LEDataOutputStream = LEDataOutputStream(os)
|
||||
private val dataOutputStream: LEDataOutputStream = LEDataOutputStream(outputStream)
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun output() {
|
||||
los.write(PwDbHeaderV4.PwDbInnerHeaderV4Fields.InnerRandomStreamID.toInt())
|
||||
los.writeInt(4)
|
||||
dataOutputStream.write(PwDbHeaderV4.PwDbInnerHeaderV4Fields.InnerRandomStreamID.toInt())
|
||||
dataOutputStream.writeInt(4)
|
||||
if (header.innerRandomStream == null)
|
||||
throw IOException("Can't write innerRandomStream")
|
||||
los.writeInt(header.innerRandomStream!!.id)
|
||||
dataOutputStream.writeInt(header.innerRandomStream!!.id)
|
||||
|
||||
val streamKeySize = header.innerRandomStreamKey.size
|
||||
los.write(PwDbHeaderV4.PwDbInnerHeaderV4Fields.InnerRandomstreamKey.toInt())
|
||||
los.writeInt(streamKeySize)
|
||||
los.write(header.innerRandomStreamKey)
|
||||
dataOutputStream.write(PwDbHeaderV4.PwDbInnerHeaderV4Fields.InnerRandomstreamKey.toInt())
|
||||
dataOutputStream.writeInt(streamKeySize)
|
||||
dataOutputStream.write(header.innerRandomStreamKey)
|
||||
|
||||
db.binPool.doForEachBinary { _, protectedBinary ->
|
||||
database.binPool.doForEachBinary { _, protectedBinary ->
|
||||
var flag = PwDbHeaderV4.KdbxBinaryFlags.None
|
||||
if (protectedBinary.isProtected) {
|
||||
flag = flag or PwDbHeaderV4.KdbxBinaryFlags.Protected
|
||||
}
|
||||
|
||||
los.write(PwDbHeaderV4.PwDbInnerHeaderV4Fields.Binary.toInt())
|
||||
los.writeInt(protectedBinary.length().toInt() + 1) // TODO verify
|
||||
los.write(flag.toInt())
|
||||
dataOutputStream.write(PwDbHeaderV4.PwDbInnerHeaderV4Fields.Binary.toInt())
|
||||
dataOutputStream.writeInt(protectedBinary.length().toInt() + 1) // TODO verify
|
||||
dataOutputStream.write(flag.toInt())
|
||||
|
||||
protectedBinary.getData()?.let {
|
||||
MemoryUtil.readBytes(it, ActionReadBytes { buffer ->
|
||||
los.write(buffer)
|
||||
readBytes(it, ActionReadBytes { buffer ->
|
||||
dataOutputStream.write(buffer)
|
||||
})
|
||||
} ?: throw IOException("Can't write protected binary")
|
||||
}
|
||||
|
||||
los.write(PwDbHeaderV4.PwDbInnerHeaderV4Fields.EndOfHeader.toInt())
|
||||
los.writeInt(0)
|
||||
dataOutputStream.write(PwDbHeaderV4.PwDbInnerHeaderV4Fields.EndOfHeader.toInt())
|
||||
dataOutputStream.writeInt(0)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun readBytes(inputStream: InputStream, actionReadBytes: ActionReadBytes) {
|
||||
val buffer = ByteArray(BUFFER_SIZE_BYTES)
|
||||
var read = 0
|
||||
while (read != -1) {
|
||||
read = inputStream.read(buffer, 0, buffer.size)
|
||||
if (read != -1) {
|
||||
val optimizedBuffer: ByteArray = if (buffer.size == read) {
|
||||
buffer
|
||||
} else {
|
||||
buffer.copyOf(read)
|
||||
}
|
||||
actionReadBytes.doAction(optimizedBuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.kunzisoft.keepass.crypto.keyDerivation.KdfFactory
|
||||
import com.kunzisoft.keepass.database.NodeHandler
|
||||
import com.kunzisoft.keepass.database.element.*
|
||||
import com.kunzisoft.keepass.database.element.PwDatabaseV4.Companion.BASE_64_FLAG
|
||||
import com.kunzisoft.keepass.database.element.PwDatabaseV4.Companion.BUFFER_SIZE_BYTES
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedBinary
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
import com.kunzisoft.keepass.database.exception.DatabaseOutputException
|
||||
@@ -40,13 +41,10 @@ import com.kunzisoft.keepass.stream.HashedBlockOutputStream
|
||||
import com.kunzisoft.keepass.stream.HmacBlockOutputStream
|
||||
import com.kunzisoft.keepass.stream.LEDataOutputStream
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import com.kunzisoft.keepass.utils.MemoryUtil
|
||||
import org.joda.time.DateTime
|
||||
import org.spongycastle.crypto.StreamCipher
|
||||
import org.xmlpull.v1.XmlSerializer
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.*
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
@@ -362,7 +360,7 @@ class PwDbV4Output(private val mDatabaseV4: PwDatabaseV4, outputStream: OutputSt
|
||||
|
||||
|
||||
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
|
||||
private fun writeObject(key: String, value: ProtectedBinary) {
|
||||
private fun writeObject(key: String, binary: ProtectedBinary) {
|
||||
|
||||
xml.startTag(null, PwDatabaseV4XML.ElemBinary)
|
||||
xml.startTag(null, PwDatabaseV4XML.ElemKey)
|
||||
@@ -370,67 +368,19 @@ class PwDbV4Output(private val mDatabaseV4: PwDatabaseV4, outputStream: OutputSt
|
||||
xml.endTag(null, PwDatabaseV4XML.ElemKey)
|
||||
|
||||
xml.startTag(null, PwDatabaseV4XML.ElemValue)
|
||||
val ref = mDatabaseV4.binPool.findKey(value)
|
||||
val ref = mDatabaseV4.binPool.findKey(binary)
|
||||
if (ref != null) {
|
||||
xml.attribute(null, PwDatabaseV4XML.AttrRef, ref.toString())
|
||||
} else {
|
||||
subWriteValue(value)
|
||||
writeBinary(binary)
|
||||
}
|
||||
xml.endTag(null, PwDatabaseV4XML.ElemValue)
|
||||
|
||||
xml.endTag(null, PwDatabaseV4XML.ElemBinary)
|
||||
}
|
||||
|
||||
/*
|
||||
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
|
||||
private fun subWriteValue(value: ProtectedBinary) {
|
||||
try {
|
||||
val inputStream = value.getData()
|
||||
if (inputStream == null) {
|
||||
Log.e(TAG, "Can't write a null input stream.")
|
||||
return
|
||||
}
|
||||
|
||||
if (value.isProtected) {
|
||||
xml.attribute(null, PwDatabaseV4XML.AttrProtected, PwDatabaseV4XML.ValTrue)
|
||||
|
||||
try {
|
||||
val cypherInputStream =
|
||||
IOUtil.pipe(inputStream,
|
||||
o -> new org.spongycastle.crypto.io.CipherOutputStream(o, randomStream))
|
||||
writeInputStreamInBase64(cypherInputStream)
|
||||
} catch (e: Exception) {}
|
||||
|
||||
} else {
|
||||
if (mDatabaseV4.compressionAlgorithm == PwCompressionAlgorithm.GZip) {
|
||||
xml.attribute(null, PwDatabaseV4XML.AttrCompressed, PwDatabaseV4XML.ValTrue)
|
||||
|
||||
try {
|
||||
val gZipInputStream =
|
||||
IOUtil.pipe(inputStream, GZIPOutputStream::new, (int) value.length())
|
||||
writeInputStreamInBase64(gZipInputStream)
|
||||
} catch (e: Exception) {}
|
||||
|
||||
} else {
|
||||
writeInputStreamInBase64(inputStream);
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun writeInputStreamInBase64(inputStream: InputStream) {
|
||||
try {
|
||||
val base64InputStream = pipe(inputStream, Base64OutputStream(o, Base64OutputStream.DEFAULT))
|
||||
MemoryUtil.readBytes(base64InputStream,
|
||||
ActionReadBytes { buffer -> xml.text(Arrays.toString(buffer)) })
|
||||
|
||||
} catch (e: Exception) {}
|
||||
}
|
||||
*/
|
||||
|
||||
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
|
||||
private fun subWriteValue(value: ProtectedBinary) {
|
||||
private fun writeBinary(value: ProtectedBinary) {
|
||||
|
||||
val valLength = value.length().toInt()
|
||||
if (valLength > 0) {
|
||||
@@ -448,8 +398,13 @@ class PwDbV4Output(private val mDatabaseV4: PwDatabaseV4, outputStream: OutputSt
|
||||
if (mDatabaseV4.compressionAlgorithm === PwCompressionAlgorithm.GZip) {
|
||||
xml.attribute(null, PwDatabaseV4XML.AttrCompressed, PwDatabaseV4XML.ValTrue)
|
||||
|
||||
val compressData = MemoryUtil.compress(buffer)
|
||||
xml.text(String(Base64.encode(compressData, BASE_64_FLAG)))
|
||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||
val gzipOutputStream = GZIPOutputStream(byteArrayOutputStream)
|
||||
copyStream(ByteArrayInputStream(buffer), gzipOutputStream)
|
||||
// IOUtils.copy(ByteArrayInputStream(ByteArrayInputStream(buffer)), gzipOutputStream)
|
||||
gzipOutputStream.close()
|
||||
|
||||
xml.text(String(Base64.encode(byteArrayOutputStream.toByteArray(), BASE_64_FLAG)))
|
||||
|
||||
} else {
|
||||
xml.text(String(Base64.encode(buffer, BASE_64_FLAG)))
|
||||
@@ -461,6 +416,23 @@ class PwDbV4Output(private val mDatabaseV4: PwDatabaseV4, outputStream: OutputSt
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun copyStream(inputStream: InputStream, out: OutputStream) {
|
||||
val buffer = ByteArray(BUFFER_SIZE_BYTES)
|
||||
try {
|
||||
var read = inputStream.read(buffer)
|
||||
while (read != -1) {
|
||||
out.write(buffer, 0, read)
|
||||
read = inputStream.read(buffer)
|
||||
if (Thread.interrupted()) {
|
||||
throw InterruptedException()
|
||||
}
|
||||
}
|
||||
} catch (error: OutOfMemoryError) {
|
||||
throw IOException(error)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
|
||||
private fun writeObject(name: String, value: String, filterXmlChars: Boolean = false) {
|
||||
var xmlString = value
|
||||
@@ -703,7 +675,7 @@ class PwDbV4Output(private val mDatabaseV4: PwDatabaseV4, outputStream: OutputSt
|
||||
xml.startTag(null, PwDatabaseV4XML.ElemBinary)
|
||||
xml.attribute(null, PwDatabaseV4XML.AttrId, key.toString())
|
||||
|
||||
subWriteValue(binary)
|
||||
writeBinary(binary)
|
||||
|
||||
xml.endTag(null, PwDatabaseV4XML.ElemBinary)
|
||||
}
|
||||
@@ -733,16 +705,5 @@ class PwDbV4Output(private val mDatabaseV4: PwDatabaseV4, outputStream: OutputSt
|
||||
|
||||
companion object {
|
||||
private val TAG = PwDbV4Output::class.java.name
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun pipe(inputStream: InputStream, outputStream: OutputStream, buf: ByteArray) {
|
||||
while (true) {
|
||||
val amt = inputStream.read(buf)
|
||||
if (amt < 0) {
|
||||
break
|
||||
}
|
||||
outputStream.write(buf, 0, amt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,111 +21,9 @@ package com.kunzisoft.keepass.utils
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.util.Log
|
||||
import java.util.*
|
||||
|
||||
import com.kunzisoft.keepass.stream.ActionReadBytes
|
||||
|
||||
import org.apache.commons.io.IOUtils
|
||||
import java.io.*
|
||||
|
||||
import java.util.HashMap
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
object MemoryUtil {
|
||||
|
||||
private val TAG = MemoryUtil::class.java.name
|
||||
const val BUFFER_SIZE_BYTES = 3 * 128
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun copyStream(inputStream: InputStream, out: OutputStream) {
|
||||
val buffer = ByteArray(BUFFER_SIZE_BYTES)
|
||||
try {
|
||||
var read = inputStream.read(buffer)
|
||||
while (read != -1) {
|
||||
out.write(buffer, 0, read)
|
||||
read = inputStream.read(buffer)
|
||||
if (Thread.interrupted()) {
|
||||
throw InterruptedException()
|
||||
}
|
||||
}
|
||||
} catch (error: OutOfMemoryError) {
|
||||
throw IOException(error)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun readBytes(inputStream: InputStream, actionReadBytes: ActionReadBytes) {
|
||||
val buffer = ByteArray(BUFFER_SIZE_BYTES)
|
||||
var read = 0
|
||||
while (read != -1) {
|
||||
read = inputStream.read(buffer, 0, buffer.size)
|
||||
if (read != -1) {
|
||||
val optimizedBuffer: ByteArray = if (buffer.size == read) {
|
||||
buffer
|
||||
} else {
|
||||
buffer.copyOf(read)
|
||||
}
|
||||
actionReadBytes.doAction(optimizedBuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun decompress(input: ByteArray): ByteArray {
|
||||
val bais = ByteArrayInputStream(input)
|
||||
val gzis = GZIPInputStream(bais)
|
||||
|
||||
val baos = ByteArrayOutputStream()
|
||||
copyStream(gzis, baos)
|
||||
|
||||
return baos.toByteArray()
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun compress(input: ByteArray): ByteArray {
|
||||
val bais = ByteArrayInputStream(input)
|
||||
|
||||
val baos = ByteArrayOutputStream()
|
||||
val gzos = GZIPOutputStream(baos)
|
||||
copyStream(bais, gzos)
|
||||
gzos.close()
|
||||
|
||||
return baos.toByteArray()
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses the input data using GZip and outputs the compressed data.
|
||||
*
|
||||
* @param input
|
||||
* An [InputStream] containing the input raw data.
|
||||
*
|
||||
* @return An [InputStream] to the compressed data.
|
||||
*/
|
||||
fun compress(input: InputStream): InputStream {
|
||||
val compressedDataStream = PipedInputStream(3 * 128)
|
||||
Log.d(TAG, "About to compress input data using gzip asynchronously...")
|
||||
val compressionOutput: PipedOutputStream
|
||||
var gzipCompressedDataStream: GZIPOutputStream? = null
|
||||
try {
|
||||
compressionOutput = PipedOutputStream(compressedDataStream)
|
||||
gzipCompressedDataStream = GZIPOutputStream(compressionOutput)
|
||||
IOUtils.copy(input, gzipCompressedDataStream)
|
||||
Log.e(TAG, "Successfully compressed input data using gzip.")
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "Failed to compress input data.", e)
|
||||
} finally {
|
||||
if (gzipCompressedDataStream != null) {
|
||||
try {
|
||||
gzipCompressedDataStream.close()
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "Failed to close gzip output stream.", e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return compressedDataStream
|
||||
}
|
||||
object ParcelableUtil {
|
||||
|
||||
// For writing to a Parcel
|
||||
fun <K : Parcelable, V : Parcelable> writeParcelableMap(
|
||||
Reference in New Issue
Block a user