79 lines
3 KiB
Kotlin
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()
|