1
0
Fork 0
seedvault/app/src/main/java/com/stevesoltys/seedvault/header/HeaderReader.kt
Torsten Grote 6c531066e7 Enable automatic coding style linting with ktlint (also on CI)
This way the coding style is guaranteed to stay consistent.
2020-10-07 19:44:05 +05:30

79 lines
3 KiB
Kotlin

package com.stevesoltys.seedvault.header
import com.stevesoltys.seedvault.Utf8
import java.io.EOFException
import java.io.IOException
import java.io.InputStream
import java.nio.ByteBuffer
interface HeaderReader {
@Throws(IOException::class, UnsupportedVersionException::class)
fun readVersion(inputStream: InputStream): Byte
@Throws(SecurityException::class)
fun getVersionHeader(byteArray: ByteArray): VersionHeader
@Throws(EOFException::class, IOException::class)
fun readSegmentHeader(inputStream: InputStream): SegmentHeader
}
internal class HeaderReaderImpl : HeaderReader {
@Throws(IOException::class, UnsupportedVersionException::class)
override fun readVersion(inputStream: InputStream): Byte {
val version = inputStream.read().toByte()
if (version < 0) throw IOException()
if (version > VERSION) throw UnsupportedVersionException(version)
return version
}
override fun getVersionHeader(byteArray: ByteArray): VersionHeader {
val buffer = ByteBuffer.wrap(byteArray)
val version = buffer.get()
val packageLength = buffer.short.toInt()
if (packageLength <= 0) throw SecurityException("Invalid package length: $packageLength")
if (packageLength > MAX_PACKAGE_LENGTH_SIZE) throw SecurityException(
"Too large package length: $packageLength"
)
if (packageLength > buffer.remaining()) throw SecurityException(
"Not enough bytes for package name"
)
val packageName = ByteArray(packageLength)
.apply { buffer.get(this) }
.toString(Utf8)
val keyLength = buffer.short.toInt()
if (keyLength < 0) throw SecurityException("Invalid key length: $keyLength")
if (keyLength > MAX_KEY_LENGTH_SIZE) throw SecurityException(
"Too large key length: $keyLength"
)
if (keyLength > buffer.remaining()) throw SecurityException("Not enough bytes for key")
val key = if (keyLength == 0) null else ByteArray(keyLength)
.apply { buffer.get(this) }
.toString(Utf8)
if (buffer.remaining() != 0) throw SecurityException("Found extra bytes in header")
return VersionHeader(version, packageName, key)
}
@Throws(EOFException::class, IOException::class)
override fun readSegmentHeader(inputStream: InputStream): SegmentHeader {
val buffer = ByteArray(SEGMENT_HEADER_SIZE)
val bytesRead = inputStream.read(buffer)
if (bytesRead == -1) throw EOFException()
if (bytesRead != SEGMENT_HEADER_SIZE) {
throw IOException("Read $bytesRead bytes, but expected $SEGMENT_HEADER_SIZE")
}
val segmentLength = ByteBuffer.wrap(buffer, 0, SEGMENT_LENGTH_SIZE).short
if (segmentLength <= 0) throw IOException()
val nonce = buffer.copyOfRange(SEGMENT_LENGTH_SIZE, buffer.size)
return SegmentHeader(segmentLength, nonce)
}
}
class UnsupportedVersionException(val version: Byte) : IOException()