Advanced-Portals/build.gradle
Sekwah 8f29d203e2 fix!: disable proxy detection to avoid vulnerabilities (see full commit for more info)
If you are using 1.12 or lower you are unaffected as the features causing this issue were not implemented back then.

Thanks to rooter.rs for notifying me of these issues as well as helping code and test a fix for this.

Velocity was unaffected by this issue if you had the plugin on the proxy though due to the likelihood that may not be the case I have decided to disable this for everyone by default

If you are on bungee you will 100% want to update to this version right away.

For a full writeup by roote.rs see https://roote.rs/posts/advancedportals/
2024-07-27 23:41:33 +01:00

424 lines
14 KiB
Groovy

import com.google.gson.Gson
import org.apache.commons.codec.Charsets
import org.apache.http.HttpEntity
import org.apache.http.HttpResponse
import org.apache.http.client.HttpClient
import org.apache.http.client.config.CookieSpecs
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.impl.client.HttpClients
import java.util.regex.Matcher
import java.util.regex.Pattern
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import java.nio.file.StandardOpenOption
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
mavenCentral()
mavenLocal()
jcenter()
}
dependencies {
classpath "org.apache.httpcomponents:httpmime:4.5.14"
classpath "com.google.code.gson:gson:2.10.1"
classpath "org.apache.httpcomponents:httpclient:4.5.14"
}
}
plugins {
id 'dev.s7a.gradle.minecraft.server' version '1.2.0'
id 'net.researchgate.release' version '2.8.1'
}
apply plugin: 'java'
apply plugin: 'idea'
def branch = System.getenv("GITHUB_REF");
if (branch != null) {
branch = branch.replace('refs/heads/', '')
}
def isCanary = version.toString().contains('canary')
group = 'com.sekwah.advancedportals'
description = ""
sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
String getPluginData(String tag) {
File file = file("src/main/resources/plugin.yml")
String version = "notfound"
file.readLines("UTF-8").each { String line ->
line = line.trim()
if (line.startsWith(tag)) {
version = line.substring(tag.length() + 2, line.length())
}
}
println "Advanced Portals v" + version
return version
}
configurations {
// configuration that holds jars to copy into lib
includeLibs
}
repositories {
maven { url "https://repo.maven.apache.org/maven2" }
maven { url "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url "https://nexus.velocitypowered.com/repository/maven-public/" }
maven { url 'https://papermc.io/repo/repository/maven-public/' }
maven { url 'https://maven.enginehub.org/repo/' } // WorldEdit
}
// includeLibs just says to include the library in the final jar
dependencies {
//implementation "org.bukkit:bukkit:1.16.1-R0.1-SNAPSHOT"
implementation "org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT"
implementation "net.md-5:bungeecord-api:1.16-R0.4"
implementation "com.velocitypowered:velocity-api:3.1.1"
annotationProcessor "com.velocitypowered:velocity-api:3.1.1"
implementation "io.netty:netty-all:4.1.91.Final"
compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
implementation "com.sk89q.worldedit:worldedit-bukkit:7.2.14"
//compile fileTree(dir: 'libs', include: ['*.jar'])
}
/** For pre-releases and testers to be able to try the latest commits if they want.
* If the builds start exceeding 8MB then we may want to upload to s3 instead and periodically clear.
* TODO possibly add a task that announces when builds are made?
* Though add a note that it may take a while for Curse to approve the files.
*/
task discordupload {
dependsOn(jar)
doLast {
String discordWebhook = System.getenv("DISCORD_WEBHOOK")
if (discordWebhook != null) {
println("Logging Into Discord")
CloseableHttpClient httpClient = HttpClients.createDefault()
HttpPost uploadFile = new HttpPost(discordWebhook)
MultipartEntityBuilder builder = MultipartEntityBuilder.create()
if (isCanary) {
builder.addTextBody("content", "New canary Build")
} else {
builder.addTextBody("content", "New release build\n\n" +
"Current Features: <${project.github}/blob/${branch}/CHANGELOG.md>")
}
builder.addBinaryBody("file", file(jar.archiveFile).newInputStream(), ContentType.APPLICATION_OCTET_STREAM, jar.archiveName)
HttpEntity multipart = builder.build()
uploadFile.setEntity(multipart)
CloseableHttpResponse response = httpClient.execute(uploadFile)
response.getEntity()
println("Posted build")
} else {
println("Discord webhook unspecified")
}
}
}
minecraftServerConfig {
//jarUrl.set('https://download.getbukkit.org/spigot/spigot-1.19.3.jar')
jarUrl.set('https://api.papermc.io/v2/projects/paper/versions/1.19.3/builds/381/downloads/paper-1.19.3-381.jar')
jvmArgument = ["-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005", "-DIReallyKnowWhatIAmDoingISwear=true"]
}
String getValueFromCurseAPI(apiKey, endpoint) {
String API_BASE_URL = 'https://minecraft.curseforge.com'
Gson gson = new Gson()
HttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
HttpGet get = new HttpGet(API_BASE_URL + endpoint)
get.setHeader('X-Api-Token', apiKey)
HttpResponse response = client.execute(get)
int statusCode = response.statusLine.statusCode
if (statusCode == 200) {
byte[] data = response.entity.content.bytes
return new String(data, Charsets.UTF_8)
} else {
if (response.getFirstHeader('content-type').value.contains('json')) {
InputStreamReader reader = new InputStreamReader(response.entity.content)
reader.close()
throw new RuntimeException("[CurseForge] Error")
} else {
throw new RuntimeException("[CurseForge] HTTP Error Code $response.statusLine.statusCode: $response.statusLine.reasonPhrase")
}
}
return ""
}
/**
* Upload a single file (in case you also want to upload the other files like source n stuff)
* @param json
* @param file
* @return
* @throws IOException
* @throws URISyntaxException
*/
UploadResponse uploadFile(Metadata metadata, File file, String apiKey, Gson gson) throws IOException, URISyntaxException {
String API_BASE_URL = 'https://minecraft.curseforge.com'
String UPLOAD_URL = "/api/projects/%s/upload-file"
// Upload
// Important info
String uploadUrl = String.format(API_BASE_URL + UPLOAD_URL, project.curse_project_id)
HttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
HttpPost post = new HttpPost(uploadUrl)
post.setHeader('X-Api-Token', apiKey)
// https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api
post.setEntity(MultipartEntityBuilder.create()
.addTextBody('metadata', gson.toJson(metadata), ContentType.APPLICATION_JSON)
.addBinaryBody('file', file)
.build())
HttpResponse response = client.execute(post)
InputStreamReader reader = new InputStreamReader(response.entity.content)
UploadResponse uploadResponse = gson.fromJson(reader, UploadResponse)
reader.close()
return uploadResponse
}
class GameVersion {
int id
int gameVersionTypeID
String name
String slug
}
/**
* As described here https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api
*/
class Metadata {
String changelog
String changelogType
int[] gameVersions
String releaseType
}
class UploadResponse {
int id;
}
// Based on https://github.com/matthewprenger/CurseGradle as it didnt support Bukkit uploads at the time.
task curseforge {
dependsOn(jar)
doLast {
String apiKey = null
if (System.getenv("CURSE_API") != null) {
apiKey = System.getenv("CURSE_API")
}
if (apiKey != null) {
Gson gson = new Gson()
//String VERSION_TYPES_URL = "/api/game/version-types"
int gameVersionTypeID = 1
String VERSION_URL = "/api/game/versions"
println("Uploading to CurseForge")
// Get game versions
String gameVersionsString = getValueFromCurseAPI(apiKey, VERSION_URL)
GameVersion[] gameVersions = gson.fromJson(gameVersionsString, GameVersion[].class)
def versions = gameVersions.findAll { it.gameVersionTypeID == gameVersionTypeID }
String[] supportedVersions = [
"1.18",
"1.17",
"1.16",
"1.15",
"1.14",
"1.13"
]
def supportedGameVersions = versions.findAll { supportedVersions.contains(it.name) }
int[] supportedGameVersionIds = supportedGameVersions.collect { it.id }.toArray()
println("Supported Version Id's ${supportedGameVersionIds}")
Metadata uploadMetadata = new Metadata();
uploadMetadata.changelog = "${project.github}/blob/${branch}/CHANGELOG.md"
uploadMetadata.changelogType = "markdown"
uploadMetadata.releaseType = "release"
uploadMetadata.gameVersions = supportedGameVersionIds
def uploadId = uploadFile(uploadMetadata, file(jar.archiveFile), apiKey, gson)
println("Uploaded with ID: ${uploadId.id}")
println("Published build")
} else {
println("Discord webhook unspecified")
}
}
// id = project.curse_project_id
// // TODO add code to reference this but also cut the latest change logs in for the files
// changelogType = 'markdown'
// releaseType = 'release'
}
/**
* Will build then copy it to the minecraft server folder for use with the launch task and dev tools plugin
*/
tasks.register('copyPlugin') {
dependsOn(build)
doLast {
copy {
def sourceFilePath = Paths.get("$buildDir/libs/Advanced-Portals-${getVersion()}.jar")
def destinationFilePath = Paths.get("$buildDir/MinecraftServer/plugins/Advanced-Portals.jar")
println "Handling file: $destinationFilePath"
byte[] newContent = Files.readAllBytes(sourceFilePath)
if (Files.exists(destinationFilePath)) {
println "File exists. Overwriting with new binary content."
Files.write(destinationFilePath, newContent, StandardOpenOption.TRUNCATE_EXISTING)
} else {
println "File does not exist. Copying from source."
Files.copy(sourceFilePath, destinationFilePath, StandardCopyOption.REPLACE_EXISTING)
}
}
}
}
// Set SPIGOT_LOC to the location of your server and SPIGOT_JAR as the name of the jar file in the server you want to run
// DIReallyKnowWhatIAmDoingISwear is to remove the stupid pause spigot has at the start
task runJar() {
doLast {
if (System.env.MC_SERVER_LOC == null || System.env.MC_SERVER_JAR == null) {
throw new Exception('You must set the server location and jar to use MC_SERVER_LOC and MC_SERVER_JAR')
}
javaexec {
main "-jar"
args "${System.env.MC_SERVER_LOC}\\${System.env.MC_SERVER_JAR}.jar"
jvmArgs = ["-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005", "-DIReallyKnowWhatIAmDoingISwear=true"]
workingDir "${System.env.MC_SERVER_LOC}"
}
}
}
task publish {
doLast {
println "This is a dummy task to run others for version: ${version}"
}
}
// https://github.com/researchgate/gradle-release
// Only other plugin I can find using auto & gradle https://github.com/intuit/hooks
release {
failOnPublishNeeded = false
failOnSnapshotDependencies = false
git {
requireBranch = ''
}
// Disable tasks because something we have is causing -x to be ignored
createReleaseTag.enabled = false
preTagCommit.enabled = false
commitNewVersion.enabled = false
}
task cleanbuildfolder {
doFirst {
println "Cleaning up previous builds (to stop publishing old ones by mistake)"
project.delete(files("${buildDir}/libs"))
}
}
void updateFileVersion(String fileLoc, Pattern pattern, Closure<String> stringClosure) {
File file = new File(projectDir, fileLoc)
Matcher m = pattern.matcher(file.text)
if (m.find()) {
def newVersion = stringClosure.call(m)
println "Replacing ${pattern.toString()} in ${fileLoc} with '${newVersion}'"
file.text = file.text.replaceAll(pattern, newVersion)
}
}
// Just to keep all numbers the same (as they are dotted all over the place)
task updateVersionNumbers {
doFirst {
def versionRegex = ~/(\nversion:\s)([0-9.-]+)/
def velocityVersionRegex = ~/(\sversion\s=\s")([0-9.-]+)("\))/
updateFileVersion("src/main/resources/bungee.yml", versionRegex,
{ Matcher m ->
return "${m.group(1)}${getVersion()}"
})
updateFileVersion("src/main/resources/plugin.yml", versionRegex,
{ Matcher m ->
return "${m.group(1)}${getVersion()}"
})
updateFileVersion("src/main/java/com/sekwah/advancedportals/velocity/AdvancedPortalsPlugin.java",
velocityVersionRegex,
{ Matcher m ->
return "${m.group(1)}${getVersion()}${m.group(3)}"
})
}
}
updateVersion.finalizedBy 'updateVersionNumbers'
compileJava.dependsOn 'cleanbuildfolder'
// Publish rules
// Current behavior seems to be canary or release. Though pre-releases may break this pattern.
publish.dependsOn 'build'
publish.finalizedBy 'discordupload'
if (!isCanary) {
publish.finalizedBy 'curseforge'
}