Enable explicit API mode

This already caught some cases of public members that should have been
private and one case where the inferred type was too specific.

Signed-off-by: Graham <gpe@openrs2.dev>
bzip2
Graham 4 years ago
parent ed2a3f6dc6
commit 232ba32bbd
  1. 4
      all/src/main/java/dev/openrs2/Command.kt
  2. 2
      asm/src/main/java/dev/openrs2/asm/AsmJacksonModule.kt
  3. 2
      asm/src/main/java/dev/openrs2/asm/AsmModule.kt
  4. 6
      asm/src/main/java/dev/openrs2/asm/ClassForNameUtils.kt
  5. 4
      asm/src/main/java/dev/openrs2/asm/ClassNameExtensions.kt
  6. 20
      asm/src/main/java/dev/openrs2/asm/ClassNodeRemapper.kt
  7. 6
      asm/src/main/java/dev/openrs2/asm/ClassVersionUtils.kt
  8. 6
      asm/src/main/java/dev/openrs2/asm/InsnListUtils.kt
  9. 10
      asm/src/main/java/dev/openrs2/asm/InsnMatcher.kt
  10. 20
      asm/src/main/java/dev/openrs2/asm/InsnNodeUtils.kt
  11. 12
      asm/src/main/java/dev/openrs2/asm/MemberDesc.kt
  12. 16
      asm/src/main/java/dev/openrs2/asm/MemberRef.kt
  13. 2
      asm/src/main/java/dev/openrs2/asm/MemberRefDeserializer.kt
  14. 2
      asm/src/main/java/dev/openrs2/asm/MemberRefKeyDeserializer.kt
  15. 8
      asm/src/main/java/dev/openrs2/asm/MethodNodeUtils.kt
  16. 2
      asm/src/main/java/dev/openrs2/asm/NopClassVisitor.kt
  17. 4
      asm/src/main/java/dev/openrs2/asm/StackMetadata.kt
  18. 12
      asm/src/main/java/dev/openrs2/asm/classpath/AsmClassMetadata.kt
  19. 30
      asm/src/main/java/dev/openrs2/asm/classpath/ClassMetadata.kt
  20. 18
      asm/src/main/java/dev/openrs2/asm/classpath/ClassPath.kt
  21. 10
      asm/src/main/java/dev/openrs2/asm/classpath/ExtendedRemapper.kt
  22. 2
      asm/src/main/java/dev/openrs2/asm/classpath/JsrInliner.kt
  23. 20
      asm/src/main/java/dev/openrs2/asm/classpath/Library.kt
  24. 4
      asm/src/main/java/dev/openrs2/asm/classpath/LibraryRemapper.kt
  25. 8
      asm/src/main/java/dev/openrs2/asm/classpath/ReflectionClassMetadata.kt
  26. 2
      asm/src/main/java/dev/openrs2/asm/classpath/StackFrameClassWriter.kt
  27. 2
      asm/src/main/java/dev/openrs2/asm/filter/AnyClassFilter.kt
  28. 2
      asm/src/main/java/dev/openrs2/asm/filter/AnyMemberFilter.kt
  29. 4
      asm/src/main/java/dev/openrs2/asm/filter/ClassFilter.kt
  30. 6
      asm/src/main/java/dev/openrs2/asm/filter/Glob.kt
  31. 2
      asm/src/main/java/dev/openrs2/asm/filter/GlobClassFilter.kt
  32. 2
      asm/src/main/java/dev/openrs2/asm/filter/GlobMemberFilter.kt
  33. 6
      asm/src/main/java/dev/openrs2/asm/filter/MemberFilter.kt
  34. 2
      asm/src/main/java/dev/openrs2/asm/filter/UnionClassFilter.kt
  35. 2
      asm/src/main/java/dev/openrs2/asm/filter/UnionMemberFilter.kt
  36. 2
      asm/src/main/java/dev/openrs2/asm/io/AbstractJarLibraryWriter.kt
  37. 2
      asm/src/main/java/dev/openrs2/asm/io/JarLibraryReader.kt
  38. 2
      asm/src/main/java/dev/openrs2/asm/io/JarLibraryWriter.kt
  39. 4
      asm/src/main/java/dev/openrs2/asm/io/LibraryReader.kt
  40. 4
      asm/src/main/java/dev/openrs2/asm/io/LibraryWriter.kt
  41. 2
      asm/src/main/java/dev/openrs2/asm/io/ManifestJarLibraryWriter.kt
  42. 2
      asm/src/main/java/dev/openrs2/asm/io/Pack200LibraryReader.kt
  43. 2
      asm/src/main/java/dev/openrs2/asm/io/Pack200LibraryWriter.kt
  44. 2
      asm/src/main/java/dev/openrs2/asm/io/PackClassLibraryReader.kt
  45. 2
      asm/src/main/java/dev/openrs2/asm/io/PackClassLibraryWriter.kt
  46. 2
      asm/src/main/java/dev/openrs2/asm/io/SignedJarLibraryWriter.kt
  47. 4
      asm/src/main/java/dev/openrs2/asm/transform/Transformer.kt
  48. 2
      buffer/src/main/java/dev/openrs2/buffer/ReferenceCountedExtensions.kt
  49. 6
      build.gradle.kts
  50. 4
      bundler/src/main/java/dev/openrs2/bundler/BundleCommand.kt
  51. 4
      bundler/src/main/java/dev/openrs2/bundler/Bundler.kt
  52. 2
      bundler/src/main/java/dev/openrs2/bundler/BundlerModule.kt
  53. 2
      bundler/src/main/java/dev/openrs2/bundler/BundlerQualifier.kt
  54. 28
      bundler/src/main/java/dev/openrs2/bundler/Resource.kt
  55. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/BufferSizeTransformer.kt
  56. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/CachePathTransformer.kt
  57. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/DomainTransformer.kt
  58. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/HostCheckTransformer.kt
  59. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/LoadLibraryTransformer.kt
  60. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/MacResizeTransformer.kt
  61. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/MemoryAllocationTransformer.kt
  62. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/NameTransformer.kt
  63. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/PlatformDetectionTransformer.kt
  64. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/PublicKeyTransformer.kt
  65. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/ResourceTransformer.kt
  66. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/RightClickTransformer.kt
  67. 2
      bundler/src/main/java/dev/openrs2/bundler/transform/TypoTransformer.kt
  68. 8
      cache/src/main/java/dev/openrs2/cache/BufferedFileChannel.kt
  69. 8
      cache/src/main/java/dev/openrs2/cache/DiskStore.kt
  70. 8
      cache/src/main/java/dev/openrs2/cache/FlatFileStore.kt
  71. 8
      cache/src/main/java/dev/openrs2/cache/Js5Compression.kt
  72. 10
      cache/src/main/java/dev/openrs2/cache/Js5CompressionType.kt
  73. 26
      cache/src/main/java/dev/openrs2/cache/Store.kt
  74. 2
      cache/src/main/java/dev/openrs2/cache/StoreCorruptException.kt
  75. 2
      cache/src/main/java/dev/openrs2/cache/StoreFullException.kt
  76. 4
      compress-cli/src/main/java/dev/openrs2/compress/cli/CompressCommand.kt
  77. 2
      compress-cli/src/main/java/dev/openrs2/compress/cli/bzip2/Bunzip2Command.kt
  78. 2
      compress-cli/src/main/java/dev/openrs2/compress/cli/bzip2/Bzip2Command.kt
  79. 2
      compress-cli/src/main/java/dev/openrs2/compress/cli/deflate/DeflateCommand.kt
  80. 2
      compress-cli/src/main/java/dev/openrs2/compress/cli/deflate/InflateCommand.kt
  81. 2
      compress-cli/src/main/java/dev/openrs2/compress/cli/gzip/GunzipCommand.kt
  82. 2
      compress-cli/src/main/java/dev/openrs2/compress/cli/gzip/GzipCommand.kt
  83. 2
      compress-cli/src/main/java/dev/openrs2/compress/cli/lzma/LzmaCommand.kt
  84. 2
      compress-cli/src/main/java/dev/openrs2/compress/cli/lzma/UnlzmaCommand.kt
  85. 6
      compress/src/main/java/dev/openrs2/compress/bzip2/Bzip2.kt
  86. 9
      compress/src/main/java/dev/openrs2/compress/gzip/Gzip.kt
  87. 2
      compress/src/main/java/dev/openrs2/compress/gzip/GzipLevelOutputStream.kt
  88. 12
      compress/src/main/java/dev/openrs2/compress/lzma/Lzma.kt
  89. 2
      conf/src/main/java/dev/openrs2/conf/Config.kt
  90. 2
      conf/src/main/java/dev/openrs2/conf/ConfigModule.kt
  91. 2
      conf/src/main/java/dev/openrs2/conf/ConfigProvider.kt
  92. 4
      crc32/src/main/java/dev/openrs2/crc32/Crc32Command.kt
  93. 2
      crypto/src/main/java/dev/openrs2/crypto/CryptoModule.kt
  94. 8
      crypto/src/main/java/dev/openrs2/crypto/IsaacRandom.kt
  95. 8
      crypto/src/main/java/dev/openrs2/crypto/Pkcs12KeyStore.kt
  96. 28
      crypto/src/main/java/dev/openrs2/crypto/Rsa.kt
  97. 2
      crypto/src/main/java/dev/openrs2/crypto/RsaKeyProvider.kt
  98. 2
      crypto/src/main/java/dev/openrs2/crypto/ThreadLocalSecureRandom.kt
  99. 12
      crypto/src/main/java/dev/openrs2/crypto/Whirlpool.kt
  100. 20
      crypto/src/main/java/dev/openrs2/crypto/Xtea.kt
  101. Some files were not shown because too many files have changed in this diff Show More

