Skip to content

Commit

Permalink
fix(#8): file path check, pack.mcmeta check
Browse files Browse the repository at this point in the history
  • Loading branch information
iceice666 committed May 4, 2024
1 parent 07516da commit 5beffbc
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 38 deletions.
5 changes: 5 additions & 0 deletions src/main/java/net/iceice666/resourcepackserver/Mod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents.ServerStarted
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents.ServerStopping
import net.fabricmc.loader.api.FabricLoader
import net.minecraft.command.CommandRegistryAccess
import net.minecraft.server.command.CommandManager.RegistrationEnvironment
import net.minecraft.server.command.ServerCommandSource
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.nio.file.Path

class Mod : DedicatedServerModInitializer {
override fun onInitializeServer() {
Expand All @@ -27,5 +29,8 @@ class Mod : DedicatedServerModInitializer {

@JvmField
val LOGGER: Logger = LoggerFactory.getLogger("resourcepack-server")

@JvmField
val GAME_DIR: Path = FabricLoader.getInstance().gameDir
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ package net.iceice666.resourcepackserver
import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpHandler
import com.sun.net.httpserver.HttpServer
import net.iceice666.resourcepackserver.Mod.Companion.GAME_DIR
import net.iceice666.resourcepackserver.lib.ConfigLoader
import org.slf4j.Logger
import java.io.*
import java.net.InetSocketAddress
import java.net.URL
import java.net.URLConnection
import java.nio.file.Paths
import java.security.MessageDigest
import java.util.*
import java.util.zip.ZipFile
import kotlin.io.path.isReadable


// Object declaration for a singleton pattern that manages a resource pack file server.
Expand All @@ -28,6 +32,9 @@ object ResourcePackFileServer {
// resolved
private var resPath = ""

private val gameAbsDir = GAME_DIR.toAbsolutePath()
.toString().removeSuffix(".")

// Getter for the server path.
@JvmStatic
fun getOriginPath(): String = originPath
Expand All @@ -43,77 +50,106 @@ object ResourcePackFileServer {
fun isServerRunning(): Boolean = server != null

// Setter for the path of the resource pack, with string normalization.
fun setPath(location: String) {
path = location.trim()
resPath = path

if (path.startsWith("http://") || path.startsWith("https://")) {
fun setPath(location: String): String {
val tmpPath = location.trim()
// Nothing changed, return
if (originPath == tmpPath) return "Nothing changed."

// A remote source
if (tmpPath.startsWith("http://") || tmpPath.startsWith("https://")) {
try {
downloadFile(resPath, "tmpfile-res.zip")
resPath = "tmpfile-res.zip"
} catch (e: IOException) {
LOGGER.error("Failed to download file", e)
return
return "Failed to download file: \n" + e.message
}
resPath = "tmpfile-res.zip"
} else {
val tmpPath = Paths.get(tmpPath)
if (!tmpPath.toAbsolutePath().startsWith(gameAbsDir)) {
return "Cannot resolve the file path.\n" +
"Please ensure the file is under the game directory(${
gameAbsDir
})\n" +
"and ends with '.zip'."
}

if (!tmpPath.isReadable()) {
return "Cannot read the file.\n" +
"Please ensure the file exists and is readable."
}

resPath = tmpPath.toString()
}

if (!containsPackMcmeta()) {
return "File is not a valid resource pack."
}

calculateSha1(resPath)
return calculateSha1()

}

// Calculates the SHA-1 checksum of the file at the given path.
fun calculateSha1(path: String = resPath) {
try {
FileInputStream(path).use { fis ->
val sha1Digest = MessageDigest.getInstance("SHA-1")
val buffer = ByteArray(1024)
var bytesRead: Int
while (fis.read(buffer).also { bytesRead = it } != -1) {
sha1Digest.update(buffer, 0, bytesRead)
}
val sha1Hash = sha1Digest.digest()
sha1 = sha1Hash.joinToString("") { "%02x".format(it) }
LOGGER.info("Path of resourcepack is $path")
LOGGER.info("SHA-1 of server resourcepack is $sha1")
private fun containsPackMcmeta(path: String = resPath): Boolean {
val zipFile = ZipFile(path)
val entries = zipFile.entries()

var res = false

while (entries.hasMoreElements()) {
if ("pack.mcmeta" == entries.nextElement().name) {
res = true
break
}
} catch (e: FileNotFoundException) {
LOGGER.error(
"""
Resourcepack not found.
Please check your config file or run the command '/rps set' to set the correct resourcepack.
""".trimIndent()
)
} catch (e: Exception) {
LOGGER.error("An error occurred while calculating SHA-1: ${e.message}")
}

zipFile.close()

return res
}

// Calculates the SHA-1 checksum of the file at the given path.
fun calculateSha1(path: String = resPath): String {

val fis = FileInputStream(path)
val sha1Digest = MessageDigest.getInstance("SHA-1")
val buffer = ByteArray(1024)
var bytesRead: Int

while (fis.read(buffer).also { bytesRead = it } != -1) {
sha1Digest.update(buffer, 0, bytesRead)
}

val sha1Hash = sha1Digest.digest()
sha1 = sha1Hash.joinToString("") { "%02x".format(it) }

return "Path of resourcepack is $path\n" +
"SHA-1 of server resourcepack is $sha1"

}

// Starts the HTTP server if needed.
fun start(force: Boolean = false) {
if (!force && !CONFIG.enabled) {

LOGGER.info("Resourcepack server is disabled")
return

}
val port = CONFIG.serverPort

try {
val port = CONFIG.serverPort
server = HttpServer.create(InetSocketAddress(port), 0).apply {
createContext("/", FileHandler())
executor = null // Use the default executor
start()
}
LOGGER.info("Resourcepack server is running on port $port")

} catch (e: IOException) {
LOGGER.error("Failed to start file server", e)
return
}

setPath(CONFIG.path)

LOGGER.info("Resourcepack server is running on port $port")
val msg = setPath(CONFIG.path)
LOGGER.info(msg)


}
Expand Down Expand Up @@ -145,6 +181,7 @@ fun downloadFile(fileUrl: String, destinationPath: String) {
}
}
}

// Handler class that responds to HTTP requests with the resource pack file.
internal class FileHandler : HttpHandler {
@Throws(IOException::class)
Expand Down

0 comments on commit 5beffbc

Please sign in to comment.