mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-29 02:52:56 +02:00
Merge pull request #1467 from davotoula/prevent-resource-leaks-with-streams
Prevent resource leaks with streams
This commit is contained in:
@@ -1842,15 +1842,15 @@ object LocalCache : ILocalCache {
|
|||||||
note.addRelay(relay)
|
note.addRelay(relay)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isVerified =
|
val isVerified =
|
||||||
try {
|
try {
|
||||||
val cachePath = Amethyst.instance.nip95cache
|
val cachePath = Amethyst.instance.nip95cache
|
||||||
cachePath.mkdirs()
|
cachePath.mkdirs()
|
||||||
val file = File(cachePath, event.id)
|
val file = File(cachePath, event.id)
|
||||||
if (!file.exists() && (wasVerified || justVerify(event))) {
|
if (!file.exists() && (wasVerified || justVerify(event))) {
|
||||||
val stream = FileOutputStream(file)
|
FileOutputStream(file).use { stream ->
|
||||||
stream.write(event.decode())
|
stream.write(event.decode())
|
||||||
stream.close()
|
}
|
||||||
Log.i(
|
Log.i(
|
||||||
"FileStorageEvent",
|
"FileStorageEvent",
|
||||||
"NIP95 File received from $relay and saved to disk as $file",
|
"NIP95 File received from $relay and saved to disk as $file",
|
||||||
@@ -2134,7 +2134,7 @@ object LocalCache : ILocalCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findStatusesForUser(user: User): ImmutableList<AddressableNote> {
|
fun findStatusesForUser(user: User): ImmutableList<AddressableNote> {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
return addressables
|
return addressables
|
||||||
@@ -2151,7 +2151,7 @@ object LocalCache : ILocalCache {
|
|||||||
.toImmutableList()
|
.toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun findEarliestOtsForNote(
|
fun findEarliestOtsForNote(
|
||||||
note: Note,
|
note: Note,
|
||||||
resolverBuilder: OtsResolverBuilder,
|
resolverBuilder: OtsResolverBuilder,
|
||||||
): Long? {
|
): Long? {
|
||||||
@@ -2178,7 +2178,7 @@ object LocalCache : ILocalCache {
|
|||||||
|
|
||||||
fun cachedModificationEventsForNote(note: Note): List<Note>? = modificationCache[note.idHex]
|
fun cachedModificationEventsForNote(note: Note): List<Note>? = modificationCache[note.idHex]
|
||||||
|
|
||||||
suspend fun findLatestModificationForNote(note: Note): List<Note> {
|
fun findLatestModificationForNote(note: Note): List<Note> {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
val noteAuthor = note.author ?: return emptyList()
|
val noteAuthor = note.author ?: return emptyList()
|
||||||
@@ -2340,9 +2340,9 @@ object LocalCache : ILocalCache {
|
|||||||
val children =
|
val children =
|
||||||
if (noteEvent is WrappedEvent) {
|
if (noteEvent is WrappedEvent) {
|
||||||
noteEvent.host?.id?.let {
|
noteEvent.host?.id?.let {
|
||||||
getNoteIfExists(it)?.let {
|
getNoteIfExists(it)?.let { it2 ->
|
||||||
removeFromCache(it)
|
removeFromCache(it2)
|
||||||
it.removeAllChildNotes()
|
it2.removeAllChildNotes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -41,7 +41,7 @@ class CrashReportCache(
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun writeReport(report: String) {
|
fun writeReport(report: String) {
|
||||||
val trace = outputStream()
|
val trace = outputStream()
|
||||||
trace.write(report.toByteArray())
|
trace.write(report.toByteArray())
|
||||||
trace.close()
|
trace.close()
|
||||||
@@ -50,8 +50,10 @@ class CrashReportCache(
|
|||||||
suspend fun loadAndDelete(): String? =
|
suspend fun loadAndDelete(): String? =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val stack =
|
val stack =
|
||||||
inputStreamOrNull()?.let { inStream ->
|
inputStreamOrNull()?.use { inStream ->
|
||||||
InputStreamReader(inStream).readText()
|
InputStreamReader(inStream).use { reader ->
|
||||||
|
reader.readText()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
deleteReport()
|
deleteReport()
|
||||||
stack
|
stack
|
||||||
|
@@ -96,19 +96,21 @@ class BlossomUploader {
|
|||||||
|
|
||||||
checkNotNull(imageInputStream) { "Can't open the image input stream" }
|
checkNotNull(imageInputStream) { "Can't open the image input stream" }
|
||||||
|
|
||||||
return upload(
|
return imageInputStream.use { stream ->
|
||||||
imageInputStream,
|
upload(
|
||||||
hash,
|
stream,
|
||||||
payload.size,
|
hash,
|
||||||
fileName,
|
payload.size,
|
||||||
myContentType,
|
fileName,
|
||||||
alt,
|
myContentType,
|
||||||
sensitiveContent,
|
alt,
|
||||||
serverBaseUrl,
|
sensitiveContent,
|
||||||
okHttpClient,
|
serverBaseUrl,
|
||||||
httpAuth,
|
okHttpClient,
|
||||||
context,
|
httpAuth,
|
||||||
)
|
context,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encodeAuth(event: BlossomAuthorizationEvent): String {
|
fun encodeAuth(event: BlossomAuthorizationEvent): String {
|
||||||
|
@@ -109,18 +109,20 @@ class Nip96Uploader {
|
|||||||
|
|
||||||
checkNotNull(imageInputStream) { "Can't open the image input stream" }
|
checkNotNull(imageInputStream) { "Can't open the image input stream" }
|
||||||
|
|
||||||
return upload(
|
return imageInputStream.use { stream ->
|
||||||
imageInputStream,
|
upload(
|
||||||
length,
|
stream,
|
||||||
myContentType,
|
length,
|
||||||
alt,
|
myContentType,
|
||||||
sensitiveContent,
|
alt,
|
||||||
server,
|
sensitiveContent,
|
||||||
okHttpClient,
|
server,
|
||||||
onProgress,
|
okHttpClient,
|
||||||
httpAuth,
|
onProgress,
|
||||||
context,
|
httpAuth,
|
||||||
)
|
context,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun upload(
|
suspend fun upload(
|
||||||
|
@@ -50,8 +50,8 @@ class Request(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
val httpURLConnection = url.openConnection() as HttpURLConnection
|
val httpURLConnection = url.openConnection() as HttpURLConnection
|
||||||
httpURLConnection.setReadTimeout(10000)
|
httpURLConnection.readTimeout = 10000
|
||||||
httpURLConnection.setConnectTimeout(10000)
|
httpURLConnection.connectTimeout = 10000
|
||||||
httpURLConnection.setRequestProperty("User-Agent", "OpenTimestamps Java")
|
httpURLConnection.setRequestProperty("User-Agent", "OpenTimestamps Java")
|
||||||
httpURLConnection.setRequestProperty("Accept", "application/json")
|
httpURLConnection.setRequestProperty("Accept", "application/json")
|
||||||
httpURLConnection.setRequestProperty("Accept-Encoding", "gzip")
|
httpURLConnection.setRequestProperty("Accept-Encoding", "gzip")
|
||||||
@@ -62,17 +62,17 @@ class Request(
|
|||||||
|
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
httpURLConnection.setDoOutput(true)
|
httpURLConnection.setDoOutput(true)
|
||||||
httpURLConnection.setRequestMethod("POST")
|
httpURLConnection.requestMethod = "POST"
|
||||||
httpURLConnection.setRequestProperty(
|
httpURLConnection.setRequestProperty(
|
||||||
"Content-Length",
|
"Content-Length",
|
||||||
"" + this.data!!.size.toString(),
|
"" + this.data!!.size.toString(),
|
||||||
)
|
)
|
||||||
val wr = DataOutputStream(httpURLConnection.getOutputStream())
|
DataOutputStream(httpURLConnection.getOutputStream()).use { wr ->
|
||||||
wr.write(this.data, 0, this.data!!.size)
|
wr.write(this.data, 0, this.data!!.size)
|
||||||
wr.flush()
|
wr.flush()
|
||||||
wr.close()
|
}
|
||||||
} else {
|
} else {
|
||||||
httpURLConnection.setRequestMethod("GET")
|
httpURLConnection.requestMethod = "GET"
|
||||||
}
|
}
|
||||||
|
|
||||||
httpURLConnection.connect()
|
httpURLConnection.connect()
|
||||||
@@ -84,7 +84,7 @@ class Request(
|
|||||||
response.status = responseCode
|
response.status = responseCode
|
||||||
response.fromUrl = url.toString()
|
response.fromUrl = url.toString()
|
||||||
var `is` = httpURLConnection.getInputStream()
|
var `is` = httpURLConnection.getInputStream()
|
||||||
if ("gzip" == httpURLConnection.getContentEncoding()) {
|
if ("gzip" == httpURLConnection.contentEncoding) {
|
||||||
`is` = GZIPInputStream(`is`)
|
`is` = GZIPInputStream(`is`)
|
||||||
}
|
}
|
||||||
response.setStream(`is`)
|
response.setStream(`is`)
|
||||||
|
@@ -23,6 +23,7 @@ package com.vitorpamplona.quartz.nip03Timestamp.ots.http
|
|||||||
import com.fasterxml.jackson.databind.JsonNode
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.io.Closeable
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
@@ -30,7 +31,7 @@ import java.nio.charset.StandardCharsets
|
|||||||
/**
|
/**
|
||||||
* Holds the response from an HTTP request.
|
* Holds the response from an HTTP request.
|
||||||
*/
|
*/
|
||||||
class Response {
|
class Response : Closeable {
|
||||||
private var stream: InputStream? = null
|
private var stream: InputStream? = null
|
||||||
|
|
||||||
var fromUrl: String? = null
|
var fromUrl: String? = null
|
||||||
@@ -53,7 +54,7 @@ class Response {
|
|||||||
|
|
||||||
@get:Throws(IOException::class)
|
@get:Throws(IOException::class)
|
||||||
val string: String
|
val string: String
|
||||||
get() = kotlin.text.String(this.bytes, StandardCharsets.UTF_8)
|
get() = String(this.bytes, StandardCharsets.UTF_8)
|
||||||
|
|
||||||
@get:Throws(IOException::class)
|
@get:Throws(IOException::class)
|
||||||
val bytes: ByteArray
|
val bytes: ByteArray
|
||||||
@@ -79,4 +80,9 @@ class Response {
|
|||||||
JsonMapper.builder().build()
|
JsonMapper.builder().build()
|
||||||
return builder.readTree(jsonString)
|
return builder.readTree(jsonString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
stream?.close()
|
||||||
|
stream = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -62,7 +62,7 @@ abstract class OpCrypto internal constructor() : OpUnary() {
|
|||||||
val digest = MessageDigest.getInstance(this.hashLibName())
|
val digest = MessageDigest.getInstance(this.hashLibName())
|
||||||
var chunk = ctx.read(1048576)
|
var chunk = ctx.read(1048576)
|
||||||
|
|
||||||
while (chunk != null && chunk.size > 0) {
|
while (chunk.isNotEmpty()) {
|
||||||
digest.update(chunk)
|
digest.update(chunk)
|
||||||
chunk = ctx.read(1048576)
|
chunk = ctx.read(1048576)
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ abstract class OpCrypto internal constructor() : OpUnary() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, NoSuchAlgorithmException::class)
|
@Throws(IOException::class, NoSuchAlgorithmException::class)
|
||||||
fun hashFd(file: File?): ByteArray = hashFd(FileInputStream(file))
|
fun hashFd(file: File?): ByteArray = FileInputStream(file).use { inputStream -> hashFd(inputStream) }
|
||||||
|
|
||||||
@Throws(IOException::class, NoSuchAlgorithmException::class)
|
@Throws(IOException::class, NoSuchAlgorithmException::class)
|
||||||
fun hashFd(bytes: ByteArray): ByteArray {
|
fun hashFd(bytes: ByteArray): ByteArray {
|
||||||
@@ -93,6 +93,7 @@ abstract class OpCrypto internal constructor() : OpUnary() {
|
|||||||
count = inputStream.read(chunk, 0, 1048576)
|
count = inputStream.read(chunk, 0, 1048576)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Is this needed? Closing of stream should be callers responsibility?
|
||||||
inputStream.close()
|
inputStream.close()
|
||||||
val hash = digest.digest()
|
val hash = digest.digest()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user