@ -10,9 +10,9 @@ import dev.openrs2.deob.DeobfuscateCommand
import dev.openrs2.deob.ast.DeobfuscateAstCommand import dev.openrs2.deob.ast.DeobfuscateAstCommand
import dev.openrs2.game.GameCommand import dev.openrs2.game.GameCommand
fun main(args: Array<String>) = Command().main(args) public fun main(args: Array<String>): Unit = Command().main(args)
class Command : NoOpCliktCommand(name = "openrs2") { public class Command : NoOpCliktCommand(name = "openrs2") {
init { init {
subcommands( subcommands(
BundleCommand(), BundleCommand(),

@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class AsmJacksonModule : SimpleModule() { public class AsmJacksonModule : SimpleModule() {
init { init {
addDeserializer(MemberRef::class.java, MemberRefDeserializer) addDeserializer(MemberRef::class.java, MemberRefDeserializer)
addKeyDeserializer(MemberRef::class.java, MemberRefKeyDeserializer) addKeyDeserializer(MemberRef::class.java, MemberRefKeyDeserializer)

@ -5,7 +5,7 @@ import com.google.inject.AbstractModule
import com.google.inject.multibindings.Multibinder import com.google.inject.multibindings.Multibinder
import dev.openrs2.yaml.YamlModule import dev.openrs2.yaml.YamlModule
object AsmModule : AbstractModule() { public object AsmModule : AbstractModule() {
override fun configure() { override fun configure() {
install(YamlModule) install(YamlModule)

@ -6,7 +6,7 @@ import org.objectweb.asm.tree.LdcInsnNode
import org.objectweb.asm.tree.MethodInsnNode import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.MethodNode
object ClassForNameUtils { public object ClassForNameUtils {
private val INVOKE_MATCHER = InsnMatcher.compile("LDC INVOKESTATIC") private val INVOKE_MATCHER = InsnMatcher.compile("LDC INVOKESTATIC")
private fun isClassForName(match: List<AbstractInsnNode>): Boolean { private fun isClassForName(match: List<AbstractInsnNode>): Boolean {
@ -31,11 +31,11 @@ object ClassForNameUtils {
return (ldc.cst as String).toInternalClassName() return (ldc.cst as String).toInternalClassName()
} }
fun findClassNames(method: MethodNode): Sequence<String> { public fun findClassNames(method: MethodNode): Sequence<String> {
return findLdcInsns(method).map(::internalName) return findLdcInsns(method).map(::internalName)
} }
fun remap(remapper: Remapper, method: MethodNode) { public fun remap(remapper: Remapper, method: MethodNode) {
for (ldc in findLdcInsns(method)) { for (ldc in findLdcInsns(method)) {
val name = remapper.mapType(internalName(ldc)) val name = remapper.mapType(internalName(ldc))
if (name != null) { if (name != null) {

@ -1,9 +1,9 @@
package dev.openrs2.asm package dev.openrs2.asm
fun String.toBinaryClassName(): String { public fun String.toBinaryClassName(): String {
return replace('/', '.') return replace('/', '.')
} }
fun String.toInternalClassName(): String { public fun String.toInternalClassName(): String {
return replace('.', '/') return replace('.', '/')
} }

@ -18,7 +18,7 @@ import org.objectweb.asm.tree.ParameterNode
import org.objectweb.asm.tree.TryCatchBlockNode import org.objectweb.asm.tree.TryCatchBlockNode
import org.objectweb.asm.tree.TypeInsnNode import org.objectweb.asm.tree.TypeInsnNode
fun ClassNode.remap(remapper: ExtendedRemapper) { public fun ClassNode.remap(remapper: ExtendedRemapper) {
val originalName = name val originalName = name
name = remapper.mapType(originalName) name = remapper.mapType(originalName)
signature = remapper.mapSignature(signature, false) signature = remapper.mapSignature(signature, false)
@ -46,20 +46,20 @@ fun ClassNode.remap(remapper: ExtendedRemapper) {
} }
} }
fun InnerClassNode.remap(remapper: Remapper) { public fun InnerClassNode.remap(remapper: Remapper) {
name = remapper.mapType(name) name = remapper.mapType(name)
outerName = remapper.mapType(outerName) outerName = remapper.mapType(outerName)
innerName = remapper.mapType(innerName) innerName = remapper.mapType(innerName)
} }
fun FieldNode.remap(remapper: ExtendedRemapper, owner: String) { public fun FieldNode.remap(remapper: ExtendedRemapper, owner: String) {
name = remapper.mapFieldName(owner, name, desc) name = remapper.mapFieldName(owner, name, desc)
desc = remapper.mapDesc(desc) desc = remapper.mapDesc(desc)
signature = remapper.mapSignature(signature, true) signature = remapper.mapSignature(signature, true)
value = remapper.mapValue(value) value = remapper.mapValue(value)
} }
fun MethodNode.remap(remapper: ExtendedRemapper, owner: String) { public fun MethodNode.remap(remapper: ExtendedRemapper, owner: String) {
if (parameters == null) { if (parameters == null) {
parameters = List(Type.getArgumentTypes(desc).size) { ParameterNode(null, 0) } parameters = List(Type.getArgumentTypes(desc).size) { ParameterNode(null, 0) }
} }
@ -86,15 +86,21 @@ fun MethodNode.remap(remapper: ExtendedRemapper, owner: String) {
} }
} }
fun ParameterNode.remap(remapper: ExtendedRemapper, owner: String, methodName: String, desc: String, index: Int) { public fun ParameterNode.remap(
remapper: ExtendedRemapper,
owner: String,
methodName: String,
desc: String,
index: Int
) {
name = remapper.mapArgumentName(owner, methodName, desc, index, name) name = remapper.mapArgumentName(owner, methodName, desc, index, name)
} }
fun TryCatchBlockNode.remap(remapper: Remapper) { public fun TryCatchBlockNode.remap(remapper: Remapper) {
type = remapper.mapType(type) type = remapper.mapType(type)
} }
fun AbstractInsnNode.remap(remapper: ExtendedRemapper) { public fun AbstractInsnNode.remap(remapper: ExtendedRemapper) {
when (this) { when (this) {
is FrameNode -> throw UnsupportedOperationException("SKIP_FRAMES and COMPUTE_FRAMES must be used") is FrameNode -> throw UnsupportedOperationException("SKIP_FRAMES and COMPUTE_FRAMES must be used")
is FieldInsnNode -> { is FieldInsnNode -> {

@ -1,15 +1,15 @@
package dev.openrs2.asm package dev.openrs2.asm
object ClassVersionUtils { public object ClassVersionUtils {
private fun swapWords(v: Int): Int { private fun swapWords(v: Int): Int {
return (v shl 16) or (v ushr 16) return (v shl 16) or (v ushr 16)
} }
fun gte(v1: Int, v2: Int): Boolean { public fun gte(v1: Int, v2: Int): Boolean {
return swapWords(v1) >= swapWords(v2) return swapWords(v1) >= swapWords(v2)
} }
fun max(v1: Int, v2: Int): Int { public fun max(v1: Int, v2: Int): Int {
return if (gte(v1, v2)) { return if (gte(v1, v2)) {
v1 v1
} else { } else {

@ -5,7 +5,7 @@ import org.objectweb.asm.tree.InsnList
private val ANY_INSN = { _: AbstractInsnNode -> true } private val ANY_INSN = { _: AbstractInsnNode -> true }
fun getExpression( public fun getExpression(
last: AbstractInsnNode, last: AbstractInsnNode,
filter: (AbstractInsnNode) -> Boolean = ANY_INSN filter: (AbstractInsnNode) -> Boolean = ANY_INSN
): List<AbstractInsnNode>? { ): List<AbstractInsnNode>? {
@ -31,7 +31,7 @@ fun getExpression(
return null return null
} }
fun InsnList.replaceExpression( public fun InsnList.replaceExpression(
last: AbstractInsnNode, last: AbstractInsnNode,
replacement: AbstractInsnNode, replacement: AbstractInsnNode,
filter: (AbstractInsnNode) -> Boolean = ANY_INSN filter: (AbstractInsnNode) -> Boolean = ANY_INSN
@ -42,7 +42,7 @@ fun InsnList.replaceExpression(
return true return true
} }
fun InsnList.deleteExpression( public fun InsnList.deleteExpression(
last: AbstractInsnNode, last: AbstractInsnNode,
filter: (AbstractInsnNode) -> Boolean = ANY_INSN filter: (AbstractInsnNode) -> Boolean = ANY_INSN
): Boolean { ): Boolean {

@ -6,12 +6,12 @@ import org.objectweb.asm.tree.InsnList
import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.MethodNode
import org.objectweb.asm.util.Printer import org.objectweb.asm.util.Printer
class InsnMatcher private constructor(private val regex: Regex) { public class InsnMatcher private constructor(private val regex: Regex) {
fun match(method: MethodNode): Sequence<List<AbstractInsnNode>> { public fun match(method: MethodNode): Sequence<List<AbstractInsnNode>> {
return match(method.instructions) return match(method.instructions)
} }
fun match(list: InsnList): Sequence<List<AbstractInsnNode>> { public fun match(list: InsnList): Sequence<List<AbstractInsnNode>> {
val insns = ArrayList<AbstractInsnNode>(list.size()) val insns = ArrayList<AbstractInsnNode>(list.size())
val builder = StringBuilder(list.size()) val builder = StringBuilder(list.size())
@ -27,7 +27,7 @@ class InsnMatcher private constructor(private val regex: Regex) {
} }
} }
companion object { public companion object {
private const val PRIVATE_USE_AREA = 0xE000 private const val PRIVATE_USE_AREA = 0xE000
private val OPCODE_GROUPS = mapOf( private val OPCODE_GROUPS = mapOf(
"InsnNode" to intArrayOf( "InsnNode" to intArrayOf(
@ -260,7 +260,7 @@ class InsnMatcher private constructor(private val regex: Regex) {
throw IllegalArgumentException("$opcode is not a valid opcode or opcode group") throw IllegalArgumentException("$opcode is not a valid opcode or opcode group")
} }
fun compile(regex: String): InsnMatcher { public fun compile(regex: String): InsnMatcher {
val pattern = StringBuilder() val pattern = StringBuilder()
val opcode = StringBuilder() val opcode = StringBuilder()

@ -200,7 +200,7 @@ private val THROW_RETURN_OPCODES = listOf(
Opcodes.ATHROW Opcodes.ATHROW
) )
val AbstractInsnNode.nextReal: AbstractInsnNode? public val AbstractInsnNode.nextReal: AbstractInsnNode?
get() { get() {
var insn = next var insn = next
while (insn != null && insn.opcode == -1) { while (insn != null && insn.opcode == -1) {
@ -209,7 +209,7 @@ val AbstractInsnNode.nextReal: AbstractInsnNode?
return insn return insn
} }
val AbstractInsnNode.previousReal: AbstractInsnNode? public val AbstractInsnNode.previousReal: AbstractInsnNode?
get() { get() {
var insn = previous var insn = previous
while (insn != null && insn.opcode == -1) { while (insn != null && insn.opcode == -1) {
@ -218,7 +218,7 @@ val AbstractInsnNode.previousReal: AbstractInsnNode?
return insn return insn
} }
val AbstractInsnNode.nextVirtual: AbstractInsnNode? public val AbstractInsnNode.nextVirtual: AbstractInsnNode?
get() { get() {
var insn = next var insn = next
while (insn != null && insn.opcode != -1) { while (insn != null && insn.opcode != -1) {
@ -227,7 +227,7 @@ val AbstractInsnNode.nextVirtual: AbstractInsnNode?
return insn return insn
} }
val AbstractInsnNode.previousVirtual: AbstractInsnNode? public val AbstractInsnNode.previousVirtual: AbstractInsnNode?
get() { get() {
var insn = previous var insn = previous
while (insn != null && insn.opcode != -1) { while (insn != null && insn.opcode != -1) {
@ -236,7 +236,7 @@ val AbstractInsnNode.previousVirtual: AbstractInsnNode?
return insn return insn
} }
val AbstractInsnNode.intConstant: Int? public val AbstractInsnNode.intConstant: Int?
get() = when (this) { get() = when (this) {
is IntInsnNode -> { is IntInsnNode -> {
if (opcode == Opcodes.BIPUSH || opcode == Opcodes.SIPUSH) { if (opcode == Opcodes.BIPUSH || opcode == Opcodes.SIPUSH) {
@ -265,7 +265,7 @@ val AbstractInsnNode.intConstant: Int?
} }
} }
val AbstractInsnNode.isSequential: Boolean public val AbstractInsnNode.isSequential: Boolean
get() = when (this) { get() = when (this) {
is LabelNode -> false is LabelNode -> false
is JumpInsnNode -> false is JumpInsnNode -> false
@ -274,14 +274,14 @@ val AbstractInsnNode.isSequential: Boolean
else -> opcode !in THROW_RETURN_OPCODES else -> opcode !in THROW_RETURN_OPCODES
} }
val AbstractInsnNode.isPure: Boolean public val AbstractInsnNode.isPure: Boolean
get() = when (opcode) { get() = when (opcode) {
in PURE_OPCODES -> true in PURE_OPCODES -> true
in IMPURE_OPCODES -> false in IMPURE_OPCODES -> false
else -> throw IllegalArgumentException() else -> throw IllegalArgumentException()
} }
fun Int.toAbstractInsnNode(): AbstractInsnNode = when (this) { public fun Int.toAbstractInsnNode(): AbstractInsnNode = when (this) {
-1 -> InsnNode(Opcodes.ICONST_M1) -1 -> InsnNode(Opcodes.ICONST_M1)
0 -> InsnNode(Opcodes.ICONST_0) 0 -> InsnNode(Opcodes.ICONST_0)
1 -> InsnNode(Opcodes.ICONST_1) 1 -> InsnNode(Opcodes.ICONST_1)
@ -294,7 +294,7 @@ fun Int.toAbstractInsnNode(): AbstractInsnNode = when (this) {
else -> LdcInsnNode(this) else -> LdcInsnNode(this)
} }
fun AbstractInsnNode.toPrettyString(): String { public fun AbstractInsnNode.toPrettyString(): String {
val printer = Textifier() val printer = Textifier()
val visitor = TraceMethodVisitor(printer) val visitor = TraceMethodVisitor(printer)
@ -308,7 +308,7 @@ fun AbstractInsnNode.toPrettyString(): String {
} }
} }
fun TryCatchBlockNode.isBodyEmpty(): Boolean { public fun TryCatchBlockNode.isBodyEmpty(): Boolean {
var current = start.next var current = start.next
while (true) { while (true) {

@ -5,12 +5,12 @@ import org.objectweb.asm.tree.FieldNode
import org.objectweb.asm.tree.MethodInsnNode import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.MethodNode
data class MemberDesc(val name: String, val desc: String) { public data class MemberDesc(val name: String, val desc: String) {
constructor(field: FieldNode) : this(field.name, field.desc) public constructor(field: FieldNode) : this(field.name, field.desc)
constructor(method: MethodNode) : this(method.name, method.desc) public constructor(method: MethodNode) : this(method.name, method.desc)
constructor(fieldInsn: FieldInsnNode) : this(fieldInsn.name, fieldInsn.desc) public constructor(fieldInsn: FieldInsnNode) : this(fieldInsn.name, fieldInsn.desc)
constructor(methodInsn: MethodInsnNode) : this(methodInsn.name, methodInsn.desc) public constructor(methodInsn: MethodInsnNode) : this(methodInsn.name, methodInsn.desc)
constructor(memberRef: MemberRef) : this(memberRef.name, memberRef.desc) public constructor(memberRef: MemberRef) : this(memberRef.name, memberRef.desc)
override fun toString(): String { override fun toString(): String {
return "$name $desc" return "$name $desc"

@ -6,12 +6,12 @@ import org.objectweb.asm.tree.FieldNode
import org.objectweb.asm.tree.MethodInsnNode import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.MethodNode
data class MemberRef(val owner: String, val name: String, val desc: String) : Comparable<MemberRef> { public data class MemberRef(val owner: String, val name: String, val desc: String) : Comparable<MemberRef> {
constructor(clazz: ClassNode, field: FieldNode) : this(clazz.name, field.name, field.desc) public constructor(clazz: ClassNode, field: FieldNode) : this(clazz.name, field.name, field.desc)
constructor(clazz: ClassNode, method: MethodNode) : this(clazz.name, method.name, method.desc) public constructor(clazz: ClassNode, method: MethodNode) : this(clazz.name, method.name, method.desc)
constructor(fieldInsn: FieldInsnNode) : this(fieldInsn.owner, fieldInsn.name, fieldInsn.desc) public constructor(fieldInsn: FieldInsnNode) : this(fieldInsn.owner, fieldInsn.name, fieldInsn.desc)
constructor(methodInsn: MethodInsnNode) : this(methodInsn.owner, methodInsn.name, methodInsn.desc) public constructor(methodInsn: MethodInsnNode) : this(methodInsn.owner, methodInsn.name, methodInsn.desc)
constructor(owner: String, desc: MemberDesc) : this(owner, desc.name, desc.desc) public constructor(owner: String, desc: MemberDesc) : this(owner, desc.name, desc.desc)
override fun compareTo(other: MemberRef): Int { override fun compareTo(other: MemberRef): Int {
var result = owner.compareTo(other.owner) var result = owner.compareTo(other.owner)
@ -31,10 +31,10 @@ data class MemberRef(val owner: String, val name: String, val desc: String) : Co
return "$owner.$name $desc" return "$owner.$name $desc"
} }
companion object { public companion object {
private val STRING_REGEX = Regex("([^.]+)[.]([^ ]+) (.+)") private val STRING_REGEX = Regex("([^.]+)[.]([^ ]+) (.+)")
fun fromString(str: String): MemberRef { public fun fromString(str: String): MemberRef {
val result = STRING_REGEX.matchEntire(str) val result = STRING_REGEX.matchEntire(str)
require(result != null) require(result != null)
return MemberRef(result.groupValues[1], result.groupValues[2], result.groupValues[3]) return MemberRef(result.groupValues[1], result.groupValues[2], result.groupValues[3])

@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.deser.std.StdDeserializer import com.fasterxml.jackson.databind.deser.std.StdDeserializer
object MemberRefDeserializer : StdDeserializer<MemberRef>(MemberRef::class.java) { public object MemberRefDeserializer : StdDeserializer<MemberRef>(MemberRef::class.java) {
override fun deserialize(parser: JsonParser, ctx: DeserializationContext): MemberRef { override fun deserialize(parser: JsonParser, ctx: DeserializationContext): MemberRef {
return MemberRef.fromString(ctx.readValue(parser, String::class.java)) return MemberRef.fromString(ctx.readValue(parser, String::class.java))
} }

@ -3,7 +3,7 @@ package dev.openrs2.asm
import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.KeyDeserializer import com.fasterxml.jackson.databind.KeyDeserializer
object MemberRefKeyDeserializer : KeyDeserializer() { public object MemberRefKeyDeserializer : KeyDeserializer() {
override fun deserializeKey(key: String, ctx: DeserializationContext): Any { override fun deserializeKey(key: String, ctx: DeserializationContext): Any {
return MemberRef.fromString(key) return MemberRef.fromString(key)
} }

@ -33,7 +33,7 @@ private fun remapAll(indexes: List<Int>, argType: Type, localIndex: Int, newLoca
return indexes.mapTo(mutableListOf()) { remap(it, argType, localIndex, newLocalIndex) } return indexes.mapTo(mutableListOf()) { remap(it, argType, localIndex, newLocalIndex) }
} }
fun MethodNode.removeArgument(argIndex: Int) { public fun MethodNode.removeArgument(argIndex: Int) {
// remove argument from the descriptor // remove argument from the descriptor
val type = Type.getType(desc) val type = Type.getType(desc)
val argType = type.argumentTypes[argIndex] val argType = type.argumentTypes[argIndex]
@ -129,7 +129,7 @@ fun MethodNode.removeArgument(argIndex: Int) {
} }
} }
fun MethodNode.removeDeadCode(owner: String) { public fun MethodNode.removeDeadCode(owner: String) {
var changed: Boolean var changed: Boolean
do { do {
changed = false changed = false
@ -152,10 +152,10 @@ fun MethodNode.removeDeadCode(owner: String) {
} while (changed) } while (changed)
} }
val MethodNode.hasCode public val MethodNode.hasCode: Boolean
get() = access and (Opcodes.ACC_NATIVE or Opcodes.ACC_ABSTRACT) == 0 get() = access and (Opcodes.ACC_NATIVE or Opcodes.ACC_ABSTRACT) == 0
fun MethodNode.copy(): MethodNode { public fun MethodNode.copy(): MethodNode {
val copy = MethodNode( val copy = MethodNode(
access, access,
name, name,

@ -3,4 +3,4 @@ package dev.openrs2.asm
import org.objectweb.asm.ClassVisitor import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.Opcodes import org.objectweb.asm.Opcodes
object NopClassVisitor : ClassVisitor(Opcodes.ASM8) public object NopClassVisitor : ClassVisitor(Opcodes.ASM8)

@ -9,7 +9,7 @@ import org.objectweb.asm.tree.LdcInsnNode
import org.objectweb.asm.tree.MethodInsnNode import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.MultiANewArrayInsnNode import org.objectweb.asm.tree.MultiANewArrayInsnNode
data class StackMetadata(val pops: Int, val pushes: Int) public data class StackMetadata(val pops: Int, val pushes: Int)
private val NONE = StackMetadata(0, 0) private val NONE = StackMetadata(0, 0)
private val POP1 = StackMetadata(1, 0) private val POP1 = StackMetadata(1, 0)
@ -181,7 +181,7 @@ private val SIMPLE_OPCODES = mapOf(
Opcodes.IFNONNULL to POP1 Opcodes.IFNONNULL to POP1
) )
val AbstractInsnNode.stackMetadata public val AbstractInsnNode.stackMetadata: StackMetadata
get() = when (this) { get() = when (this) {
is LdcInsnNode -> if (cst is Double || cst is Long) { is LdcInsnNode -> if (cst is Double || cst is Long) {
PUSH2 PUSH2

@ -4,7 +4,7 @@ import dev.openrs2.asm.MemberDesc
import org.objectweb.asm.Opcodes import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.ClassNode
class AsmClassMetadata( public class AsmClassMetadata(
private val classPath: ClassPath, private val classPath: ClassPath,
private val clazz: ClassNode, private val clazz: ClassNode,
override val dependency: Boolean override val dependency: Boolean
@ -12,19 +12,19 @@ class AsmClassMetadata(
override val name: String override val name: String
get() = clazz.name get() = clazz.name
override val `interface` override val `interface`: Boolean
get() = clazz.access and Opcodes.ACC_INTERFACE != 0 get() = clazz.access and Opcodes.ACC_INTERFACE != 0
override val superClass override val superClass: ClassMetadata?
get() = clazz.superName?.let { classPath[it] ?: error("Failed to find $it on provided classpath.") } get() = clazz.superName?.let { classPath[it] ?: error("Failed to find $it on provided classpath.") }
override val superInterfaces override val superInterfaces: List<ClassMetadata>
get() = clazz.interfaces.map { classPath[it] ?: error("Failed to find $it on provided classpath.") } get() = clazz.interfaces.map { classPath[it] ?: error("Failed to find $it on provided classpath.") }
override val fields override val fields: List<MemberDesc>
get() = clazz.fields.map(::MemberDesc) get() = clazz.fields.map(::MemberDesc)
override val methods override val methods: List<MemberDesc>
get() = clazz.methods.map(::MemberDesc) get() = clazz.methods.map(::MemberDesc)
override fun getFieldAccess(field: MemberDesc): Int? { override fun getFieldAccess(field: MemberDesc): Int? {

@ -2,16 +2,16 @@ package dev.openrs2.asm.classpath
import dev.openrs2.asm.MemberDesc import dev.openrs2.asm.MemberDesc
abstract class ClassMetadata { public abstract class ClassMetadata {
abstract val name: String public abstract val name: String
abstract val dependency: Boolean public abstract val dependency: Boolean
abstract val `interface`: Boolean public abstract val `interface`: Boolean
abstract val superClass: ClassMetadata? public abstract val superClass: ClassMetadata?
abstract val superInterfaces: List<ClassMetadata> public abstract val superInterfaces: List<ClassMetadata>
abstract val fields: List<MemberDesc> public abstract val fields: List<MemberDesc>
abstract val methods: List<MemberDesc> public abstract val methods: List<MemberDesc>
val superClassAndInterfaces: List<ClassMetadata> public val superClassAndInterfaces: List<ClassMetadata>
get() { get() {
val clazz = superClass val clazz = superClass
return if (clazz != null) { return if (clazz != null) {
@ -21,10 +21,10 @@ abstract class ClassMetadata {
} }
} }
abstract fun getFieldAccess(field: MemberDesc): Int? public abstract fun getFieldAccess(field: MemberDesc): Int?
abstract fun getMethodAccess(method: MemberDesc): Int? public abstract fun getMethodAccess(method: MemberDesc): Int?
fun isOverride(method: MemberDesc): Boolean { public fun isOverride(method: MemberDesc): Boolean {
val superClass = this.superClass val superClass = this.superClass
if (superClass != null) { if (superClass != null) {
if (method in superClass.methods) { if (method in superClass.methods) {
@ -49,7 +49,7 @@ abstract class ClassMetadata {
return false return false
} }
fun isAssignableFrom(type: ClassMetadata): Boolean { public fun isAssignableFrom(type: ClassMetadata): Boolean {
return type == this || isSuperClassOf(type) || isSuperInterfaceOf(type) return type == this || isSuperClassOf(type) || isSuperInterfaceOf(type)
} }
@ -71,7 +71,7 @@ abstract class ClassMetadata {
return false return false
} }
fun resolveField(member: MemberDesc): ClassMetadata? { public fun resolveField(member: MemberDesc): ClassMetadata? {
// see https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-5.html#jvms-5.4.3.2 // see https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-5.html#jvms-5.4.3.2
if (fields.contains(member)) { if (fields.contains(member)) {

@ -10,10 +10,10 @@ import org.objectweb.asm.tree.AbstractInsnNode
import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.ClassNode
import java.util.IdentityHashMap import java.util.IdentityHashMap
class ClassPath( public class ClassPath(
private val runtime: ClassLoader, private val runtime: ClassLoader,
private val dependencies: List<Library>, private val dependencies: List<Library>,
val libraries: List<Library> public val libraries: List<Library>
) { ) {
private val cache = mutableMapOf<String, ClassMetadata?>() private val cache = mutableMapOf<String, ClassMetadata?>()
@ -26,9 +26,9 @@ class ClassPath(
* Transformers to avoid adding extraneous labels until the last possible * Transformers to avoid adding extraneous labels until the last possible
* moment, which would confuse some of our analyses if added earlier. * moment, which would confuse some of our analyses if added earlier.
*/ */
val originalPcs = IdentityHashMap<AbstractInsnNode, Int>() public val originalPcs: MutableMap<AbstractInsnNode, Int> = IdentityHashMap()
val libraryClasses: Sequence<ClassMetadata> public val libraryClasses: Sequence<ClassMetadata>
get() = libraries.asSequence().flatten().map { get(it.name)!! } get() = libraries.asSequence().flatten().map { get(it.name)!! }
private inline fun computeIfAbsent(name: String, f: (String) -> ClassMetadata?): ClassMetadata? { private inline fun computeIfAbsent(name: String, f: (String) -> ClassMetadata?): ClassMetadata? {
@ -41,7 +41,7 @@ class ClassPath(
return clazz return clazz
} }
operator fun get(name: String): ClassMetadata? = computeIfAbsent(name) { public operator fun get(name: String): ClassMetadata? = computeIfAbsent(name) {
for (library in libraries) { for (library in libraries) {
val clazz = library[name] val clazz = library[name]
if (clazz != null) { if (clazz != null) {
@ -65,7 +65,7 @@ class ClassPath(
return@computeIfAbsent ReflectionClassMetadata(this, clazz) return@computeIfAbsent ReflectionClassMetadata(this, clazz)
} }
fun getClassNode(name: String): ClassNode? { public fun getClassNode(name: String): ClassNode? {
for (library in libraries) { for (library in libraries) {
val clazz = library[name] val clazz = library[name]
if (clazz != null) { if (clazz != null) {
@ -76,7 +76,7 @@ class ClassPath(
return null return null
} }
fun remap(remapper: ExtendedRemapper) { public fun remap(remapper: ExtendedRemapper) {
for (library in libraries) { for (library in libraries) {
library.remap(remapper) library.remap(remapper)
} }
@ -84,11 +84,11 @@ class ClassPath(
cache.clear() cache.clear()
} }
fun createInheritedFieldSets(): DisjointSet<MemberRef> { public fun createInheritedFieldSets(): DisjointSet<MemberRef> {
return createInheritedMemberSets(ClassMetadata::fields, ClassMetadata::getFieldAccess, fields = true) return createInheritedMemberSets(ClassMetadata::fields, ClassMetadata::getFieldAccess, fields = true)
} }
fun createInheritedMethodSets(): DisjointSet<MemberRef> { public fun createInheritedMethodSets(): DisjointSet<MemberRef> {
return createInheritedMemberSets(ClassMetadata::methods, ClassMetadata::getMethodAccess, fields = false) return createInheritedMemberSets(ClassMetadata::methods, ClassMetadata::getMethodAccess, fields = false)
} }

@ -3,20 +3,20 @@ package dev.openrs2.asm.classpath
import org.objectweb.asm.commons.Remapper import org.objectweb.asm.commons.Remapper
import org.objectweb.asm.tree.AbstractInsnNode import org.objectweb.asm.tree.AbstractInsnNode
abstract class ExtendedRemapper : Remapper() { public abstract class ExtendedRemapper : Remapper() {
open fun getFieldInitializer(owner: String, name: String, descriptor: String): List<AbstractInsnNode>? { public open fun getFieldInitializer(owner: String, name: String, descriptor: String): List<AbstractInsnNode>? {
return null return null
} }
open fun mapFieldOwner(owner: String, name: String, descriptor: String): String { public open fun mapFieldOwner(owner: String, name: String, descriptor: String): String {
return mapType(owner) return mapType(owner)
} }
open fun mapMethodOwner(owner: String, name: String, descriptor: String): String { public open fun mapMethodOwner(owner: String, name: String, descriptor: String): String {
return mapType(owner) return mapType(owner)
} }
open fun mapArgumentName( public open fun mapArgumentName(
owner: String, owner: String,
name: String, name: String,
descriptor: String, descriptor: String,

@ -5,7 +5,7 @@ import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes import org.objectweb.asm.Opcodes
import org.objectweb.asm.commons.JSRInlinerAdapter import org.objectweb.asm.commons.JSRInlinerAdapter
class JsrInliner(cv: ClassVisitor) : ClassVisitor(Opcodes.ASM8, cv) { public class JsrInliner(cv: ClassVisitor) : ClassVisitor(Opcodes.ASM8, cv) {
override fun visitMethod( override fun visitMethod(
access: Int, access: Int,
name: String, name: String,

@ -10,10 +10,10 @@ import java.nio.file.Path
import java.util.SortedMap import java.util.SortedMap
import java.util.TreeMap import java.util.TreeMap
class Library(val name: String) : Iterable<ClassNode> { public class Library(public val name: String) : Iterable<ClassNode> {
private var classes: SortedMap<String, ClassNode> = TreeMap() private var classes: SortedMap<String, ClassNode> = TreeMap()
constructor(name: String, library: Library) : this(name) { public constructor(name: String, library: Library) : this(name) {
for (clazz in library.classes.values) { for (clazz in library.classes.values) {
val copy = ClassNode() val copy = ClassNode()
clazz.accept(copy) clazz.accept(copy)
@ -21,19 +21,19 @@ class Library(val name: String) : Iterable<ClassNode> {
} }
} }
operator fun contains(name: String): Boolean { public operator fun contains(name: String): Boolean {
return classes.containsKey(name) return classes.containsKey(name)
} }
operator fun get(name: String): ClassNode? { public operator fun get(name: String): ClassNode? {
return classes[name] return classes[name]
} }
fun add(clazz: ClassNode): ClassNode? { public fun add(clazz: ClassNode): ClassNode? {
return classes.put(clazz.name, clazz) return classes.put(clazz.name, clazz)
} }
fun remove(name: String): ClassNode? { public fun remove(name: String): ClassNode? {
return classes.remove(name) return classes.remove(name)
} }
@ -41,11 +41,11 @@ class Library(val name: String) : Iterable<ClassNode> {
return classes.values.iterator() return classes.values.iterator()
} }
fun remap(remapper: ExtendedRemapper) { public fun remap(remapper: ExtendedRemapper) {
classes = LibraryRemapper(remapper, classes).remap() classes = LibraryRemapper(remapper, classes).remap()
} }
fun write(path: Path, writer: LibraryWriter, classPath: ClassPath) { public fun write(path: Path, writer: LibraryWriter, classPath: ClassPath) {
logger.info { "Writing library $path" } logger.info { "Writing library $path" }
path.useAtomicOutputStream { output -> path.useAtomicOutputStream { output ->
@ -53,10 +53,10 @@ class Library(val name: String) : Iterable<ClassNode> {
} }
} }
companion object { public companion object {
private val logger = InlineLogger() private val logger = InlineLogger()
fun read(name: String, path: Path, reader: LibraryReader): Library { public fun read(name: String, path: Path, reader: LibraryReader): Library {
logger.info { "Reading library $path" } logger.info { "Reading library $path" }
val classes = Files.newInputStream(path).use { input -> val classes = Files.newInputStream(path).use { input ->

@ -15,7 +15,7 @@ import java.util.SortedMap
import java.util.TreeMap import java.util.TreeMap
import kotlin.math.max import kotlin.math.max
class LibraryRemapper( public class LibraryRemapper(
private val remapper: ExtendedRemapper, private val remapper: ExtendedRemapper,
private var classes: SortedMap<String, ClassNode> private var classes: SortedMap<String, ClassNode>
) { ) {
@ -34,7 +34,7 @@ class LibraryRemapper(
private val splicedFields = mutableSetOf<MemberRef>() private val splicedFields = mutableSetOf<MemberRef>()
private val methods = mutableListOf<Method>() private val methods = mutableListOf<Method>()
fun remap(): SortedMap<String, ClassNode> { public fun remap(): SortedMap<String, ClassNode> {
// extract static fields/methods that are being moved between classes // extract static fields/methods that are being moved between classes
extractFields() extractFields()
extractMethods() extractMethods()

@ -7,7 +7,7 @@ import org.objectweb.asm.Type
private val Class<*>.asmName: String private val Class<*>.asmName: String
get() = name.toInternalClassName() get() = name.toInternalClassName()
class ReflectionClassMetadata(private val classPath: ClassPath, private val clazz: Class<*>) : ClassMetadata() { public class ReflectionClassMetadata(private val classPath: ClassPath, private val clazz: Class<*>) : ClassMetadata() {
override val name: String override val name: String
get() = clazz.asmName get() = clazz.asmName
@ -20,13 +20,13 @@ class ReflectionClassMetadata(private val classPath: ClassPath, private val claz
override val superClass: ClassMetadata? override val superClass: ClassMetadata?
get() = if (clazz.superclass != null) classPath[clazz.superclass.asmName]!! else null get() = if (clazz.superclass != null) classPath[clazz.superclass.asmName]!! else null
override val superInterfaces override val superInterfaces: List<ClassMetadata>
get() = clazz.interfaces.map { classPath[it.asmName]!! } get() = clazz.interfaces.map { classPath[it.asmName]!! }
override val fields override val fields: List<MemberDesc>
get() = clazz.declaredFields.map { MemberDesc(it.name, Type.getDescriptor(it.type)) } get() = clazz.declaredFields.map { MemberDesc(it.name, Type.getDescriptor(it.type)) }
override val methods override val methods: List<MemberDesc>
get() = clazz.declaredMethods.map { MemberDesc(it.name, Type.getMethodDescriptor(it)) } get() = clazz.declaredMethods.map { MemberDesc(it.name, Type.getMethodDescriptor(it)) }
override fun getFieldAccess(field: MemberDesc): Int? { override fun getFieldAccess(field: MemberDesc): Int? {

@ -2,7 +2,7 @@ package dev.openrs2.asm.classpath
import org.objectweb.asm.ClassWriter import org.objectweb.asm.ClassWriter
class StackFrameClassWriter(private val classPath: ClassPath) : ClassWriter(COMPUTE_FRAMES) { public class StackFrameClassWriter(private val classPath: ClassPath) : ClassWriter(COMPUTE_FRAMES) {
override fun getCommonSuperClass(type1: String, type2: String): String { override fun getCommonSuperClass(type1: String, type2: String): String {
var c = classPath[type1]!! var c = classPath[type1]!!
val d = classPath[type2]!! val d = classPath[type2]!!

@ -1,6 +1,6 @@
package dev.openrs2.asm.filter package dev.openrs2.asm.filter
object AnyClassFilter : ClassFilter { public object AnyClassFilter : ClassFilter {
override fun matches(name: String): Boolean { override fun matches(name: String): Boolean {
return true return true
} }

@ -1,6 +1,6 @@
package dev.openrs2.asm.filter package dev.openrs2.asm.filter
object AnyMemberFilter : MemberFilter { public object AnyMemberFilter : MemberFilter {
override fun matches(owner: String, name: String, desc: String): Boolean { override fun matches(owner: String, name: String, desc: String): Boolean {
return true return true
} }

@ -1,5 +1,5 @@
package dev.openrs2.asm.filter package dev.openrs2.asm.filter
interface ClassFilter { public interface ClassFilter {
fun matches(name: String): Boolean public fun matches(name: String): Boolean
} }

@ -1,11 +1,11 @@
package dev.openrs2.asm.filter package dev.openrs2.asm.filter
object Glob { public object Glob {
fun compile(pattern: String): Regex { public fun compile(pattern: String): Regex {
return compile(pattern, className = false) return compile(pattern, className = false)
} }
fun compileClass(pattern: String): Regex { public fun compileClass(pattern: String): Regex {
return compile(pattern, className = true) return compile(pattern, className = true)
} }

@ -2,7 +2,7 @@ package dev.openrs2.asm.filter
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
class GlobClassFilter(@Suppress("CanBeParameter") private val patterns: List<String>) : ClassFilter { public class GlobClassFilter(@Suppress("CanBeParameter") private val patterns: List<String>) : ClassFilter {
@JsonIgnore @JsonIgnore
private val compiledPatterns = patterns.map(Glob::compileClass).toList() private val compiledPatterns = patterns.map(Glob::compileClass).toList()

@ -3,7 +3,7 @@ package dev.openrs2.asm.filter
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import dev.openrs2.asm.MemberRef import dev.openrs2.asm.MemberRef
class GlobMemberFilter(@Suppress("CanBeParameter") private val patterns: List<MemberRef>) : MemberFilter { public class GlobMemberFilter(@Suppress("CanBeParameter") private val patterns: List<MemberRef>) : MemberFilter {
private data class CompiledPattern(val owner: Regex, val name: Regex, val desc: Regex) private data class CompiledPattern(val owner: Regex, val name: Regex, val desc: Regex)
@JsonIgnore @JsonIgnore

@ -2,10 +2,10 @@ package dev.openrs2.asm.filter
import dev.openrs2.asm.MemberRef import dev.openrs2.asm.MemberRef
interface MemberFilter { public interface MemberFilter {
fun matches(owner: String, name: String, desc: String): Boolean public fun matches(owner: String, name: String, desc: String): Boolean
fun matches(member: MemberRef): Boolean { public fun matches(member: MemberRef): Boolean {
return matches(member.owner, member.name, member.desc) return matches(member.owner, member.name, member.desc)
} }
} }

@ -1,6 +1,6 @@
package dev.openrs2.asm.filter package dev.openrs2.asm.filter
class UnionClassFilter(vararg filters: ClassFilter) : ClassFilter { public class UnionClassFilter(vararg filters: ClassFilter) : ClassFilter {
private val filters = filters.toList() private val filters = filters.toList()
override fun matches(name: String): Boolean { override fun matches(name: String): Boolean {

@ -1,6 +1,6 @@
package dev.openrs2.asm.filter package dev.openrs2.asm.filter
class UnionMemberFilter(vararg filters: MemberFilter) : MemberFilter { public class UnionMemberFilter(vararg filters: MemberFilter) : MemberFilter {
private val filters = filters.toList() private val filters = filters.toList()
override fun matches(owner: String, name: String, desc: String): Boolean { override fun matches(owner: String, name: String, desc: String): Boolean {

@ -12,7 +12,7 @@ import java.io.OutputStream
import java.util.jar.JarEntry import java.util.jar.JarEntry
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
abstract class AbstractJarLibraryWriter : LibraryWriter { public abstract class AbstractJarLibraryWriter : LibraryWriter {
override fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>) { override fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>) {
createJarOutputStream(output).use { jar -> createJarOutputStream(output).use { jar ->
for (clazz in classes) { for (clazz in classes) {

@ -7,7 +7,7 @@ import org.objectweb.asm.tree.ClassNode
import java.io.InputStream import java.io.InputStream
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
object JarLibraryReader : LibraryReader { public object JarLibraryReader : LibraryReader {
private const val CLASS_SUFFIX = ".class" private const val CLASS_SUFFIX = ".class"
override fun read(input: InputStream): Iterable<ClassNode> { override fun read(input: InputStream): Iterable<ClassNode> {

@ -4,7 +4,7 @@ import dev.openrs2.util.io.DeterministicJarOutputStream
import java.io.OutputStream import java.io.OutputStream
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
object JarLibraryWriter : AbstractJarLibraryWriter() { public object JarLibraryWriter : AbstractJarLibraryWriter() {
override fun createJarOutputStream(output: OutputStream): JarOutputStream { override fun createJarOutputStream(output: OutputStream): JarOutputStream {
return DeterministicJarOutputStream(output) return DeterministicJarOutputStream(output)
} }

@ -3,6 +3,6 @@ package dev.openrs2.asm.io
import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.ClassNode
import java.io.InputStream import java.io.InputStream
interface LibraryReader { public interface LibraryReader {
fun read(input: InputStream): Iterable<ClassNode> public fun read(input: InputStream): Iterable<ClassNode>
} }

@ -4,6 +4,6 @@ import dev.openrs2.asm.classpath.ClassPath
import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.ClassNode
import java.io.OutputStream import java.io.OutputStream
interface LibraryWriter { public interface LibraryWriter {
fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>) public fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>)
} }

@ -5,7 +5,7 @@ import java.io.OutputStream
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
import java.util.jar.Manifest import java.util.jar.Manifest
class ManifestJarLibraryWriter(private val manifest: Manifest) : AbstractJarLibraryWriter() { public class ManifestJarLibraryWriter(private val manifest: Manifest) : AbstractJarLibraryWriter() {
override fun createJarOutputStream(output: OutputStream): JarOutputStream { override fun createJarOutputStream(output: OutputStream): JarOutputStream {
return DeterministicJarOutputStream(output, manifest) return DeterministicJarOutputStream(output, manifest)
} }

@ -8,7 +8,7 @@ import java.io.InputStream
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
import java.util.jar.Pack200 import java.util.jar.Pack200
object Pack200LibraryReader : LibraryReader { public object Pack200LibraryReader : LibraryReader {
override fun read(input: InputStream): Iterable<ClassNode> { override fun read(input: InputStream): Iterable<ClassNode> {
ByteArrayOutputStream().use { tempOutput -> ByteArrayOutputStream().use { tempOutput ->
Gzip.createHeaderlessInputStream(input).use { gzipInput -> Gzip.createHeaderlessInputStream(input).use { gzipInput ->

@ -9,7 +9,7 @@ import java.io.OutputStream
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
import java.util.jar.Pack200 import java.util.jar.Pack200
object Pack200LibraryWriter : LibraryWriter { public object Pack200LibraryWriter : LibraryWriter {
override fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>) { override fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>) {
ByteArrayOutputStream().use { tempOutput -> ByteArrayOutputStream().use { tempOutput ->
JarLibraryWriter.write(tempOutput, classPath, classes) JarLibraryWriter.write(tempOutput, classPath, classes)

@ -3,7 +3,7 @@ package dev.openrs2.asm.io
import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.ClassNode
import java.io.InputStream import java.io.InputStream
object PackClassLibraryReader : LibraryReader { public object PackClassLibraryReader : LibraryReader {
override fun read(input: InputStream): Iterable<ClassNode> { override fun read(input: InputStream): Iterable<ClassNode> {
// TODO(gpe): implement // TODO(gpe): implement
return emptyList() return emptyList()

@ -4,7 +4,7 @@ import dev.openrs2.asm.classpath.ClassPath
import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.ClassNode
import java.io.OutputStream import java.io.OutputStream
object PackClassLibraryWriter : LibraryWriter { public object PackClassLibraryWriter : LibraryWriter {
override fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>) { override fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>) {
// TODO(gpe): implement // TODO(gpe): implement
} }

@ -14,7 +14,7 @@ import java.nio.file.Files
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
import java.util.jar.Manifest import java.util.jar.Manifest
class SignedJarLibraryWriter( public class SignedJarLibraryWriter(
private val manifest: Manifest, private val manifest: Manifest,
private val keyStore: Pkcs12KeyStore private val keyStore: Pkcs12KeyStore
) : LibraryWriter { ) : LibraryWriter {

@ -7,8 +7,8 @@ import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.FieldNode import org.objectweb.asm.tree.FieldNode
import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.MethodNode
abstract class Transformer { public abstract class Transformer {
open fun transform(classPath: ClassPath) { public open fun transform(classPath: ClassPath) {
preTransform(classPath) preTransform(classPath)
var changed: Boolean var changed: Boolean

@ -2,7 +2,7 @@ package dev.openrs2.buffer
import io.netty.util.ReferenceCounted import io.netty.util.ReferenceCounted
inline fun <T : ReferenceCounted, R> T.use(block: (T) -> R): R { public inline fun <T : ReferenceCounted, R> T.use(block: (T) -> R): R {
try { try {
return block(this) return block(this)
} finally { } finally {

@ -55,6 +55,12 @@ allprojects {
} }
} }
plugins.withType<KotlinPluginWrapper> {
kotlin {
explicitApi()
}
}
plugins.withType<KotlinterPlugin> { plugins.withType<KotlinterPlugin> {
configure<KotlinterExtension> { configure<KotlinterExtension> {
// see https://github.com/pinterest/ktlint/issues/764 // see https://github.com/pinterest/ktlint/issues/764

@ -4,9 +4,9 @@ import com.github.ajalt.clikt.core.CliktCommand
import com.google.inject.Guice import com.google.inject.Guice
import java.nio.file.Paths import java.nio.file.Paths
fun main(args: Array<String>) = BundleCommand().main(args) public fun main(args: Array<String>): Unit = BundleCommand().main(args)
class BundleCommand : CliktCommand(name = "bundle") { public class BundleCommand : CliktCommand(name = "bundle") {
override fun run() { override fun run() {
val injector = Guice.createInjector(BundlerModule) val injector = Guice.createInjector(BundlerModule)
val bundler = injector.getInstance(Bundler::class.java) val bundler = injector.getInstance(Bundler::class.java)

@ -23,7 +23,7 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class Bundler @Inject constructor( public class Bundler @Inject constructor(
@BundlerQualifier private val transformers: Set<@JvmSuppressWildcards Transformer>, @BundlerQualifier private val transformers: Set<@JvmSuppressWildcards Transformer>,
private val config: Config private val config: Config
) { ) {
@ -39,7 +39,7 @@ class Bundler @Inject constructor(
mainAttributes[PERMISSIONS] = "all-permissions" mainAttributes[PERMISSIONS] = "all-permissions"
} }
fun run(input: Path, output: Path, keyStorePath: Path) { public fun run(input: Path, output: Path, keyStorePath: Path) {
// read input jars/packs // read input jars/packs
logger.info { "Reading input jars" } logger.info { "Reading input jars" }
val unpacker = Library.read("unpackclass", input.resolve("unpackclass.pack"), JarLibraryReader) val unpacker = Library.read("unpackclass", input.resolve("unpackclass.pack"), JarLibraryReader)

@ -18,7 +18,7 @@ import dev.openrs2.bundler.transform.TypoTransformer
import dev.openrs2.conf.ConfigModule import dev.openrs2.conf.ConfigModule
import dev.openrs2.crypto.CryptoModule import dev.openrs2.crypto.CryptoModule
object BundlerModule : AbstractModule() { public object BundlerModule : AbstractModule() {
override fun configure() { override fun configure() {
install(ConfigModule) install(ConfigModule)
install(CryptoModule) install(CryptoModule)

@ -5,4 +5,4 @@ import javax.inject.Qualifier
@Qualifier @Qualifier
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION) @Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION)
annotation class BundlerQualifier public annotation class BundlerQualifier

@ -11,31 +11,31 @@ import java.security.MessageDigest
import java.util.zip.CRC32 import java.util.zip.CRC32
import java.util.zip.Deflater import java.util.zip.Deflater
class Resource( public class Resource(
val source: String, public val source: String,
val destination: String, public val destination: String,
val crc: Int, public val crc: Int,
val digest: ByteArray, public val digest: ByteArray,
val uncompressedSize: Int, public val uncompressedSize: Int,
val content: ByteArray public val content: ByteArray
) { ) {
val sourceWithCrc: String public val sourceWithCrc: String
get() = source.replace(".", "_$crc.") get() = source.replace(".", "_$crc.")
val compressedSize: Int public val compressedSize: Int
get() = content.size get() = content.size
init { init {
require(digest.size == 20) require(digest.size == 20)
} }
fun write(dir: Path) { public fun write(dir: Path) {
val path = dir.resolve(source) val path = dir.resolve(source)
logger.info { "Writing resource $path" } logger.info { "Writing resource $path" }
Files.write(path, content) Files.write(path, content)
} }
companion object { public companion object {
private val logger = InlineLogger() private val logger = InlineLogger()
private fun compress(source: String, destination: String, uncompressed: ByteArray): Resource { private fun compress(source: String, destination: String, uncompressed: ByteArray): Resource {
@ -66,7 +66,7 @@ class Resource(
return Resource(source, destination, crc.value.toInt(), digest.digest(), uncompressed.size, content) return Resource(source, destination, crc.value.toInt(), digest.digest(), uncompressed.size, content)
} }
fun compressLibrary( public fun compressLibrary(
source: String, source: String,
destination: String, destination: String,
classPath: ClassPath, classPath: ClassPath,
@ -85,7 +85,7 @@ class Resource(
return compress(source, destination, uncompressed) return compress(source, destination, uncompressed)
} }
fun compressGlNatives() = listOf( public fun compressGlNatives(): List<List<Resource>> = listOf(
// Windows i386 // Windows i386
listOf( listOf(
compressNative("jaggl_0_0.lib", "jaggl.dll", "windows-i386/jaggl.dll") compressNative("jaggl_0_0.lib", "jaggl.dll", "windows-i386/jaggl.dll")
@ -119,7 +119,7 @@ class Resource(
) )
) )
fun compressMiscNatives() = listOf( public fun compressMiscNatives(): List<Resource> = listOf(
compressNative("jagmisc_0.lib", "jagmisc.dll", "windows-i386/jagmisc.dll"), compressNative("jagmisc_0.lib", "jagmisc.dll", "windows-i386/jagmisc.dll"),
compressNative("jagmisc_1.lib", "jagmisc.dll", "windows-amd64/jagmisc.dll") compressNative("jagmisc_1.lib", "jagmisc.dll", "windows-amd64/jagmisc.dll")
) )

@ -15,7 +15,7 @@ import org.objectweb.asm.tree.MethodNode
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class BufferSizeTransformer : Transformer() { public class BufferSizeTransformer : Transformer() {
private var buffer: MemberRef? = null private var buffer: MemberRef? = null
private var buffersResized = 0 private var buffersResized = 0

@ -12,7 +12,7 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class CachePathTransformer @Inject constructor( public class CachePathTransformer @Inject constructor(
private val config: Config private val config: Config
) : Transformer() { ) : Transformer() {
private var paths = 0 private var paths = 0

@ -12,7 +12,7 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class DomainTransformer @Inject constructor( public class DomainTransformer @Inject constructor(
private val config: Config private val config: Config
) : Transformer() { ) : Transformer() {
private var domains = 0 private var domains = 0

@ -14,7 +14,7 @@ import org.objectweb.asm.tree.MethodNode
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class HostCheckTransformer : Transformer() { public class HostCheckTransformer : Transformer() {
private var hostChecks = 0 private var hostChecks = 0
override fun preTransform(classPath: ClassPath) { override fun preTransform(classPath: ClassPath) {

@ -13,7 +13,7 @@ import org.objectweb.asm.tree.MethodNode
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class LoadLibraryTransformer : Transformer() { public class LoadLibraryTransformer : Transformer() {
private var jnilibs = 0 private var jnilibs = 0
private var amd64Checks = 0 private var amd64Checks = 0
private var sunOsChecks = 0 private var sunOsChecks = 0

@ -15,7 +15,7 @@ import org.objectweb.asm.tree.MethodNode
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class MacResizeTransformer : Transformer() { public class MacResizeTransformer : Transformer() {
private var branchesRemoved = 0 private var branchesRemoved = 0
override fun preTransform(classPath: ClassPath) { override fun preTransform(classPath: ClassPath) {

@ -15,7 +15,7 @@ import org.objectweb.asm.tree.VarInsnNode
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class MemoryAllocationTransformer : Transformer() { public class MemoryAllocationTransformer : Transformer() {
private var usedMemoryExprsZeroed = 0 private var usedMemoryExprsZeroed = 0
override fun preTransform(classPath: ClassPath) { override fun preTransform(classPath: ClassPath) {

@ -12,7 +12,7 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class NameTransformer @Inject constructor( public class NameTransformer @Inject constructor(
private val config: Config private val config: Config
) : Transformer() { ) : Transformer() {
private var names = 0 private var names = 0

@ -22,7 +22,7 @@ import org.objectweb.asm.tree.VarInsnNode
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class PlatformDetectionTransformer : Transformer() { public class PlatformDetectionTransformer : Transformer() {
private var glBlocks = 0 private var glBlocks = 0
private var miscBlocks = 0 private var miscBlocks = 0

@ -12,7 +12,7 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class PublicKeyTransformer @Inject constructor(private val key: RSAPrivateCrtKeyParameters) : Transformer() { public class PublicKeyTransformer @Inject constructor(private val key: RSAPrivateCrtKeyParameters) : Transformer() {
private var exponents = 0 private var exponents = 0
private var moduli = 0 private var moduli = 0

@ -17,7 +17,7 @@ import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.MethodNode
import org.objectweb.asm.tree.TypeInsnNode import org.objectweb.asm.tree.TypeInsnNode
class ResourceTransformer( public class ResourceTransformer(
private val resources: List<Resource>? = null, private val resources: List<Resource>? = null,
private val glResources: List<List<Resource>> = Resource.compressGlNatives(), private val glResources: List<List<Resource>> = Resource.compressGlNatives(),
private val miscResources: List<Resource> = Resource.compressMiscNatives() private val miscResources: List<Resource> = Resource.compressMiscNatives()

@ -14,7 +14,7 @@ import org.objectweb.asm.tree.MethodNode
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class RightClickTransformer : Transformer() { public class RightClickTransformer : Transformer() {
private var metaDownCalls = 0 private var metaDownCalls = 0
override fun preTransform(classPath: ClassPath) { override fun preTransform(classPath: ClassPath) {

@ -10,7 +10,7 @@ import org.objectweb.asm.tree.MethodNode
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class TypoTransformer : Transformer() { public class TypoTransformer : Transformer() {
private var errorsFixed = 0 private var errorsFixed = 0
override fun preTransform(classPath: ClassPath) { override fun preTransform(classPath: ClassPath) {

@ -9,7 +9,7 @@ import java.nio.channels.FileChannel
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
class BufferedFileChannel( public class BufferedFileChannel(
private val channel: FileChannel, private val channel: FileChannel,
readBufferSize: Int, readBufferSize: Int,
writeBufferSize: Int, writeBufferSize: Int,
@ -23,7 +23,7 @@ class BufferedFileChannel(
private val writeBuffer = alloc.buffer(writeBufferSize, writeBufferSize) private val writeBuffer = alloc.buffer(writeBufferSize, writeBufferSize)
private var writePos = -1L private var writePos = -1L
fun read(pos: Long, dest: ByteBuf, len: Int) { public fun read(pos: Long, dest: ByteBuf, len: Int) {
require(pos >= 0) require(pos >= 0)
require(len <= dest.writableBytes()) require(len <= dest.writableBytes())
@ -165,7 +165,7 @@ class BufferedFileChannel(
} }
} }
fun write(pos: Long, src: ByteBuf, len: Int) { public fun write(pos: Long, src: ByteBuf, len: Int) {
require(pos >= 0) require(pos >= 0)
require(len <= src.readableBytes()) require(len <= src.readableBytes())
@ -277,7 +277,7 @@ class BufferedFileChannel(
} }
} }
fun size(): Long { public fun size(): Long {
return size return size
} }

@ -17,7 +17,7 @@ import kotlin.math.min
* A [Store] implementation compatible with the native `main_file_cache.dat2` * A [Store] implementation compatible with the native `main_file_cache.dat2`
* and `main_file_cache.idx*` format used by the client. * and `main_file_cache.idx*` format used by the client.
*/ */
class DiskStore private constructor( public class DiskStore private constructor(
private val root: Path, private val root: Path,
private val data: BufferedFileChannel, private val data: BufferedFileChannel,
private val indexes: Array<BufferedFileChannel?>, private val indexes: Array<BufferedFileChannel?>,
@ -436,7 +436,7 @@ class DiskStore private constructor(
} }
} }
companion object { public companion object {
private const val INDEX_ENTRY_SIZE = 6 private const val INDEX_ENTRY_SIZE = 6
private const val BLOCK_HEADER_SIZE = 8 private const val BLOCK_HEADER_SIZE = 8
@ -460,7 +460,7 @@ class DiskStore private constructor(
return root.resolve("main_file_cache.idx$archive") return root.resolve("main_file_cache.idx$archive")
} }
fun open(root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT): Store { public fun open(root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT): Store {
val data = BufferedFileChannel( val data = BufferedFileChannel(
FileChannel.open(dataPath(root), READ, WRITE), FileChannel.open(dataPath(root), READ, WRITE),
DATA_BUFFER_SIZE, DATA_BUFFER_SIZE,
@ -485,7 +485,7 @@ class DiskStore private constructor(
return DiskStore(root, data, archives, alloc) return DiskStore(root, data, archives, alloc)
} }
fun create(root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT): Store { public fun create(root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT): Store {
Files.createDirectories(root) Files.createDirectories(root)
val data = BufferedFileChannel( val data = BufferedFileChannel(

@ -15,7 +15,7 @@ import java.nio.file.Path
* content-addressable version control systems, such as Git, than the native * content-addressable version control systems, such as Git, than the native
* format used by the client. * format used by the client.
*/ */
class FlatFileStore private constructor( public class FlatFileStore private constructor(
private val root: Path, private val root: Path,
private val alloc: ByteBufAllocator private val alloc: ByteBufAllocator
) : Store { ) : Store {
@ -108,12 +108,12 @@ class FlatFileStore private constructor(
// no-op // no-op
} }
companion object { public companion object {
private val ARCHIVE_NAME = Regex("[1-9][0-9]*") private val ARCHIVE_NAME = Regex("[1-9][0-9]*")
private val GROUP_NAME = Regex("[1-9][0-9]*[.]dat") private val GROUP_NAME = Regex("[1-9][0-9]*[.]dat")
private const val GROUP_EXTENSION = ".dat" private const val GROUP_EXTENSION = ".dat"
fun open(root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT): Store { public fun open(root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT): Store {
if (!Files.isDirectory(root)) { if (!Files.isDirectory(root)) {
throw FileNotFoundException() throw FileNotFoundException()
} }
@ -121,7 +121,7 @@ class FlatFileStore private constructor(
return FlatFileStore(root, alloc) return FlatFileStore(root, alloc)
} }
fun create(root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT): Store { public fun create(root: Path, alloc: ByteBufAllocator = ByteBufAllocator.DEFAULT): Store {
Files.createDirectories(root) Files.createDirectories(root)
return FlatFileStore(root, alloc) return FlatFileStore(root, alloc)
} }

@ -8,8 +8,8 @@ import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufInputStream import io.netty.buffer.ByteBufInputStream
import io.netty.buffer.ByteBufOutputStream import io.netty.buffer.ByteBufOutputStream
object Js5Compression { public object Js5Compression {
fun compress(input: ByteBuf, type: Js5CompressionType, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun compress(input: ByteBuf, type: Js5CompressionType, key: XteaKey = XteaKey.ZERO): ByteBuf {
input.alloc().buffer().use { output -> input.alloc().buffer().use { output ->
output.writeByte(type.ordinal) output.writeByte(type.ordinal)
@ -48,7 +48,7 @@ object Js5Compression {
} }
} }
fun compressBest(input: ByteBuf, enableLzma: Boolean = false, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun compressBest(input: ByteBuf, enableLzma: Boolean = false, key: XteaKey = XteaKey.ZERO): ByteBuf {
var best = compress(input.slice(), Js5CompressionType.NONE, key) var best = compress(input.slice(), Js5CompressionType.NONE, key)
try { try {
for (type in Js5CompressionType.values()) { for (type in Js5CompressionType.values()) {
@ -73,7 +73,7 @@ object Js5Compression {
} }
} }
fun uncompress(input: ByteBuf, key: XteaKey = XteaKey.ZERO): ByteBuf { public fun uncompress(input: ByteBuf, key: XteaKey = XteaKey.ZERO): ByteBuf {
val typeId = input.readUnsignedByte().toInt() val typeId = input.readUnsignedByte().toInt()
val type = Js5CompressionType.fromOrdinal(typeId) val type = Js5CompressionType.fromOrdinal(typeId)
require(type != null) { require(type != null) {

@ -8,13 +8,13 @@ import java.io.OutputStream
import java.util.zip.Deflater import java.util.zip.Deflater
import java.util.zip.GZIPInputStream import java.util.zip.GZIPInputStream
enum class Js5CompressionType { public enum class Js5CompressionType {
NONE, NONE,
BZIP2, BZIP2,
GZIP, GZIP,
LZMA; LZMA;
fun createInputStream(input: InputStream, length: Int): InputStream { public fun createInputStream(input: InputStream, length: Int): InputStream {
return when (this) { return when (this) {
NONE -> input NONE -> input
BZIP2 -> Bzip2.createHeaderlessInputStream(input) BZIP2 -> Bzip2.createHeaderlessInputStream(input)
@ -23,7 +23,7 @@ enum class Js5CompressionType {
} }
} }
fun createOutputStream(output: OutputStream): OutputStream { public fun createOutputStream(output: OutputStream): OutputStream {
return when (this) { return when (this) {
NONE -> output NONE -> output
BZIP2 -> Bzip2.createHeaderlessOutputStream(output) BZIP2 -> Bzip2.createHeaderlessOutputStream(output)
@ -39,8 +39,8 @@ enum class Js5CompressionType {
} }
} }
companion object { public companion object {
fun fromOrdinal(ordinal: Int): Js5CompressionType? { public fun fromOrdinal(ordinal: Int): Js5CompressionType? {
val values = values() val values = values()
return if (ordinal >= 0 && ordinal < values.size) { return if (ordinal >= 0 && ordinal < values.size) {
values[ordinal] values[ordinal]

@ -10,7 +10,7 @@ import java.io.IOException
* A low-level interface for reading and writing raw groups directly to and * A low-level interface for reading and writing raw groups directly to and
* from a collection of JS5 archives. * from a collection of JS5 archives.
*/ */
interface Store : Flushable, Closeable { public interface Store : Flushable, Closeable {
/** /**
* Checks whether an archive exists. * Checks whether an archive exists.
* @param archive the archive ID. * @param archive the archive ID.
@ -18,7 +18,7 @@ interface Store : Flushable, Closeable {
* @throws IllegalArgumentException if the archive ID is out of bounds. * @throws IllegalArgumentException if the archive ID is out of bounds.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun exists(archive: Int): Boolean public fun exists(archive: Int): Boolean
/** /**
* Checks whether a group exists. * Checks whether a group exists.
@ -29,14 +29,14 @@ interface Store : Flushable, Closeable {
* bounds. * bounds.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun exists(archive: Int, group: Int): Boolean public fun exists(archive: Int, group: Int): Boolean
/** /**
* Lists all archives in the store. * Lists all archives in the store.
* @return a sorted list of archive IDs. * @return a sorted list of archive IDs.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun list(): List<Int> public fun list(): List<Int>
/** /**
* Lists all groups in an archive. * Lists all groups in an archive.
@ -47,7 +47,7 @@ interface Store : Flushable, Closeable {
* @throws FileNotFoundException if the archive does not exist. * @throws FileNotFoundException if the archive does not exist.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun list(archive: Int): List<Int> public fun list(archive: Int): List<Int>
/** /**
* Creates an archive. Does nothing if the archive already exists. * Creates an archive. Does nothing if the archive already exists.
@ -55,7 +55,7 @@ interface Store : Flushable, Closeable {
* @throws IllegalArgumentException if the archive ID is out of bounds. * @throws IllegalArgumentException if the archive ID is out of bounds.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun create(archive: Int) public fun create(archive: Int)
/** /**
* Reads a group. * Reads a group.
@ -71,7 +71,7 @@ interface Store : Flushable, Closeable {
* @throws StoreCorruptException if the store is corrupt. * @throws StoreCorruptException if the store is corrupt.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun read(archive: Int, group: Int): ByteBuf public fun read(archive: Int, group: Int): ByteBuf
/** /**
* Writes a group. If the archive does not exist, it is created first. If a * Writes a group. If the archive does not exist, it is created first. If a
@ -87,7 +87,7 @@ interface Store : Flushable, Closeable {
* @throws StoreFullException if the store is full. * @throws StoreFullException if the store is full.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun write(archive: Int, group: Int, buf: ByteBuf) public fun write(archive: Int, group: Int, buf: ByteBuf)
/** /**
* Deletes an archive and all groups contained inside it. Does nothing if * Deletes an archive and all groups contained inside it. Does nothing if
@ -96,7 +96,7 @@ interface Store : Flushable, Closeable {
* @throws IllegalArgumentException if the archive ID is out of bounds. * @throws IllegalArgumentException if the archive ID is out of bounds.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun remove(archive: Int) public fun remove(archive: Int)
/** /**
* Deletes a group. Does nothing if the archive or group does not exist. * Deletes a group. Does nothing if the archive or group does not exist.
@ -106,17 +106,17 @@ interface Store : Flushable, Closeable {
* bounds. * bounds.
* @throws IOException if an underlying I/O error occurs. * @throws IOException if an underlying I/O error occurs.
*/ */
fun remove(archive: Int, group: Int) public fun remove(archive: Int, group: Int)
companion object { public companion object {
/** /**
* The maximum archive ID. * The maximum archive ID.
*/ */
const val MAX_ARCHIVE = 255 public const val MAX_ARCHIVE: Int = 255
/** /**
* The maximum length of a group's contents in bytes. * The maximum length of a group's contents in bytes.
*/ */
const val MAX_GROUP_SIZE = (1 shl 24) - 1 public const val MAX_GROUP_SIZE: Int = (1 shl 24) - 1
} }
} }

@ -2,4 +2,4 @@ package dev.openrs2.cache
import java.io.IOException import java.io.IOException
class StoreCorruptException(message: String) : IOException(message) public class StoreCorruptException(message: String) : IOException(message)

@ -2,4 +2,4 @@ package dev.openrs2.cache
import java.io.IOException import java.io.IOException
class StoreFullException : IOException() public class StoreFullException : IOException()

@ -11,9 +11,9 @@ import dev.openrs2.compress.cli.gzip.GzipCommand
import dev.openrs2.compress.cli.lzma.LzmaCommand import dev.openrs2.compress.cli.lzma.LzmaCommand
import dev.openrs2.compress.cli.lzma.UnlzmaCommand import dev.openrs2.compress.cli.lzma.UnlzmaCommand
fun main(args: Array<String>) = CompressCommand().main(args) public fun main(args: Array<String>): Unit = CompressCommand().main(args)
class CompressCommand : NoOpCliktCommand(name = "compress") { public class CompressCommand : NoOpCliktCommand(name = "compress") {
init { init {
subcommands( subcommands(
Bzip2Command(), Bzip2Command(),

@ -8,7 +8,7 @@ import com.github.ajalt.clikt.parameters.types.inputStream
import com.github.ajalt.clikt.parameters.types.outputStream import com.github.ajalt.clikt.parameters.types.outputStream
import dev.openrs2.compress.bzip2.Bzip2 import dev.openrs2.compress.bzip2.Bzip2
class Bunzip2Command : CliktCommand(name = "bunzip2") { public class Bunzip2Command : CliktCommand(name = "bunzip2") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
private val output by option().outputStream().defaultStdout() private val output by option().outputStream().defaultStdout()

@ -8,7 +8,7 @@ import com.github.ajalt.clikt.parameters.types.inputStream
import com.github.ajalt.clikt.parameters.types.outputStream import com.github.ajalt.clikt.parameters.types.outputStream
import dev.openrs2.compress.bzip2.Bzip2 import dev.openrs2.compress.bzip2.Bzip2
class Bzip2Command : CliktCommand(name = "bzip2") { public class Bzip2Command : CliktCommand(name = "bzip2") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
private val output by option().outputStream().defaultStdout() private val output by option().outputStream().defaultStdout()

@ -12,7 +12,7 @@ import com.github.ajalt.clikt.parameters.types.outputStream
import java.util.zip.Deflater import java.util.zip.Deflater
import java.util.zip.DeflaterOutputStream import java.util.zip.DeflaterOutputStream
class DeflateCommand : CliktCommand(name = "deflate") { public class DeflateCommand : CliktCommand(name = "deflate") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
private val output by option().outputStream().defaultStdout() private val output by option().outputStream().defaultStdout()
private val level by option().int().default(Deflater.BEST_COMPRESSION).validate { private val level by option().int().default(Deflater.BEST_COMPRESSION).validate {

@ -9,7 +9,7 @@ import com.github.ajalt.clikt.parameters.types.outputStream
import java.util.zip.Inflater import java.util.zip.Inflater
import java.util.zip.InflaterInputStream import java.util.zip.InflaterInputStream
class InflateCommand : CliktCommand(name = "inflate") { public class InflateCommand : CliktCommand(name = "inflate") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
private val output by option().outputStream().defaultStdout() private val output by option().outputStream().defaultStdout()

@ -8,7 +8,7 @@ import com.github.ajalt.clikt.parameters.types.inputStream
import com.github.ajalt.clikt.parameters.types.outputStream import com.github.ajalt.clikt.parameters.types.outputStream
import dev.openrs2.compress.gzip.Gzip import dev.openrs2.compress.gzip.Gzip
class GunzipCommand : CliktCommand(name = "gunzip") { public class GunzipCommand : CliktCommand(name = "gunzip") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
private val output by option().outputStream().defaultStdout() private val output by option().outputStream().defaultStdout()

@ -12,7 +12,7 @@ import com.github.ajalt.clikt.parameters.types.outputStream
import dev.openrs2.compress.gzip.Gzip import dev.openrs2.compress.gzip.Gzip
import java.util.zip.Deflater import java.util.zip.Deflater
class GzipCommand : CliktCommand(name = "gzip") { public class GzipCommand : CliktCommand(name = "gzip") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
private val output by option().outputStream().defaultStdout() private val output by option().outputStream().defaultStdout()
private val level by option().int().default(Deflater.BEST_COMPRESSION).validate { private val level by option().int().default(Deflater.BEST_COMPRESSION).validate {

@ -12,7 +12,7 @@ import com.github.ajalt.clikt.parameters.types.outputStream
import dev.openrs2.compress.lzma.Lzma import dev.openrs2.compress.lzma.Lzma
import org.tukaani.xz.LZMA2Options import org.tukaani.xz.LZMA2Options
class LzmaCommand : CliktCommand(name = "lzma") { public class LzmaCommand : CliktCommand(name = "lzma") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
private val output by option().outputStream().defaultStdout() private val output by option().outputStream().defaultStdout()
private val level by option().int().default(LZMA2Options.PRESET_DEFAULT).validate { private val level by option().int().default(LZMA2Options.PRESET_DEFAULT).validate {

@ -10,7 +10,7 @@ import com.github.ajalt.clikt.parameters.types.long
import com.github.ajalt.clikt.parameters.types.outputStream import com.github.ajalt.clikt.parameters.types.outputStream
import dev.openrs2.compress.lzma.Lzma import dev.openrs2.compress.lzma.Lzma
class UnlzmaCommand : CliktCommand(name = "unlzma") { public class UnlzmaCommand : CliktCommand(name = "unlzma") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
private val length by option().long().required() private val length by option().long().required()
private val output by option().outputStream().defaultStdout() private val output by option().outputStream().defaultStdout()

@ -8,15 +8,15 @@ import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.io.SequenceInputStream import java.io.SequenceInputStream
object Bzip2 { public object Bzip2 {
private const val BLOCK_SIZE = 1 private const val BLOCK_SIZE = 1
private val HEADER = byteArrayOf('B'.toByte(), 'Z'.toByte(), 'h'.toByte(), ('0' + BLOCK_SIZE).toByte()) private val HEADER = byteArrayOf('B'.toByte(), 'Z'.toByte(), 'h'.toByte(), ('0' + BLOCK_SIZE).toByte())
fun createHeaderlessInputStream(input: InputStream): InputStream { public fun createHeaderlessInputStream(input: InputStream): InputStream {
return BZip2CompressorInputStream(SequenceInputStream(ByteArrayInputStream(HEADER), input)) return BZip2CompressorInputStream(SequenceInputStream(ByteArrayInputStream(HEADER), input))
} }
fun createHeaderlessOutputStream(output: OutputStream): OutputStream { public fun createHeaderlessOutputStream(output: OutputStream): OutputStream {
return BZip2CompressorOutputStream(SkipOutputStream(output, HEADER.size.toLong()), BLOCK_SIZE) return BZip2CompressorOutputStream(SkipOutputStream(output, HEADER.size.toLong()), BLOCK_SIZE)
} }
} }

@ -8,14 +8,17 @@ import java.io.SequenceInputStream
import java.util.zip.Deflater import java.util.zip.Deflater
import java.util.zip.GZIPInputStream import java.util.zip.GZIPInputStream
object Gzip { public object Gzip {
private val HEADER = byteArrayOf(0x1F, 0x8B.toByte()) private val HEADER = byteArrayOf(0x1F, 0x8B.toByte())
fun createHeaderlessInputStream(input: InputStream): InputStream { public fun createHeaderlessInputStream(input: InputStream): InputStream {
return GZIPInputStream(SequenceInputStream(ByteArrayInputStream(HEADER), input)) return GZIPInputStream(SequenceInputStream(ByteArrayInputStream(HEADER), input))
} }
fun createHeaderlessOutputStream(output: OutputStream, level: Int = Deflater.BEST_COMPRESSION): OutputStream { public fun createHeaderlessOutputStream(
output: OutputStream,
level: Int = Deflater.BEST_COMPRESSION
): OutputStream {
return GzipLevelOutputStream(SkipOutputStream(output, HEADER.size.toLong()), level) return GzipLevelOutputStream(SkipOutputStream(output, HEADER.size.toLong()), level)
} }
} }

@ -3,7 +3,7 @@ package dev.openrs2.compress.gzip
import java.io.OutputStream import java.io.OutputStream
import java.util.zip.GZIPOutputStream import java.util.zip.GZIPOutputStream
class GzipLevelOutputStream(output: OutputStream, level: Int) : GZIPOutputStream(output) { public class GzipLevelOutputStream(output: OutputStream, level: Int) : GZIPOutputStream(output) {
init { init {
def.setLevel(level) def.setLevel(level)
} }

@ -8,12 +8,12 @@ import org.tukaani.xz.LZMAOutputStream
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
object Lzma { public object Lzma {
val BEST_SPEED = LZMA2Options(LZMA2Options.PRESET_MIN) public val BEST_SPEED: LZMA2Options = LZMA2Options(LZMA2Options.PRESET_MIN)
val DEFAULT_COMPRESSION = LZMA2Options(LZMA2Options.PRESET_DEFAULT) public val DEFAULT_COMPRESSION: LZMA2Options = LZMA2Options(LZMA2Options.PRESET_DEFAULT)
val BEST_COMPRESSION = LZMA2Options(LZMA2Options.PRESET_MAX) public val BEST_COMPRESSION: LZMA2Options = LZMA2Options(LZMA2Options.PRESET_MAX)
fun createHeaderlessInputStream(input: InputStream, length: Long): InputStream { public fun createHeaderlessInputStream(input: InputStream, length: Long): InputStream {
val headerInput = LittleEndianDataInputStream(input) val headerInput = LittleEndianDataInputStream(input)
val properties = headerInput.readByte() val properties = headerInput.readByte()
@ -22,7 +22,7 @@ object Lzma {
return LZMAInputStream(input, length, properties, dictionarySize) return LZMAInputStream(input, length, properties, dictionarySize)
} }
fun createHeaderlessOutputStream(output: OutputStream, options: LZMA2Options): OutputStream { public fun createHeaderlessOutputStream(output: OutputStream, options: LZMA2Options): OutputStream {
val headerOutput = LittleEndianDataOutputStream(output) val headerOutput = LittleEndianDataOutputStream(output)
headerOutput.writeByte((options.pb * 5 + options.lp) * 9 + options.lc) headerOutput.writeByte((options.pb * 5 + options.lp) * 9 + options.lc)
headerOutput.writeInt(options.dictSize) headerOutput.writeInt(options.dictSize)

@ -1,6 +1,6 @@
package dev.openrs2.conf package dev.openrs2.conf
data class Config( public data class Config(
val game: String, val game: String,
val operator: String, val operator: String,
val domain: String val domain: String

@ -4,7 +4,7 @@ import com.google.inject.AbstractModule
import com.google.inject.Scopes import com.google.inject.Scopes
import dev.openrs2.yaml.YamlModule import dev.openrs2.yaml.YamlModule
object ConfigModule : AbstractModule() { public object ConfigModule : AbstractModule() {
override fun configure() { override fun configure() {
install(YamlModule) install(YamlModule)

@ -6,7 +6,7 @@ import java.nio.file.Paths
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Provider import javax.inject.Provider
class ConfigProvider @Inject constructor(private val mapper: ObjectMapper) : Provider<Config> { public class ConfigProvider @Inject constructor(private val mapper: ObjectMapper) : Provider<Config> {
override fun get(): Config { override fun get(): Config {
if (Files.notExists(CONFIG_PATH)) { if (Files.notExists(CONFIG_PATH)) {
Files.copy(EXAMPLE_CONFIG_PATH, CONFIG_PATH) Files.copy(EXAMPLE_CONFIG_PATH, CONFIG_PATH)

@ -6,9 +6,9 @@ import com.github.ajalt.clikt.parameters.types.defaultStdin
import com.github.ajalt.clikt.parameters.types.inputStream import com.github.ajalt.clikt.parameters.types.inputStream
import java.util.zip.CRC32 import java.util.zip.CRC32
fun main(args: Array<String>) = Crc32Command().main(args) public fun main(args: Array<String>): Unit = Crc32Command().main(args)
class Crc32Command : CliktCommand(name = "crc32") { public class Crc32Command : CliktCommand(name = "crc32") {
private val input by option().inputStream().defaultStdin() private val input by option().inputStream().defaultStdin()
override fun run() { override fun run() {

@ -4,7 +4,7 @@ import com.google.inject.AbstractModule
import com.google.inject.Scopes import com.google.inject.Scopes
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters
object CryptoModule : AbstractModule() { public object CryptoModule : AbstractModule() {
override fun configure() { override fun configure() {
bind(RSAPrivateCrtKeyParameters::class.java) bind(RSAPrivateCrtKeyParameters::class.java)
.toProvider(RsaKeyProvider::class.java) .toProvider(RsaKeyProvider::class.java)

@ -1,6 +1,6 @@
package dev.openrs2.crypto package dev.openrs2.crypto
class IsaacRandom { public class IsaacRandom {
private var count = 0 private var count = 0
private val rsl: IntArray private val rsl: IntArray
private val mem = IntArray(SIZE) private val mem = IntArray(SIZE)
@ -8,12 +8,12 @@ class IsaacRandom {
private var b = 0 private var b = 0
private var c = 0 private var c = 0
constructor() { public constructor() {
rsl = IntArray(SIZE) rsl = IntArray(SIZE)
init(false) init(false)
} }
constructor(seed: IntArray) { public constructor(seed: IntArray) {
require(seed.size <= SIZE) require(seed.size <= SIZE)
rsl = seed.copyOf(SIZE) rsl = seed.copyOf(SIZE)
@ -257,7 +257,7 @@ class IsaacRandom {
this.a = a this.a = a
} }
fun nextInt(): Int { public fun nextInt(): Int {
if (count-- == 0) { if (count-- == 0) {
isaac() isaac()
count = SIZE - 1 count = SIZE - 1

@ -23,20 +23,20 @@ import java.time.ZoneOffset
import java.util.Date import java.util.Date
import java.util.jar.JarFile import java.util.jar.JarFile
class Pkcs12KeyStore private constructor(privateKeyEntry: KeyStore.PrivateKeyEntry, signerName: String) { public class Pkcs12KeyStore private constructor(privateKeyEntry: KeyStore.PrivateKeyEntry, signerName: String) {
private val signer = JarSigner.Builder(privateKeyEntry) private val signer = JarSigner.Builder(privateKeyEntry)
.signatureAlgorithm("SHA256withRSA") .signatureAlgorithm("SHA256withRSA")
.digestAlgorithm("SHA-256") .digestAlgorithm("SHA-256")
.signerName(signerName) .signerName(signerName)
.build() .build()
fun signJar(input: Path, output: OutputStream) { public fun signJar(input: Path, output: OutputStream) {
JarFile(input.toFile()).use { file -> JarFile(input.toFile()).use { file ->
signer.sign(file, output) signer.sign(file, output)
} }
} }
companion object { public companion object {
private const val ALIAS = "openrs2" private const val ALIAS = "openrs2"
private const val PASSWORD = ALIAS private const val PASSWORD = ALIAS
@ -51,7 +51,7 @@ class Pkcs12KeyStore private constructor(privateKeyEntry: KeyStore.PrivateKeyEnt
private val SHA256_WITH_RSA = AlgorithmIdentifier(PKCSObjectIdentifiers.sha256WithRSAEncryption) private val SHA256_WITH_RSA = AlgorithmIdentifier(PKCSObjectIdentifiers.sha256WithRSAEncryption)
private val SHA256 = AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256) private val SHA256 = AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256)
fun open(path: Path, signerName: String): Pkcs12KeyStore { public fun open(path: Path, signerName: String): Pkcs12KeyStore {
val keyStore = KeyStore.getInstance("PKCS12") val keyStore = KeyStore.getInstance("PKCS12")
if (Files.exists(path)) { if (Files.exists(path)) {
Files.newInputStream(path).use { input -> Files.newInputStream(path).use { input ->

@ -28,7 +28,7 @@ import java.nio.file.Path
import java.security.spec.KeySpec import java.security.spec.KeySpec
import java.security.spec.RSAPrivateCrtKeySpec import java.security.spec.RSAPrivateCrtKeySpec
val RSAPrivateCrtKeyParameters.publicKey public val RSAPrivateCrtKeyParameters.publicKey: RSAKeyParameters
get() = RSAKeyParameters(false, modulus, publicExponent) get() = RSAKeyParameters(false, modulus, publicExponent)
private fun ByteBuf.toBigInteger(): BigInteger { private fun ByteBuf.toBigInteger(): BigInteger {
@ -40,19 +40,19 @@ private fun BigInteger.toByteBuf(): ByteBuf {
return Unpooled.wrappedBuffer(toByteArray()) return Unpooled.wrappedBuffer(toByteArray())
} }
fun ByteBuf.rsaEncrypt(key: RSAKeyParameters): ByteBuf { public fun ByteBuf.rsaEncrypt(key: RSAKeyParameters): ByteBuf {
return Rsa.encrypt(toBigInteger(), key).toByteBuf() return Rsa.encrypt(toBigInteger(), key).toByteBuf()
} }
fun ByteBuf.rsaDecrypt(key: RSAKeyParameters): ByteBuf { public fun ByteBuf.rsaDecrypt(key: RSAKeyParameters): ByteBuf {
return Rsa.decrypt(toBigInteger(), key).toByteBuf() return Rsa.decrypt(toBigInteger(), key).toByteBuf()
} }
fun RSAPrivateCrtKeyParameters.toKeySpec(): KeySpec { public fun RSAPrivateCrtKeyParameters.toKeySpec(): KeySpec {
return RSAPrivateCrtKeySpec(modulus, publicExponent, exponent, p, q, dp, dq, qInv) return RSAPrivateCrtKeySpec(modulus, publicExponent, exponent, p, q, dp, dq, qInv)
} }
object Rsa { public object Rsa {
private const val PUBLIC_KEY = "PUBLIC KEY" private const val PUBLIC_KEY = "PUBLIC KEY"
private const val PRIVATE_KEY = "PRIVATE KEY" private const val PRIVATE_KEY = "PRIVATE KEY"
@ -66,14 +66,14 @@ object Rsa {
* The maximum output length of RSA encryption is the key size plus one, so * The maximum output length of RSA encryption is the key size plus one, so
* the maximum key size supported by the client is 126 bytes - or 1008 bits. * the maximum key size supported by the client is 126 bytes - or 1008 bits.
*/ */
const val CLIENT_KEY_LENGTH = 1008 public const val CLIENT_KEY_LENGTH: Int = 1008
const val JAR_KEY_LENGTH = 2048 public const val JAR_KEY_LENGTH: Int = 2048
// 1 in 2^80 // 1 in 2^80
private const val CERTAINTY = 80 private const val CERTAINTY = 80
fun generateKeyPair(length: Int): Pair<RSAKeyParameters, RSAPrivateCrtKeyParameters> { public fun generateKeyPair(length: Int): Pair<RSAKeyParameters, RSAPrivateCrtKeyParameters> {
val generator = RSAKeyPairGenerator() val generator = RSAKeyPairGenerator()
generator.init(RSAKeyGenerationParameters(F4, secureRandom, length, CERTAINTY)) generator.init(RSAKeyGenerationParameters(F4, secureRandom, length, CERTAINTY))
@ -81,7 +81,7 @@ object Rsa {
return Pair(keyPair.public as RSAKeyParameters, keyPair.private as RSAPrivateCrtKeyParameters) return Pair(keyPair.public as RSAKeyParameters, keyPair.private as RSAPrivateCrtKeyParameters)
} }
fun encrypt(plaintext: BigInteger, key: RSAKeyParameters): BigInteger { public fun encrypt(plaintext: BigInteger, key: RSAKeyParameters): BigInteger {
require(!key.isPrivate) require(!key.isPrivate)
return plaintext.modPow(key.exponent, key.modulus) return plaintext.modPow(key.exponent, key.modulus)
} }
@ -100,7 +100,7 @@ object Rsa {
} }
} }
fun decrypt(ciphertext: BigInteger, key: RSAKeyParameters): BigInteger { public fun decrypt(ciphertext: BigInteger, key: RSAKeyParameters): BigInteger {
require(key.isPrivate) require(key.isPrivate)
if (key is RSAPrivateCrtKeyParameters) { if (key is RSAPrivateCrtKeyParameters) {
@ -137,7 +137,7 @@ object Rsa {
} }
} }
fun readPublicKey(path: Path): RSAKeyParameters { public fun readPublicKey(path: Path): RSAKeyParameters {
val der = readSinglePemObject(path, PUBLIC_KEY) val der = readSinglePemObject(path, PUBLIC_KEY)
val spki = SubjectPublicKeyInfo.getInstance(der) val spki = SubjectPublicKeyInfo.getInstance(der)
@ -147,12 +147,12 @@ object Rsa {
return RSAKeyParameters(false, key.modulus, key.publicExponent) return RSAKeyParameters(false, key.modulus, key.publicExponent)
} }
fun writePublicKey(path: Path, key: RSAKeyParameters) { public fun writePublicKey(path: Path, key: RSAKeyParameters) {
val spki = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(key) val spki = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(key)
return writeSinglePemObject(path, PUBLIC_KEY, spki.encoded) return writeSinglePemObject(path, PUBLIC_KEY, spki.encoded)
} }
fun readPrivateKey(path: Path): RSAPrivateCrtKeyParameters { public fun readPrivateKey(path: Path): RSAPrivateCrtKeyParameters {
val der = readSinglePemObject(path, PRIVATE_KEY) val der = readSinglePemObject(path, PRIVATE_KEY)
val pki = PrivateKeyInfo.getInstance(der) val pki = PrivateKeyInfo.getInstance(der)
@ -171,7 +171,7 @@ object Rsa {
) )
} }
fun writePrivateKey(path: Path, key: RSAKeyParameters) { public fun writePrivateKey(path: Path, key: RSAKeyParameters) {
val pki = PrivateKeyInfoFactory.createPrivateKeyInfo(key) val pki = PrivateKeyInfoFactory.createPrivateKeyInfo(key)
return writeSinglePemObject(path, PRIVATE_KEY, pki.encoded) return writeSinglePemObject(path, PRIVATE_KEY, pki.encoded)
} }

@ -5,7 +5,7 @@ import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
import javax.inject.Provider import javax.inject.Provider
class RsaKeyProvider : Provider<RSAPrivateCrtKeyParameters> { public class RsaKeyProvider : Provider<RSAPrivateCrtKeyParameters> {
override fun get(): RSAPrivateCrtKeyParameters { override fun get(): RSAPrivateCrtKeyParameters {
return if (Files.exists(PATH)) { return if (Files.exists(PATH)) {
Rsa.readPrivateKey(PATH) Rsa.readPrivateKey(PATH)

@ -4,5 +4,5 @@ import java.security.SecureRandom
private val threadLocal = ThreadLocal.withInitial { SecureRandom() } private val threadLocal = ThreadLocal.withInitial { SecureRandom() }
val secureRandom: SecureRandom public val secureRandom: SecureRandom
get() = threadLocal.get() get() = threadLocal.get()

@ -1,6 +1,6 @@
package dev.openrs2.crypto package dev.openrs2.crypto
class Whirlpool { public class Whirlpool {
private val bitLength = ByteArray(32) private val bitLength = ByteArray(32)
private val buffer = ByteArray(64) private val buffer = ByteArray(64)
private var bufferBits = 0 private var bufferBits = 0
@ -67,7 +67,7 @@ class Whirlpool {
} }
} }
fun NESSIEinit() { public fun NESSIEinit() {
bitLength.fill(0) bitLength.fill(0)
bufferBits = 0 bufferBits = 0
bufferPos = 0 bufferPos = 0
@ -75,7 +75,7 @@ class Whirlpool {
hash.fill(0) hash.fill(0)
} }
fun NESSIEadd(source: ByteArray, bits: Long) { public fun NESSIEadd(source: ByteArray, bits: Long) {
var sourceBits = bits var sourceBits = bits
var sourcePos = 0 var sourcePos = 0
val sourceGap = (8 - (sourceBits.toInt() and 7)) and 7 val sourceGap = (8 - (sourceBits.toInt() and 7)) and 7
@ -138,7 +138,7 @@ class Whirlpool {
} }
} }
fun NESSIEfinalize(digest: ByteArray) { public fun NESSIEfinalize(digest: ByteArray) {
buffer[bufferPos] = (buffer[bufferPos].toInt() or (0x80 ushr (bufferBits and 7))).toByte() buffer[bufferPos] = (buffer[bufferPos].toInt() or (0x80 ushr (bufferBits and 7))).toByte()
bufferPos++ bufferPos++
@ -173,7 +173,7 @@ class Whirlpool {
} }
} }
companion object { public companion object {
private const val DIGESTBITS = 512 private const val DIGESTBITS = 512
private const val DIGESTBYTES = DIGESTBITS ushr 3 private const val DIGESTBYTES = DIGESTBITS ushr 3
private const val R = 10 private const val R = 10
@ -248,7 +248,7 @@ class Whirlpool {
} }
} }
fun whirlpool(data: ByteArray, off: Int = 0, len: Int = data.size): ByteArray { public fun whirlpool(data: ByteArray, off: Int = 0, len: Int = data.size): ByteArray {
val source: ByteArray val source: ByteArray
if (off <= 0) { if (off <= 0) {
source = data source = data

@ -7,20 +7,20 @@ private const val ROUNDS = 32
private const val BLOCK_SIZE = 8 private const val BLOCK_SIZE = 8
private const val BLOCK_SIZE_MASK = BLOCK_SIZE - 1 private const val BLOCK_SIZE_MASK = BLOCK_SIZE - 1
class XteaKey( public class XteaKey(
private val k0: Int, private val k0: Int,
private val k1: Int, private val k1: Int,
private val k2: Int, private val k2: Int,
private val k3: Int private val k3: Int
) { ) {
val isZero: Boolean public val isZero: Boolean
get() = k0 == 0 && k1 == 0 && k2 == 0 && k3 == 0 get() = k0 == 0 && k1 == 0 && k2 == 0 && k3 == 0
fun toIntArray(): IntArray { public fun toIntArray(): IntArray {
return intArrayOf(k0, k1, k2, k3) return intArrayOf(k0, k1, k2, k3)
} }
fun toHex(): String { public fun toHex(): String {
return Integer.toUnsignedString(k0, 16).padStart(8, '0') + return Integer.toUnsignedString(k0, 16).padStart(8, '0') +
Integer.toUnsignedString(k1, 16).padStart(8, '0') + Integer.toUnsignedString(k1, 16).padStart(8, '0') +
Integer.toUnsignedString(k2, 16).padStart(8, '0') + Integer.toUnsignedString(k2, 16).padStart(8, '0') +
@ -31,16 +31,16 @@ class XteaKey(
return toHex() return toHex()
} }
companion object { public companion object {
val ZERO = XteaKey(0, 0, 0, 0) public val ZERO: XteaKey = XteaKey(0, 0, 0, 0)
fun fromIntArray(a: IntArray): XteaKey { public fun fromIntArray(a: IntArray): XteaKey {
require(a.size == 4) require(a.size == 4)
return XteaKey(a[0], a[1], a[2], a[3]) return XteaKey(a[0], a[1], a[2], a[3])
} }
fun fromHex(s: String): XteaKey { public fun fromHex(s: String): XteaKey {
require(s.length == 32) require(s.length == 32)
val k0 = Integer.parseUnsignedInt(s, 0, 8, 16) val k0 = Integer.parseUnsignedInt(s, 0, 8, 16)
@ -53,7 +53,7 @@ class XteaKey(
} }
} }
fun ByteBuf.xteaEncrypt(index: Int, length: Int, key: XteaKey) { public fun ByteBuf.xteaEncrypt(index: Int, length: Int, key: XteaKey) {
val k = key.toIntArray() val k = key.toIntArray()
val end = index + (length and BLOCK_SIZE_MASK.inv()) val end = index + (length and BLOCK_SIZE_MASK.inv())
@ -73,7 +73,7 @@ fun ByteBuf.xteaEncrypt(index: Int, length: Int, key: XteaKey) {
} }
} }
fun ByteBuf.xteaDecrypt(index: Int, length: Int, key: XteaKey) { public fun ByteBuf.xteaDecrypt(index: Int, length: Int, key: XteaKey) {
val k = key.toIntArray() val k = key.toIntArray()
val end = index + (length and BLOCK_SIZE_MASK.inv()) val end = index + (length and BLOCK_SIZE_MASK.inv())

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save