override fun shouldCancel(uri: FreenetURI, mimeType: String, size: Long): Boolean {
if (size > 2097152) {
logger.fine { "Canceling download of $uri because it’s > 2 MiB." }
- rejectedElements[uri.toString()] = Rejected(RejectionReason.SizeTooLarge, size)
+ rejectedElements[uri.toString().decode()] = Rejected(RejectionReason.SizeTooLarge, size)
return true
}
if (!mimeType.startsWith("image/") && !mimeType.startsWith("text/html")) {
logger.fine { "Canceling download of $uri because of its MIME type, $mimeType." }
- rejectedElements[uri.toString()] = Rejected(RejectionReason.InvalidMediaType, mimeType)
+ rejectedElements[uri.toString().decode()] = Rejected(RejectionReason.InvalidMediaType, mimeType)
return true
}
return false
ByteArrayInputStream(data).use {
ImageIO.read(it)
}?.let {
- elementCache.get(uri.toString()) {
- LinkedElement(uri.toString(), properties = mapOf("type" to "image", "size" to data.size, "sizeHuman" to data.size.human))
+ elementCache.get(uri.toString().decode()) {
+ LinkedElement(uri.toString().decode(), properties = mapOf("type" to "image", "size" to data.size, "sizeHuman" to data.size.human))
.apply {
logger.fine("Downloaded image from $link: size=${properties["size"]}.")
}
}
mimeType.baseType == "text/html" -> {
val document = Jsoup.parse(data.toString(Charset.forName(mimeType.getParameter("charset") ?: "UTF-8")))
- elementCache.get(uri.toString()) {
- LinkedElement(uri.toString(), properties = mapOf(
+ elementCache.get(uri.toString().decode()) {
+ LinkedElement(uri.toString().decode(), properties = mapOf(
"type" to "html", "size" to data.size, "sizeHuman" to data.size.human,
"title" to document.title().emptyToNull,
"description" to (document.metaDescription ?: document.firstNonHeadingParagraph)
}
override fun failed(uri: FreenetURI) {
- failureCache.put(uri.toString(), true)
+ failureCache.put(uri.toString().decode(), true)
removeLoadingLink(uri)
logger.fine { "Download failed for $uri." }
}
private fun removeLoadingLink(uri: FreenetURI) {
synchronized(loadingLinks) {
- loadingLinks.invalidate(uri.toString())
+ loadingLinks.invalidate(uri.toString().decode())
}
}
}
import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.hasEntry
import org.hamcrest.Matchers.hasItem
+import org.hamcrest.Matchers.hasKey
import org.hamcrest.Matchers.hasSize
import org.hamcrest.Matchers.not
import org.hamcrest.TypeSafeDiagnosingMatcher
@Test
fun `element loader no longer exposes an element as loading once it has been loaded`() {
runWithCallback("KSK@test") { elementLoader, _, callback, _ ->
- elementLoader.loadElement("KSK@test")
callback.loaded(FreenetURI("KSK@test"), "image/png", read("/static/images/unknown-image-0.png"))
assertThat(elementLoader.loadingElements, not(hasItem("KSK@test")))
}
}
@Test
+ fun `element loader no longer exposes an element as loading once it was loaded as text`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, _ ->
+ callback.loaded(FreenetURI("KSK@test%20file"), "text/html", ByteArray(0))
+ assertThat(elementLoader.loadingElements, not(hasItem("KSK@test file")))
+ }
+ }
+
+ @Test
+ fun `element loader no longer exposes an element as loading once it was loaded as image`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, _ ->
+ callback.loaded(FreenetURI("KSK@test%20file"), "image/png", read("/static/images/unknown-image-0.png"))
+ assertThat(elementLoader.loadingElements, not(hasItem("KSK@test file")))
+ }
+ }
+
+ @Test
fun `element loader exposes rejected element when media type does not match`() {
runWithCallback("KSK@test") { elementLoader, _, callback, _ ->
callback.shouldCancel(FreenetURI("KSK@test"), "application/x-test-data", 1234)
}
@Test
+ fun `element loader no longer exposes an element as loading once it has failed`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, _ ->
+ callback.failed(FreenetURI("KSK@test%20file"))
+ assertThat(elementLoader.loadingElements, not(hasItem("KSK@test file")))
+ }
+ }
+
+ @Test
fun `element loader decodes and normalizes link`() {
runWithCallback(decomposedKey) { _, _, _, fetchedUris ->
assertThat(fetchedUris(), contains(FreenetURI(normalizedKey)))
}
}
+ @Test
+ fun `url of element rejected because of size is decoded`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, fetchedUris ->
+ callback.shouldCancel(FreenetURI("KSK@test%20file"), "text/html", Long.MAX_VALUE)
+ assertThat(elementLoader.rejectedElements, hasKey("KSK@test file"))
+ }
+ }
+
+ @Test
+ fun `url of element rejected because of MIME type is decoded`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, fetchedUris ->
+ callback.shouldCancel(FreenetURI("KSK@test%20file"), "test/data", 1L)
+ assertThat(elementLoader.rejectedElements, hasKey("KSK@test file"))
+ }
+ }
+
+ @Test
+ fun `url of element that failed to load is decoded`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, fetchedUris ->
+ callback.failed(FreenetURI("KSK@test%20file"))
+ assertThat(elementLoader.failedElements, containsInAnyOrder("KSK@test file"))
+ }
+ }
+
+ @Test
+ fun `url of loading element is decoded`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, fetchedUris ->
+ assertThat(elementLoader.loadingElements, containsInAnyOrder("KSK@test file"))
+ }
+ }
+
+ @Test
+ fun `url of loaded text element is decoded`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, fetchedUris ->
+ callback.loaded(FreenetURI("KSK@test%20file"), "text/html", ByteArray(0))
+ assertThat(elementLoader.loadedElements, containsInAnyOrder(isLinkedElement(equalTo("KSK@test file"))))
+ }
+ }
+
+ @Test
+ fun `url of loaded image element is decoded`() {
+ runWithCallback("KSK@test%20file") { elementLoader, _, callback, fetchedUris ->
+ callback.loaded(FreenetURI("KSK@test%20file"), "image/test", read("/static/images/unknown-image-0.png"))
+ assertThat(elementLoader.loadedElements, containsInAnyOrder(isLinkedElement(equalTo("KSK@test file"))))
+ }
+ }
+
private fun read(resource: String): ByteArray =
javaClass.getResourceAsStream(resource)?.use { input ->
ByteArrayOutputStream().use {
@Suppress("unused")
// keep this instance around so its configuration isn’t lost
private val logger = Logger.getLogger(DefaultElementLoader::class.qualifiedName)
- .apply { level = ALL }
- .apply {
- addHandler(object : Handler() {
- override fun publish(record: LogRecord) {
- loggedRecords += record
- }
-
- override fun flush() = Unit
- override fun close() = Unit
- })
- }
+ .apply { level = ALL }
+ .apply {
+ addHandler(object : Handler() {
+ override fun publish(record: LogRecord) {
+ loggedRecords += record
+ }
+
+ override fun flush() = Unit
+ override fun close() = Unit
+ })
+ }
}