Remove HTTPS support (for now) and fix issues on 1.17
This commit is contained in:
parent
71d1a652b4
commit
51396cd595
6 changed files with 13 additions and 434 deletions
|
@ -3,7 +3,7 @@ main: buttondevteam.website.ButtonWebsiteModule
|
||||||
version: 4.0
|
version: 4.0
|
||||||
author: NorbiPeti
|
author: NorbiPeti
|
||||||
depend:
|
depend:
|
||||||
- ThorpeCore
|
- Chroma-Core
|
||||||
commands:
|
commands:
|
||||||
login:
|
login:
|
||||||
aliases: [web, weblogin, website]
|
aliases: [web, weblogin, website]
|
13
pom.xml
13
pom.xml
|
@ -27,8 +27,8 @@
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.3</version>
|
<version>3.3</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.8</source>
|
<source>10</source>
|
||||||
<target>1.8</target>
|
<target>10</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -111,17 +111,10 @@
|
||||||
<version>3.20.0-GA</version>
|
<version>3.20.0-GA</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-io</groupId>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
<version>1.3.2</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.TBMCPlugins.ChromaCore</groupId>
|
<groupId>com.github.TBMCPlugins.ChromaCore</groupId>
|
||||||
<artifactId>Chroma-Core</artifactId>
|
<artifactId>Chroma-Core</artifactId>
|
||||||
<version>${branch}-SNAPSHOT</version>
|
<version>v1.0.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.shredzone.acme4j/acme4j-client -->
|
<!-- https://mvnrepository.com/artifact/org.shredzone.acme4j/acme4j-client -->
|
||||||
|
|
|
@ -1,318 +0,0 @@
|
||||||
/*
|
|
||||||
* acme4j - Java ACME client
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Richard "Shred" Körber
|
|
||||||
* http://acme4j.shredzone.org
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*/ //Modified
|
|
||||||
package buttondevteam.website;
|
|
||||||
|
|
||||||
import buttondevteam.lib.TBMCCoreAPI;
|
|
||||||
import buttondevteam.website.page.AcmeChallengePage;
|
|
||||||
import org.shredzone.acme4j.*;
|
|
||||||
import org.shredzone.acme4j.challenge.Challenge;
|
|
||||||
import org.shredzone.acme4j.challenge.Http01Challenge;
|
|
||||||
import org.shredzone.acme4j.exception.AcmeException;
|
|
||||||
import org.shredzone.acme4j.util.CSRBuilder;
|
|
||||||
import org.shredzone.acme4j.util.KeyPairUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple client test tool.
|
|
||||||
* <p>
|
|
||||||
* Pass the names of the domains as parameters.
|
|
||||||
*/
|
|
||||||
public class AcmeClient {
|
|
||||||
// File name of the User Key Pair
|
|
||||||
public static final File USER_KEY_FILE = new File("user.key");
|
|
||||||
|
|
||||||
// File name of the Domain Key Pair
|
|
||||||
public static final File DOMAIN_KEY_FILE = new File("domain.key");
|
|
||||||
|
|
||||||
// File name of the CSR
|
|
||||||
public static final File DOMAIN_CSR_FILE = new File("domain.csr");
|
|
||||||
|
|
||||||
// File name of the signed certificate
|
|
||||||
public static final File DOMAIN_CHAIN_FILE = new File("domain-chain.crt");
|
|
||||||
|
|
||||||
// RSA key size of generated key pairs
|
|
||||||
private static final int KEY_SIZE = 2048;
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AcmeClient.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a certificate for the given domains. Also takes care for the registration process.
|
|
||||||
*
|
|
||||||
* @param domains
|
|
||||||
* Domains to get a common certificate for
|
|
||||||
*/
|
|
||||||
public void fetchCertificate(Collection<String> domains) throws IOException, AcmeException {
|
|
||||||
// Load the user key file. If there is no key file, create a new one.
|
|
||||||
// Keep this key pair in a safe place! In a production environment, you will not be
|
|
||||||
// able to access your account again if you should lose the key pair.
|
|
||||||
KeyPair userKeyPair = loadOrCreateKeyPair(USER_KEY_FILE);
|
|
||||||
|
|
||||||
// Create a session for Let's Encrypt.
|
|
||||||
// Use "acme://letsencrypt.org" for production server
|
|
||||||
Session session = new Session("acme://letsencrypt.org" + (TBMCCoreAPI.IsTestServer() ? "/staging" : ""));
|
|
||||||
|
|
||||||
// Get the Registration to the account.
|
|
||||||
// If there is no account yet, create a new one.
|
|
||||||
Account acc = findOrRegisterAccount(session, userKeyPair);
|
|
||||||
|
|
||||||
Order order = acc.newOrder().domains(domains).create();
|
|
||||||
|
|
||||||
// Separately authorize every requested domain.
|
|
||||||
for (Authorization auth : order.getAuthorizations()) {
|
|
||||||
authorize(auth);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load or create a key pair for the domains. This should not be the userKeyPair!
|
|
||||||
KeyPair domainKeyPair = loadOrCreateKeyPair(DOMAIN_KEY_FILE);
|
|
||||||
|
|
||||||
// Generate a CSR for all of the domains, and sign it with the domain key pair.
|
|
||||||
CSRBuilder csrb = new CSRBuilder();
|
|
||||||
csrb.addDomains(domains);
|
|
||||||
csrb.sign(domainKeyPair);
|
|
||||||
|
|
||||||
// Write the CSR to a file, for later use.
|
|
||||||
try (Writer out = new FileWriter(DOMAIN_CSR_FILE)) {
|
|
||||||
csrb.write(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.info("Ordering certificate...");
|
|
||||||
// Order the certificate
|
|
||||||
order.execute(csrb.getEncoded());
|
|
||||||
|
|
||||||
// Wait for the order to complete
|
|
||||||
try {
|
|
||||||
int attempts = 10;
|
|
||||||
while (order.getStatus() != Status.VALID && attempts-- > 0) {
|
|
||||||
// Did the order fail?
|
|
||||||
if (order.getStatus() == Status.INVALID) {
|
|
||||||
throw new AcmeException("Order failed... Giving up.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for a few seconds
|
|
||||||
Thread.sleep(3000L);
|
|
||||||
|
|
||||||
// Then update the status
|
|
||||||
order.update();
|
|
||||||
if (order.getStatus() != Status.VALID)
|
|
||||||
LOG.info("Not yet...");
|
|
||||||
}
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
LOG.error("interrupted", ex);
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the certificate
|
|
||||||
Certificate certificate = order.getCertificate();
|
|
||||||
|
|
||||||
if (certificate == null)
|
|
||||||
throw new AcmeException("Certificate is null. Wot.");
|
|
||||||
|
|
||||||
LOG.info("Success! The certificate for domains " + domains + " has been generated!");
|
|
||||||
LOG.info("Certificate URL: " + certificate.getLocation());
|
|
||||||
|
|
||||||
// Write a combined file containing the certificate and chain.
|
|
||||||
try (FileWriter fw = new FileWriter(DOMAIN_CHAIN_FILE)) {
|
|
||||||
certificate.writeCertificate(fw);
|
|
||||||
}
|
|
||||||
|
|
||||||
// That's all! Configure your web server to use the DOMAIN_KEY_FILE and
|
|
||||||
// DOMAIN_CHAIN_FILE for the requested domans.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a key pair from specified file. If the file does not exist, a new key pair is generated and saved.
|
|
||||||
*
|
|
||||||
* @return {@link KeyPair}.
|
|
||||||
*/
|
|
||||||
private KeyPair loadOrCreateKeyPair(File file) throws IOException {
|
|
||||||
if (file.exists()) {
|
|
||||||
try (FileReader fr = new FileReader(file)) {
|
|
||||||
return KeyPairUtils.readKeyPair(fr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
KeyPair domainKeyPair = KeyPairUtils.createKeyPair(KEY_SIZE);
|
|
||||||
try (FileWriter fw = new FileWriter(file)) {
|
|
||||||
KeyPairUtils.writeKeyPair(domainKeyPair, fw);
|
|
||||||
}
|
|
||||||
return domainKeyPair;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds your {@link Account} at the ACME server. It will be found by your user's public key. If your key is not known to the server yet, a new registration will be created.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* {@link Session} to bind with
|
|
||||||
* @param kp The user keypair
|
|
||||||
* @return {@link Account} connected to your account
|
|
||||||
*/
|
|
||||||
private Account findOrRegisterAccount(Session session, KeyPair kp) throws AcmeException, IOException {
|
|
||||||
Account acc;
|
|
||||||
|
|
||||||
URI loc = ButtonWebsiteModule.getRegistration();
|
|
||||||
if (loc != null) {
|
|
||||||
LOG.info("Loading account from file");
|
|
||||||
return new Login(loc.toURL(), kp, session).getAccount();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to create a new Registration.
|
|
||||||
AccountBuilder ab = new AccountBuilder().useKeyPair(kp);
|
|
||||||
|
|
||||||
// This is a new account. Let the user accept the Terms of Service.
|
|
||||||
// We won't be able to authorize domains until the ToS is accepted.
|
|
||||||
URI agreement = session.getMetadata().getTermsOfService();
|
|
||||||
acceptAgreement(ab, agreement);
|
|
||||||
acc = ab.create(session);
|
|
||||||
LOG.info("Registered a new user, URI: " + acc.getLocation());
|
|
||||||
ButtonWebsiteModule.storeRegistration(acc.getLocation());
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorize a domain. It will be associated with your account, so you will be able to retrieve a signed certificate for the domain later.
|
|
||||||
* <p>
|
|
||||||
* You need separate authorizations for subdomains (e.g. "www" subdomain). Wildcard certificates are not currently supported.
|
|
||||||
*
|
|
||||||
* @param auth
|
|
||||||
* {@link Authorization} for the domain
|
|
||||||
*/
|
|
||||||
private void authorize(Authorization auth) throws AcmeException {
|
|
||||||
LOG.info("Authorization for domain " + auth.getDomain());
|
|
||||||
|
|
||||||
// The authorization is already valid. No need to process a challenge.
|
|
||||||
if (auth.getStatus() == Status.VALID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Challenge challenge = httpChallenge(auth);
|
|
||||||
|
|
||||||
if (challenge == null) {
|
|
||||||
throw new AcmeException("No challenge found");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the challenge is already verified, there's no need to execute it again.
|
|
||||||
if (challenge.getStatus() == Status.VALID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now trigger the challenge.
|
|
||||||
challenge.trigger();
|
|
||||||
|
|
||||||
// Poll for the challenge to complete.
|
|
||||||
try {
|
|
||||||
int attempts = 10;
|
|
||||||
while (challenge.getStatus() != Status.VALID && attempts-- > 0) {
|
|
||||||
// Did the authorization fail?
|
|
||||||
if (challenge.getStatus() == Status.INVALID) {
|
|
||||||
throw new AcmeException("Challenge failed... Giving up.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for a few seconds
|
|
||||||
Thread.sleep(3000L);
|
|
||||||
|
|
||||||
// Then update the status
|
|
||||||
challenge.update();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
LOG.error("interrupted", ex);
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
// All reattempts are used up and there is still no valid authorization?
|
|
||||||
if (challenge.getStatus() != Status.VALID) {
|
|
||||||
throw new AcmeException("Failed to pass the challenge for domain " + auth.getDomain() + ", ... Giving up.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares a HTTP challenge.
|
|
||||||
* <p>
|
|
||||||
* The verification of this challenge expects a file with a certain content to be reachable at a given path under the domain to be tested.
|
|
||||||
* <p>
|
|
||||||
* This example outputs instructions that need to be executed manually. In a production environment, you would rather generate this file automatically, or maybe use a servlet that returns
|
|
||||||
* {@link Http01Challenge#getAuthorization()}.
|
|
||||||
*
|
|
||||||
* @param auth
|
|
||||||
* {@link Authorization} to find the challenge in
|
|
||||||
* @return {@link Challenge} to verify
|
|
||||||
*/
|
|
||||||
public Challenge httpChallenge(Authorization auth) throws AcmeException {
|
|
||||||
// Find a single http-01 challenge
|
|
||||||
Http01Challenge challenge = auth.findChallenge(Http01Challenge.TYPE);
|
|
||||||
if (challenge == null) {
|
|
||||||
throw new AcmeException("Found no " + Http01Challenge.TYPE + " challenge, don't know what to do...");
|
|
||||||
}
|
|
||||||
LOG.info("Storing the challenge data.");
|
|
||||||
LOG.info("It should be reachable at: http://" + auth.getDomain() + "/.well-known/acme-challenge/" + challenge.getToken());
|
|
||||||
ButtonWebsiteModule.addHttpPage(new AcmeChallengePage(challenge.getToken(), challenge.getAuthorization()));
|
|
||||||
ButtonWebsiteModule.startHttp();
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000); // Just to make sure
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
}
|
|
||||||
return challenge;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Presents the user a link to the Terms of Service, and asks for confirmation. If the user denies confirmation, an exception is thrown.
|
|
||||||
*
|
|
||||||
* @param ab
|
|
||||||
* {@link AccountBuilder} for the user
|
|
||||||
* @param agreement
|
|
||||||
* {@link URI} of the Terms of Service
|
|
||||||
*/
|
|
||||||
public void acceptAgreement(AccountBuilder ab, URI agreement) throws AcmeException, IOException {
|
|
||||||
LOG.info("Terms of Service: " + agreement);
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
|
||||||
System.out.println("Do you accept the terms? (y/n)");
|
|
||||||
if (br.readLine().equalsIgnoreCase("y\n")) {
|
|
||||||
throw new AcmeException("User did not accept Terms of Service");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Motify the Registration and accept the agreement
|
|
||||||
ab.agreeToTermsOfService();
|
|
||||||
LOG.info("Updated user's ToS");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes this example.
|
|
||||||
*
|
|
||||||
* @param args
|
|
||||||
* Domains to get a certificate for
|
|
||||||
*/
|
|
||||||
public static void main(String... args) {
|
|
||||||
if (args.length == 0) {
|
|
||||||
LOG.error("Error while doing ACME!", new Exception("No domains given"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.info("Starting up...");
|
|
||||||
|
|
||||||
Collection<String> domains = Arrays.asList(args);
|
|
||||||
try {
|
|
||||||
AcmeClient ct = new AcmeClient();
|
|
||||||
ct.fetchCertificate(domains);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
LOG.error("Failed to get a certificate for domains " + domains, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,31 +5,12 @@ import buttondevteam.lib.architecture.ButtonPlugin;
|
||||||
import buttondevteam.website.io.IOHelper;
|
import buttondevteam.website.io.IOHelper;
|
||||||
import buttondevteam.website.page.*;
|
import buttondevteam.website.page.*;
|
||||||
import com.sun.net.httpserver.HttpServer;
|
import com.sun.net.httpserver.HttpServer;
|
||||||
import com.sun.net.httpserver.HttpsConfigurator;
|
|
||||||
import com.sun.net.httpserver.HttpsParameters;
|
|
||||||
import com.sun.net.httpserver.HttpsServer;
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
|
||||||
import org.bouncycastle.openssl.PEMKeyPair;
|
|
||||||
import org.bouncycastle.openssl.PEMParser;
|
|
||||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
import javax.net.ssl.*;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.PrivateKey;
|
|
||||||
import java.security.Security;
|
|
||||||
import java.security.cert.Certificate;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class ButtonWebsiteModule extends ButtonPlugin {
|
public class ButtonWebsiteModule extends ButtonPlugin {
|
||||||
private static HttpsServer server;
|
|
||||||
/**
|
/**
|
||||||
* For ACME validation and user redirection
|
* For ACME validation and user redirection
|
||||||
*/
|
*/
|
||||||
|
@ -38,75 +19,8 @@ public class ButtonWebsiteModule extends ButtonPlugin {
|
||||||
|
|
||||||
public ButtonWebsiteModule() {
|
public ButtonWebsiteModule() {
|
||||||
try {
|
try {
|
||||||
int ps = getConfig().getInt("https-port", 443);
|
|
||||||
int p = getConfig().getInt("http-port", 80);
|
int p = getConfig().getInt("http-port", 80);
|
||||||
server = HttpsServer.create(new InetSocketAddress((InetAddress) null, ps), 10);
|
|
||||||
httpserver = HttpServer.create(new InetSocketAddress((InetAddress) null, p), 10);
|
httpserver = HttpServer.create(new InetSocketAddress((InetAddress) null, p), 10);
|
||||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
|
||||||
|
|
||||||
// initialise the keystore
|
|
||||||
char[] password = "password".toCharArray();
|
|
||||||
KeyStore ks = KeyStore.getInstance("JKS");
|
|
||||||
File certfile = AcmeClient.DOMAIN_CHAIN_FILE; /* your cert path */
|
|
||||||
File keystoreFile = new File("keystore.keystore");
|
|
||||||
|
|
||||||
ks.load(keystoreFile.exists() ? new FileInputStream(keystoreFile) : null, password);
|
|
||||||
|
|
||||||
String alias = "chroma";
|
|
||||||
|
|
||||||
//////
|
|
||||||
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
InputStream certstream = fullStream(certfile);
|
|
||||||
Certificate[] certs = cf.generateCertificates(certstream).toArray(new Certificate[0]);
|
|
||||||
|
|
||||||
BufferedReader br = new BufferedReader(new FileReader(AcmeClient.DOMAIN_KEY_FILE));
|
|
||||||
|
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
|
||||||
|
|
||||||
PEMParser pp = new PEMParser(br);
|
|
||||||
PEMKeyPair pemKeyPair = (PEMKeyPair) pp.readObject();
|
|
||||||
KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
|
|
||||||
pp.close();
|
|
||||||
PrivateKey pk = kp.getPrivate();
|
|
||||||
|
|
||||||
// Add the certificate
|
|
||||||
ks.setKeyEntry(alias, pk, password, certs); // TODO: Only set if updated
|
|
||||||
|
|
||||||
// Save the new keystore contents
|
|
||||||
FileOutputStream out = new FileOutputStream(keystoreFile);
|
|
||||||
ks.store(out, password);
|
|
||||||
out.close();
|
|
||||||
|
|
||||||
// setup the key manager factory
|
|
||||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
|
||||||
kmf.init(ks, password);
|
|
||||||
|
|
||||||
// setup the trust manager factory
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
|
||||||
tmf.init(ks);
|
|
||||||
|
|
||||||
// setup the HTTPS context and parameters
|
|
||||||
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
|
||||||
server.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
|
|
||||||
public void configure(HttpsParameters params) {
|
|
||||||
try {
|
|
||||||
// initialise the SSL context
|
|
||||||
SSLContext c = SSLContext.getDefault();
|
|
||||||
SSLEngine engine = c.createSSLEngine();
|
|
||||||
params.setNeedClientAuth(false);
|
|
||||||
params.setCipherSuites(engine.getEnabledCipherSuites());
|
|
||||||
params.setProtocols(engine.getEnabledProtocols());
|
|
||||||
|
|
||||||
// get the default parameters
|
|
||||||
SSLParameters defaultSSLParameters = c.getDefaultSSLParameters();
|
|
||||||
params.setSSLParameters(defaultSSLParameters);
|
|
||||||
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.out.println("Failed to create HTTPS port");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
enabled = true;
|
enabled = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
TBMCCoreAPI.SendException("An error occurred while starting the webserver!", e, this);
|
TBMCCoreAPI.SendException("An error occurred while starting the webserver!", e, this);
|
||||||
|
@ -125,19 +39,12 @@ public class ButtonWebsiteModule extends ButtonPlugin {
|
||||||
addPage(new ProfilePage());
|
addPage(new ProfilePage());
|
||||||
addPage(new BuildNotificationsPage());
|
addPage(new BuildNotificationsPage());
|
||||||
addPage(new BridgePage());
|
addPage(new BridgePage());
|
||||||
|
addHttpPage(new BridgePage());
|
||||||
TBMCCoreAPI.RegisterUserClass(WebUser.class, WebUser::new);
|
TBMCCoreAPI.RegisterUserClass(WebUser.class, WebUser::new);
|
||||||
getCommand2MC().registerCommand(new LoginCommand());
|
getCommand2MC().registerCommand(new LoginCommand());
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
||||||
this.getLogger().info("Starting webserver...");
|
this.getLogger().info("Starting webserver...");
|
||||||
server.setExecutor(
|
httpserver.createContext("/", exchange -> IOHelper.SendResponse(IOHelper.Redirect("https://www.youtube.com/watch?v=dQw4w9WgXcQ", exchange)));
|
||||||
new ThreadPoolExecutor(4, 8, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)));
|
|
||||||
httpserver.createContext("/", exchange -> IOHelper.SendResponse(IOHelper.Redirect("https://server.figytuna.com/", exchange)));
|
|
||||||
final Calendar calendar = Calendar.getInstance();
|
|
||||||
if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY && !TBMCCoreAPI.IsTestServer()) { // Only update every week
|
|
||||||
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
|
||||||
AcmeClient.main("server.figytuna.com"); // Task is running async so we don't need an extra thread
|
|
||||||
}
|
|
||||||
((Runnable) server::start).run(); // Totally normal way of calling a method
|
|
||||||
if (!httpstarted)
|
if (!httpstarted)
|
||||||
httpserver.start();
|
httpserver.start();
|
||||||
this.getLogger().info("Webserver started");
|
this.getLogger().info("Webserver started");
|
||||||
|
@ -162,9 +69,7 @@ public class ButtonWebsiteModule extends ButtonPlugin {
|
||||||
* Adds a new page/endpoint to the website. This method needs to be called before the server finishes loading (onEnable).
|
* Adds a new page/endpoint to the website. This method needs to be called before the server finishes loading (onEnable).
|
||||||
*/
|
*/
|
||||||
public static void addPage(Page page) {
|
public static void addPage(Page page) {
|
||||||
if (!enabled)
|
// No HTTPS support for now but these pages should be secured (and updated)
|
||||||
return;
|
|
||||||
server.createContext("/" + page.GetName(), page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,13 +6,9 @@ import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.*;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
@ -57,7 +53,10 @@ public class IOHelper {
|
||||||
try {
|
try {
|
||||||
if (exchange.getRequestBody().available() == 0)
|
if (exchange.getRequestBody().available() == 0)
|
||||||
return "";
|
return "";
|
||||||
return IOUtils.toString(exchange.getRequestBody(), "UTF-8");
|
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||||
|
exchange.getRequestBody().transferTo(baos);
|
||||||
|
return baos.toString(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -6,8 +6,8 @@ import buttondevteam.website.io.IOHelper;
|
||||||
import buttondevteam.website.io.Response;
|
import buttondevteam.website.io.Response;
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import com.sun.net.httpserver.HttpHandler;
|
import com.sun.net.httpserver.HttpHandler;
|
||||||
import org.apache.commons.io.output.ByteArrayOutputStream;
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue