mirror of
https://github.com/unmojang/OnlineModeFix.git
synced 2025-09-10 16:00:40 -04:00
Added an online-mode fix.
This commit is contained in:
parent
31df51d672
commit
1b3b36f281
@ -1,5 +1,5 @@
|
|||||||
name: MineOnlineBroadcast
|
name: MineOnlineBroadcast
|
||||||
version: 1.0.7
|
version: 1.0.8
|
||||||
description: Lists a server on mineonline.codie.gg/servers
|
description: Lists a server on mineonline.codie.gg/servers
|
||||||
author: codieradical
|
author: codieradical
|
||||||
authors: [Codie]
|
authors: [Codie]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import gg.codie.mineonline.ProxyThread;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
@ -6,6 +7,7 @@ import java.io.*;
|
|||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.ServerSocket;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@ -20,6 +22,26 @@ public class MineOnlineBroadcast extends JavaPlugin {
|
|||||||
public static long lastPing;
|
public static long lastPing;
|
||||||
MineOnlineBroadcastListener listener;
|
MineOnlineBroadcastListener listener;
|
||||||
Logger log;
|
Logger log;
|
||||||
|
ProxyThread proxyThread;
|
||||||
|
|
||||||
|
public void launchProxy() throws IOException {
|
||||||
|
ServerSocket serverSocket = new ServerSocket(0);
|
||||||
|
proxyThread = new ProxyThread(serverSocket);
|
||||||
|
proxyThread.start();
|
||||||
|
|
||||||
|
System.out.println("Enabling online-mode fix.");
|
||||||
|
|
||||||
|
System.setProperty("http.proxyHost", serverSocket.getInetAddress().getHostAddress());
|
||||||
|
System.setProperty("http.proxyPort", "" + serverSocket.getLocalPort());
|
||||||
|
System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopProxy() {
|
||||||
|
if (proxyThread != null) {
|
||||||
|
proxyThread.stop();
|
||||||
|
proxyThread = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] createChecksum(String filename) throws Exception {
|
public static byte[] createChecksum(String filename) throws Exception {
|
||||||
InputStream fis = new FileInputStream(filename);
|
InputStream fis = new FileInputStream(filename);
|
||||||
@ -123,6 +145,10 @@ public class MineOnlineBroadcast extends JavaPlugin {
|
|||||||
Properties propertiesFile = new Properties();
|
Properties propertiesFile = new Properties();
|
||||||
propertiesFile.load(new FileInputStream(new File("server.properties")));
|
propertiesFile.load(new FileInputStream(new File("server.properties")));
|
||||||
|
|
||||||
|
boolean isPublic = propertiesFile.getProperty("public", "true").equals("true");
|
||||||
|
if(!isPublic)
|
||||||
|
return;
|
||||||
|
|
||||||
String ip = propertiesFile.getProperty("serverlist-ip", propertiesFile.getProperty("server-ip", propertiesFile.getProperty("ip", null)));
|
String ip = propertiesFile.getProperty("serverlist-ip", propertiesFile.getProperty("server-ip", propertiesFile.getProperty("ip", null)));
|
||||||
String port = propertiesFile.getProperty("serverlist-port", propertiesFile.getProperty("server-port", propertiesFile.getProperty("port", "25565")));
|
String port = propertiesFile.getProperty("serverlist-port", propertiesFile.getProperty("server-port", propertiesFile.getProperty("port", "25565")));
|
||||||
int users = getServer().getOnlinePlayers().length;
|
int users = getServer().getOnlinePlayers().length;
|
||||||
@ -162,10 +188,21 @@ public class MineOnlineBroadcast extends JavaPlugin {
|
|||||||
this.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_LOGIN, this.listener, Event.Priority.Lowest, this);
|
this.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_LOGIN, this.listener, Event.Priority.Lowest, this);
|
||||||
this.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_QUIT, this.listener, Event.Priority.Highest, this);
|
this.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_QUIT, this.listener, Event.Priority.Highest, this);
|
||||||
this.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_KICK, this.listener, Event.Priority.Highest, this);
|
this.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_KICK, this.listener, Event.Priority.Highest, this);
|
||||||
|
try {
|
||||||
|
Properties propertiesFile = new Properties();
|
||||||
|
propertiesFile.load(new FileInputStream(new File("server.properties")));
|
||||||
|
boolean onlineMode = propertiesFile.getProperty("online-mode", "true").equals("true");
|
||||||
|
|
||||||
|
if (onlineMode)
|
||||||
|
launchProxy();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warning("Failed to enable online-mode fix. Authentication may fail.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
broadcastThread.interrupt();
|
broadcastThread.interrupt();
|
||||||
|
stopProxy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
src/gg/codie/minecraft/api/SessionServer.java
Normal file
23
src/gg/codie/minecraft/api/SessionServer.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package gg.codie.minecraft.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class SessionServer {
|
||||||
|
private static final String BASE_URL = "https://sessionserver.mojang.com";
|
||||||
|
|
||||||
|
public static boolean hasJoined(String username, String serverId, String ip) throws IOException {
|
||||||
|
HttpURLConnection connection;
|
||||||
|
|
||||||
|
URL url = new URL(BASE_URL + "/session/minecraft/hasJoined?username=" + username + "&serverId=" + serverId + (ip != null ? "&ip=" + ip : ""));
|
||||||
|
connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setRequestMethod("GET");
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setDoOutput(false);
|
||||||
|
|
||||||
|
connection.connect();
|
||||||
|
|
||||||
|
return connection.getResponseCode() == 200;
|
||||||
|
}
|
||||||
|
}
|
262
src/gg/codie/mineonline/ProxyThread.java
Normal file
262
src/gg/codie/mineonline/ProxyThread.java
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
package gg.codie.mineonline;
|
||||||
|
|
||||||
|
import gg.codie.minecraft.api.SessionServer;
|
||||||
|
import gg.codie.utils.ArrayUtils;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class ProxyThread implements Runnable {
|
||||||
|
private AtomicReference<ServerSocket> serverSocket = new AtomicReference<>();
|
||||||
|
private Thread worker;
|
||||||
|
private AtomicBoolean running = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
worker = new Thread(this);
|
||||||
|
worker.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
running.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isRunning() {
|
||||||
|
return running.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProxyThread(ServerSocket serverSocket) {
|
||||||
|
this.serverSocket.set(serverSocket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
running.set(true);
|
||||||
|
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||||
|
|
||||||
|
Socket clientSocket = null;
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
System.out.println(serverSocket.get().getInetAddress() + ":" + serverSocket.get().getLocalPort());
|
||||||
|
|
||||||
|
while (running.get()) {
|
||||||
|
//Stream to put data to the browser
|
||||||
|
PrintWriter outGoing = null;
|
||||||
|
try {
|
||||||
|
clientSocket = serverSocket.get().accept();
|
||||||
|
outGoing = new PrintWriter(clientSocket.getOutputStream(), true);
|
||||||
|
|
||||||
|
final int bufferSize = 8096;
|
||||||
|
|
||||||
|
byte[] buffer = new byte[bufferSize];
|
||||||
|
int bytes_read;
|
||||||
|
LinkedList<Byte> request = new LinkedList();
|
||||||
|
|
||||||
|
bytes_read = clientSocket.getInputStream().read(buffer, 0, bufferSize);
|
||||||
|
for(int i = 0; i < bytes_read; i++)
|
||||||
|
request.add(buffer[i]);
|
||||||
|
|
||||||
|
String requestHeaders = new String(buffer).split("\r\n\r\n")[0];
|
||||||
|
|
||||||
|
// keep reading.
|
||||||
|
String requestString = new String(buffer);
|
||||||
|
for (String header : requestHeaders.split("\r\n")) {
|
||||||
|
if(header.contains("Content-Length")) {
|
||||||
|
int contentLength = Integer.parseInt(header.split(": ")[1]);
|
||||||
|
int headerLength = requestString.substring(0, requestString.indexOf("\r\n\r\n") + 4).length();
|
||||||
|
|
||||||
|
while(request.size() < contentLength + headerLength) {
|
||||||
|
bytes_read = clientSocket.getInputStream().read(buffer, 0, bufferSize);
|
||||||
|
for(int i = 0; i < bytes_read; i++)
|
||||||
|
request.add(buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] requestBytes = ArrayUtils.toPrimitives(request.toArray(new Byte[0]));
|
||||||
|
requestString = new String(requestBytes);
|
||||||
|
|
||||||
|
int headerSize = requestString.split("\r\n\r\n")[0].length() + 4;
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
System.out.println("Request");
|
||||||
|
requestHeaders = requestString.split("\r\n\r\n")[0];
|
||||||
|
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
System.out.println(requestString);
|
||||||
|
|
||||||
|
String urlString = "";
|
||||||
|
try {
|
||||||
|
urlString = pullLinks(requestString).get(0);
|
||||||
|
} catch (IndexOutOfBoundsException ex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix online-mode.
|
||||||
|
if(urlString.contains("minecraft.net/game/checkserver.jsp?")) {
|
||||||
|
|
||||||
|
System.out.println("here.");
|
||||||
|
|
||||||
|
String username = null;
|
||||||
|
String serverId = null;
|
||||||
|
String ip = null;
|
||||||
|
|
||||||
|
String[] args = urlString.replace("http://www.minecraft.net/game/checkserver.jsp?", "").split("&");
|
||||||
|
for (String arg : args) {
|
||||||
|
String[] keyValue = arg.split("=");
|
||||||
|
|
||||||
|
if (keyValue[0].equals("user"))
|
||||||
|
username = keyValue[1];
|
||||||
|
else if (keyValue[0].equals("serverId"))
|
||||||
|
serverId = keyValue[1];
|
||||||
|
else if (keyValue[0].equals("ip"))
|
||||||
|
ip = keyValue[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username != null && serverId != null) {
|
||||||
|
boolean validJoin = SessionServer.hasJoined(
|
||||||
|
username,
|
||||||
|
serverId,
|
||||||
|
ip
|
||||||
|
);
|
||||||
|
|
||||||
|
if (validJoin) {
|
||||||
|
String responseHeaders =
|
||||||
|
"HTTP/1.0 200 OKServer:Werkzeug/1.0.1 Python/3.7.0\r\n\r\n";
|
||||||
|
|
||||||
|
clientSocket.getOutputStream().write(responseHeaders.getBytes());
|
||||||
|
clientSocket.getOutputStream().write("YES".getBytes(StandardCharsets.UTF_8));
|
||||||
|
clientSocket.getOutputStream().flush();
|
||||||
|
clientSocket.getOutputStream().close();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
URL url = new URL(urlString);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
|
||||||
|
for (String header : requestHeaders.substring(requestHeaders.indexOf("\r\n") + 2).split("\r\n")) {
|
||||||
|
String headerName = header.substring(0, header.indexOf(":"));
|
||||||
|
String headerValue = header.substring(header.indexOf(":") + 2);
|
||||||
|
connection.setRequestProperty(headerName, headerValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
String methodLine = requestHeaders.substring(0, requestHeaders.indexOf("\r\n"));
|
||||||
|
connection.setRequestMethod(methodLine.substring(0, methodLine.indexOf(" ")));
|
||||||
|
|
||||||
|
byte[] content = new byte[0];
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (headerSize < requestBytes.length) {
|
||||||
|
content = Arrays.copyOfRange(requestBytes, headerSize, requestBytes.length);
|
||||||
|
|
||||||
|
connection.setUseCaches(false);
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
|
||||||
|
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
|
||||||
|
|
||||||
|
wr.write(content);
|
||||||
|
wr.flush();
|
||||||
|
wr.close();
|
||||||
|
} else {
|
||||||
|
connection.setUseCaches(false);
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String responseHeader = "";
|
||||||
|
for (Map.Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
|
||||||
|
if (header.getKey() == null) {
|
||||||
|
Iterator<String> valueIterator = header.getValue().iterator();
|
||||||
|
responseHeader += valueIterator.next();
|
||||||
|
while (valueIterator.hasNext()) {
|
||||||
|
responseHeader += " " + valueIterator.next();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
responseHeader += header.getKey() + ":";
|
||||||
|
Iterator<String> valueIterator = header.getValue().iterator();
|
||||||
|
responseHeader += valueIterator.next();
|
||||||
|
while (valueIterator.hasNext()) {
|
||||||
|
responseHeader += ", " + valueIterator.next();
|
||||||
|
}
|
||||||
|
responseHeader += "\r\n";
|
||||||
|
}
|
||||||
|
responseHeader += "\r\n";
|
||||||
|
|
||||||
|
String contentString = new String(content);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
System.out.println("Response");
|
||||||
|
System.out.print(responseHeader);
|
||||||
|
System.out.println(contentString);
|
||||||
|
|
||||||
|
InputStream is = connection.getInputStream();
|
||||||
|
|
||||||
|
clientSocket.getOutputStream().write(responseHeader.getBytes());
|
||||||
|
|
||||||
|
buffer = new byte[bufferSize];
|
||||||
|
while ((bytes_read = is.read(buffer, 0, bufferSize)) != -1) {
|
||||||
|
for (int i = 0; i < bytes_read; i++) {
|
||||||
|
clientSocket.getOutputStream().write(buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clientSocket.getOutputStream().flush();
|
||||||
|
clientSocket.getOutputStream().close();
|
||||||
|
|
||||||
|
} catch (Exception ex) {
|
||||||
|
String responseHeaders =
|
||||||
|
"HTTP/1.0 404 Not FoundServer:Werkzeug/1.0.1 Python/3.7.0\r\n\r\n";
|
||||||
|
clientSocket.getOutputStream().write(responseHeaders.getBytes());
|
||||||
|
clientSocket.getOutputStream().flush();
|
||||||
|
clientSocket.getOutputStream().close();
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException ex) {
|
||||||
|
System.err.println("Got a 404 for: " + ex.getMessage());
|
||||||
|
} catch (IOException ex) {
|
||||||
|
System.out.println("Something went very wrong.");
|
||||||
|
ex.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
outGoing.close();
|
||||||
|
try {
|
||||||
|
clientSocket.close();
|
||||||
|
} catch (Exception e) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
serverSocket.get().close();
|
||||||
|
} catch (Exception e) { }
|
||||||
|
running.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Pull all links from the body for easy retrieval
|
||||||
|
private static ArrayList<String> pullLinks(String text) {
|
||||||
|
ArrayList<String> links = new ArrayList<String>();
|
||||||
|
|
||||||
|
String regex = "\\(?\\b(http://|www[.])[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]";
|
||||||
|
Pattern p = Pattern.compile(regex);
|
||||||
|
Matcher m = p.matcher(text);
|
||||||
|
while(m.find()) {
|
||||||
|
String urlStr = m.group();
|
||||||
|
if (urlStr.startsWith("(") && urlStr.endsWith(")"))
|
||||||
|
{
|
||||||
|
urlStr = urlStr.substring(1, urlStr.length() - 1);
|
||||||
|
}
|
||||||
|
links.add(urlStr);
|
||||||
|
}
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
}
|
14
src/gg/codie/utils/ArrayUtils.java
Normal file
14
src/gg/codie/utils/ArrayUtils.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package gg.codie.utils;
|
||||||
|
|
||||||
|
public class ArrayUtils {
|
||||||
|
public static byte[] toPrimitives(Byte[] oBytes)
|
||||||
|
{
|
||||||
|
|
||||||
|
byte[] bytes = new byte[oBytes.length];
|
||||||
|
for(int i = 0; i < oBytes.length; i++){
|
||||||
|
bytes[i] = oBytes[i];
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user