Export retained notification images in HTML
This commit is contained in:
@@ -2,6 +2,8 @@ package se.ajpanton.notificationlog.data
|
||||
|
||||
import android.content.Context
|
||||
import java.io.File
|
||||
import java.io.DataInputStream
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
/** Stores copied notification image bytes independently of the source app's URI lifetime. */
|
||||
class EncryptedImageStore(context: Context) {
|
||||
@@ -9,6 +11,7 @@ class EncryptedImageStore(context: Context) {
|
||||
private val cipher = AesGcmCipher(LogEncryptionKeyProvider().getOrCreate())
|
||||
|
||||
fun save(id: String, bytes: ByteArray) {
|
||||
require(id.matches(IMAGE_ID_PATTERN)) { "Invalid notification image ID." }
|
||||
val payload = cipher.encrypt(bytes)
|
||||
File(directory, "$id.bin").outputStream().use { output ->
|
||||
output.write(payload.initializationVector.size)
|
||||
@@ -16,4 +19,26 @@ class EncryptedImageStore(context: Context) {
|
||||
output.write(payload.cipherText)
|
||||
}
|
||||
}
|
||||
|
||||
fun read(id: String): ByteArray? {
|
||||
require(id.matches(IMAGE_ID_PATTERN)) { "Invalid notification image ID." }
|
||||
val file = File(directory, "$id.bin")
|
||||
if (!file.exists()) return null
|
||||
try {
|
||||
DataInputStream(file.inputStream()).use { input ->
|
||||
val ivLength = input.readUnsignedByte()
|
||||
require(ivLength in 12..32) { "Invalid notification image IV length." }
|
||||
val initializationVector = ByteArray(ivLength).also(input::readFully)
|
||||
val cipherText = input.readBytes()
|
||||
require(cipherText.isNotEmpty()) { "Empty encrypted notification image." }
|
||||
return cipher.decrypt(EncryptedPayload(initializationVector, cipherText))
|
||||
}
|
||||
} catch (error: FileNotFoundException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val IMAGE_ID_PATTERN = Regex("[0-9a-f-]{36}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ object NotificationLogEntryJson {
|
||||
.put("packageName", entry.packageName)
|
||||
.put("appName", entry.appName)
|
||||
.put("action", entry.action.name)
|
||||
.put("contents", entry.contents),
|
||||
.put("contents", entry.contents)
|
||||
.put("imageId", entry.imageId),
|
||||
)
|
||||
}
|
||||
}.toString().encodeToByteArray()
|
||||
@@ -32,6 +33,7 @@ object NotificationLogEntryJson {
|
||||
appName = entry.getString("appName"),
|
||||
action = NotificationAction.valueOf(entry.getString("action")),
|
||||
contents = if (entry.isNull("contents")) null else entry.getString("contents"),
|
||||
imageId = entry.optString("imageId").takeIf { it.isNotEmpty() },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user