X-Git-Url: https://git.pterodactylus.net/?p=Sone.git;a=blobdiff_plain;f=src%2Fmain%2Fkotlin%2Fnet%2Fpterodactylus%2Fsone%2Ftext%2FSoneTextParser.kt;h=24b04faa3028db2e0f217fb6dc4fa22deda0671f;hp=68a38ef5b650ddf97ac69f74abf918b07d226027;hb=HEAD;hpb=a45d1b5d50019622c4c6fce6ffa46b4e640b8e7f diff --git a/src/main/kotlin/net/pterodactylus/sone/text/SoneTextParser.kt b/src/main/kotlin/net/pterodactylus/sone/text/SoneTextParser.kt index 68a38ef..24b04fa 100644 --- a/src/main/kotlin/net/pterodactylus/sone/text/SoneTextParser.kt +++ b/src/main/kotlin/net/pterodactylus/sone/text/SoneTextParser.kt @@ -1,28 +1,20 @@ package net.pterodactylus.sone.text -import freenet.keys.FreenetURI -import freenet.support.Base64 -import net.pterodactylus.sone.data.Sone -import net.pterodactylus.sone.data.impl.IdOnlySone -import net.pterodactylus.sone.database.PostProvider -import net.pterodactylus.sone.database.SoneProvider -import net.pterodactylus.sone.text.LinkType.CHK -import net.pterodactylus.sone.text.LinkType.FREEMAIL -import net.pterodactylus.sone.text.LinkType.HTTP -import net.pterodactylus.sone.text.LinkType.HTTPS -import net.pterodactylus.sone.text.LinkType.KSK -import net.pterodactylus.sone.text.LinkType.POST -import net.pterodactylus.sone.text.LinkType.SONE -import net.pterodactylus.sone.text.LinkType.SSK +import freenet.keys.* +import net.pterodactylus.sone.data.* +import net.pterodactylus.sone.data.impl.* +import net.pterodactylus.sone.database.* +import net.pterodactylus.sone.text.LinkType.* import net.pterodactylus.sone.text.LinkType.USK -import net.pterodactylus.sone.utils.let -import org.bitpedia.util.Base32 -import java.net.MalformedURLException +import net.pterodactylus.sone.utils.* +import org.bitpedia.util.* +import java.net.* +import javax.inject.* /** * [Parser] implementation that can recognize Freenet URIs. */ -class SoneTextParser(private val soneProvider: SoneProvider?, private val postProvider: PostProvider?) { +class SoneTextParser @Inject constructor(private val soneProvider: SoneProvider?, private val postProvider: PostProvider?) { fun parse(source: String, context: SoneTextParserContext?) = source.split("\n") @@ -50,29 +42,41 @@ class SoneTextParser(private val soneProvider: SoneProvider?, private val postPr } }.map { it.first }.toList() + private val NextLink.linkWithoutBacklink: String + get() { + val backlink = link.indexOf("/../") + val query = link.indexOf("?") + return if ((backlink > -1) && ((query == -1) || (query > -1) && (backlink < query))) + link.substring(0, backlink) + else + link + } + private fun NextLink.toPart(context: SoneTextParserContext?) = when (linkType) { KSK, CHK -> try { - FreenetURI(link).let { freenetUri -> + FreenetURI(linkWithoutBacklink).let { freenetUri -> FreenetLinkPart( - link, - if (freenetUri.isKSK) { - freenetUri.guessableKey - } else { - freenetUri.metaString ?: freenetUri.docName ?: link.substring(0, 9) - }, - link.split('?').first() + linkWithoutBacklink, + freenetUri.allMetaStrings?.lastOrNull { it != "" } ?: freenetUri.docName ?: linkWithoutBacklink.substring(0, 9), + linkWithoutBacklink.split('?').first() ) } } catch (e: MalformedURLException) { - PlainTextPart(link) + PlainTextPart(linkWithoutBacklink) } SSK, USK -> try { - FreenetLinkPart(link, FreenetURI(link).docName, trusted = context?.routingKey?.contentEquals(FreenetURI(link).routingKey) == true) + FreenetURI(linkWithoutBacklink).let { uri -> + uri.allMetaStrings + ?.takeIf { (it.size > 1) || ((it.size == 1) && (it.single() != "")) } + ?.lastOrNull() + ?: uri.docName + ?: "${uri.keyType}@${uri.routingKey.asFreenetBase64}" + }.let { FreenetLinkPart(linkWithoutBacklink.removeSuffix("/"), it, trusted = context?.routingKey?.contentEquals(FreenetURI(linkWithoutBacklink).routingKey) == true) } } catch (e: MalformedURLException) { - PlainTextPart(link) + PlainTextPart(linkWithoutBacklink) } - SONE -> link.substring(7).let { SonePart(soneProvider?.getSone(it)?.orNull() ?: IdOnlySone(it)) } + SONE -> link.substring(7).let { SonePart(soneProvider?.getSone(it) ?: IdOnlySone(it)) } POST -> postProvider?.getPost(link.substring(7))?.let { PostPart(it) } ?: PlainTextPart(link) FREEMAIL -> link.indexOf('@').let { atSign -> link.substring(atSign + 1, link.length - 9).let { freemailId -> @@ -111,7 +115,7 @@ private fun List.mergeAdjacentPlainTextParts() = fold(emptyList()) { private fun List.removeEmptyPlainTextParts() = filterNot { it == PlainTextPart("") } -private val String.decodedId: String get() = Base64.encode(Base32.decode(this)) +private val String.decodedId: String get() = Base32.decode(this).asFreenetBase64 private val String.withoutProtocol get() = substring(indexOf("//") + 2) private val String.withoutUrlParameters get() = split('?').first() @@ -134,7 +138,7 @@ private val String.withoutMiddlePathComponents } private val String.withoutTrailingSlash get() = if (endsWith("/")) substring(0, length - 1) else this private val SoneTextParserContext.routingKey: ByteArray? get() = postingSone?.routingKey -private val Sone.routingKey: ByteArray get() = Base64.decode(id) +private val Sone.routingKey: ByteArray get() = id.fromFreenetBase64 private enum class LinkType(private val scheme: String, private val freenetLink: Boolean) {