diff --git a/MinecraftClient/Protocol/ProtocolHandler.cs b/MinecraftClient/Protocol/ProtocolHandler.cs
index 6adad9ed..d36834a5 100644
--- a/MinecraftClient/Protocol/ProtocolHandler.cs
+++ b/MinecraftClient/Protocol/ProtocolHandler.cs
@@ -1,437 +1,437 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using MinecraftClient.Protocol.Handlers;
-using MinecraftClient.Proxy;
-using System.Net.Sockets;
-using System.Net.Security;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using MinecraftClient.Protocol.Handlers;
+using MinecraftClient.Proxy;
+using System.Net.Sockets;
+using System.Net.Security;
using MinecraftClient.Protocol.Handlers.Forge;
-
-
-namespace MinecraftClient.Protocol
-{
- ///
- /// Handle login, session, server ping and provide a protocol handler for interacting with a minecraft server.
- ///
-
- public static class ProtocolHandler
- {
- ///
- /// Retrieve information about a Minecraft server
- ///
- /// Server IP to ping
- /// Server Port to ping
- /// Will contain protocol version, if ping successful
- /// TRUE if ping was successful
-
- public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion, ref ForgeInfo forgeInfo)
- {
- bool success = false;
- int protocolversionTmp = 0;
- ForgeInfo forgeInfoTmp = null;
- if (AutoTimeout.Perform(() =>
- {
- try
- {
- if (Protocol16Handler.doPing(serverIP, serverPort, ref protocolversionTmp)
- || Protocol18Handler.doPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp))
- {
- success = true;
- }
- else ConsoleIO.WriteLineFormatted("§8Unexpected response from the server (is that a Minecraft server?)");
- }
- catch (Exception e)
- {
- ConsoleIO.WriteLineFormatted(String.Format("§8{0}: {1}", e.GetType().FullName, e.Message));
- }
- }, TimeSpan.FromSeconds(30)))
- {
- protocolversion = protocolversionTmp;
- forgeInfo = forgeInfoTmp;
- return success;
- }
- else
- {
- ConsoleIO.WriteLineFormatted("§8A timeout occured while attempting to connect to this IP.");
- return false;
- }
- }
-
- ///
- /// Get a protocol handler for the specified Minecraft version
- ///
- /// Tcp Client connected to the server
- /// Protocol version to handle
- /// Handler with the appropriate callbacks
- ///
-
- public static IMinecraftCom getProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo forgeInfo, IMinecraftComHandler Handler)
- {
- int[] supportedVersions_Protocol16 = { 51, 60, 61, 72, 73, 74, 78 };
- if (Array.IndexOf(supportedVersions_Protocol16, ProtocolVersion) > -1)
- return new Protocol16Handler(Client, ProtocolVersion, Handler);
- int[] supportedVersions_Protocol18 = { 4, 5, 47 };
- if (Array.IndexOf(supportedVersions_Protocol18, ProtocolVersion) > -1)
- return new Protocol18Handler(Client, ProtocolVersion, Handler, forgeInfo);
- throw new NotSupportedException("The protocol version no." + ProtocolVersion + " is not supported.");
- }
-
- ///
- /// Convert a human-readable Minecraft version number to network protocol version number
- ///
- /// The Minecraft version number
- /// The protocol version number or 0 if could not determine protocol version: error, unknown, not supported
-
- public static int MCVer2ProtocolVersion(string MCVersion)
- {
- if (MCVersion.Contains('.'))
- {
- switch (MCVersion.Split(' ')[0].Trim())
- {
- case "1.4.6":
- case "1.4.7":
- return 51;
- case "1.5.1":
- return 60;
- case "1.5.2":
- return 61;
- case "1.6.0":
- return 72;
- case "1.6.1":
- case "1.6.2":
- case "1.6.3":
- case "1.6.4":
- return 73;
- case "1.7.2":
- case "1.7.3":
- case "1.7.4":
- case "1.7.5":
- return 4;
- case "1.7.6":
- case "1.7.7":
- case "1.7.8":
- case "1.7.9":
- case "1.7.10":
- return 5;
- case "1.8.0":
- case "1.8.1":
- case "1.8.2":
- case "1.8.3":
- case "1.8.4":
- case "1.8.5":
- case "1.8.6":
- case "1.8.7":
- case "1.8.8":
- return 47;
- default:
- return 0;
- }
- }
- else
- {
- try
- {
- return Int32.Parse(MCVersion);
- }
- catch
- {
- return 0;
- }
- }
- }
-
- public enum LoginResult { OtherError, ServiceUnavailable, SSLError, Success, WrongPassword, AccountMigrated, NotPremium, LoginRequired, InvalidToken, NullError };
-
- ///
- /// Allows to login to a premium Minecraft account using the Yggdrasil authentication scheme.
- ///
- /// Login
- /// Password
- /// Will contain the access token returned by Minecraft.net, if the login is successful
- /// Will contain the client token generated before sending to Minecraft.net
- /// Will contain the player's PlayerID, needed for multiplayer
- /// Returns the status of the login (Success, Failure, etc.)
-
- public static LoginResult GetLogin(string user, string pass, out SessionToken session)
- {
- session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
-
- try
- {
+
+
+namespace MinecraftClient.Protocol
+{
+ ///
+ /// Handle login, session, server ping and provide a protocol handler for interacting with a minecraft server.
+ ///
+
+ public static class ProtocolHandler
+ {
+ ///
+ /// Retrieve information about a Minecraft server
+ ///
+ /// Server IP to ping
+ /// Server Port to ping
+ /// Will contain protocol version, if ping successful
+ /// TRUE if ping was successful
+
+ public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion, ref ForgeInfo forgeInfo)
+ {
+ bool success = false;
+ int protocolversionTmp = 0;
+ ForgeInfo forgeInfoTmp = null;
+ if (AutoTimeout.Perform(() =>
+ {
+ try
+ {
+ if (Protocol16Handler.doPing(serverIP, serverPort, ref protocolversionTmp)
+ || Protocol18Handler.doPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp))
+ {
+ success = true;
+ }
+ else ConsoleIO.WriteLineFormatted("§8Unexpected response from the server (is that a Minecraft server?)");
+ }
+ catch (Exception e)
+ {
+ ConsoleIO.WriteLineFormatted(String.Format("§8{0}: {1}", e.GetType().FullName, e.Message));
+ }
+ }, TimeSpan.FromSeconds(30)))
+ {
+ protocolversion = protocolversionTmp;
+ forgeInfo = forgeInfoTmp;
+ return success;
+ }
+ else
+ {
+ ConsoleIO.WriteLineFormatted("§8A timeout occured while attempting to connect to this IP.");
+ return false;
+ }
+ }
+
+ ///
+ /// Get a protocol handler for the specified Minecraft version
+ ///
+ /// Tcp Client connected to the server
+ /// Protocol version to handle
+ /// Handler with the appropriate callbacks
+ ///
+
+ public static IMinecraftCom getProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo forgeInfo, IMinecraftComHandler Handler)
+ {
+ int[] supportedVersions_Protocol16 = { 51, 60, 61, 72, 73, 74, 78 };
+ if (Array.IndexOf(supportedVersions_Protocol16, ProtocolVersion) > -1)
+ return new Protocol16Handler(Client, ProtocolVersion, Handler);
+ int[] supportedVersions_Protocol18 = { 4, 5, 47 };
+ if (Array.IndexOf(supportedVersions_Protocol18, ProtocolVersion) > -1)
+ return new Protocol18Handler(Client, ProtocolVersion, Handler, forgeInfo);
+ throw new NotSupportedException("The protocol version no." + ProtocolVersion + " is not supported.");
+ }
+
+ ///
+ /// Convert a human-readable Minecraft version number to network protocol version number
+ ///
+ /// The Minecraft version number
+ /// The protocol version number or 0 if could not determine protocol version: error, unknown, not supported
+
+ public static int MCVer2ProtocolVersion(string MCVersion)
+ {
+ if (MCVersion.Contains('.'))
+ {
+ switch (MCVersion.Split(' ')[0].Trim())
+ {
+ case "1.4.6":
+ case "1.4.7":
+ return 51;
+ case "1.5.1":
+ return 60;
+ case "1.5.2":
+ return 61;
+ case "1.6.0":
+ return 72;
+ case "1.6.1":
+ case "1.6.2":
+ case "1.6.3":
+ case "1.6.4":
+ return 73;
+ case "1.7.2":
+ case "1.7.3":
+ case "1.7.4":
+ case "1.7.5":
+ return 4;
+ case "1.7.6":
+ case "1.7.7":
+ case "1.7.8":
+ case "1.7.9":
+ case "1.7.10":
+ return 5;
+ case "1.8.0":
+ case "1.8.1":
+ case "1.8.2":
+ case "1.8.3":
+ case "1.8.4":
+ case "1.8.5":
+ case "1.8.6":
+ case "1.8.7":
+ case "1.8.8":
+ return 47;
+ default:
+ return 0;
+ }
+ }
+ else
+ {
+ try
+ {
+ return Int32.Parse(MCVersion);
+ }
+ catch
+ {
+ return 0;
+ }
+ }
+ }
+
+ public enum LoginResult { OtherError, ServiceUnavailable, SSLError, Success, WrongPassword, AccountMigrated, NotPremium, LoginRequired, InvalidToken, NullError };
+
+ ///
+ /// Allows to login to a premium Minecraft account using the Yggdrasil authentication scheme.
+ ///
+ /// Login
+ /// Password
+ /// Will contain the access token returned by Minecraft.net, if the login is successful
+ /// Will contain the client token generated before sending to Minecraft.net
+ /// Will contain the player's PlayerID, needed for multiplayer
+ /// Returns the status of the login (Success, Failure, etc.)
+
+ public static LoginResult GetLogin(string user, string pass, out SessionToken session)
+ {
+ session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
+
+ try
+ {
string result = "";
- string json_request = "{\"agent\": { \"name\": \"Minecraft\", \"version\": 1 }, \"username\": \"" + jsonEncode(user) + "\", \"password\": \"" + jsonEncode(pass) + "\", \"clientToken\": \"" + jsonEncode(session.ClientID) + "\" }";
- int code = doHTTPSPost("authserver.mojang.com", "/authenticate", json_request, ref result);
- if (code == 200)
- {
- if (result.Contains("availableProfiles\":[]}"))
- {
- return LoginResult.NotPremium;
- }
- else
- {
- string[] temp = result.Split(new string[] { "accessToken\":\"" }, StringSplitOptions.RemoveEmptyEntries);
- if (temp.Length >= 2) { session.ID = temp[1].Split('"')[0]; }
- temp = result.Split(new string[] { "name\":\"" }, StringSplitOptions.RemoveEmptyEntries);
- if (temp.Length >= 2) { session.PlayerName = temp[1].Split('"')[0]; }
- temp = result.Split(new string[] { "availableProfiles\":[{\"id\":\"" }, StringSplitOptions.RemoveEmptyEntries);
- if (temp.Length >= 2) { session.PlayerID = temp[1].Split('"')[0]; }
- return LoginResult.Success;
- }
- }
- else if (code == 403)
- {
- if (result.Contains("UserMigratedException"))
- {
- return LoginResult.AccountMigrated;
- }
- else return LoginResult.WrongPassword;
- }
- else if (code == 503)
- {
- return LoginResult.ServiceUnavailable;
- }
- else
- {
- ConsoleIO.WriteLineFormatted("§8Got error code from server: " + code);
- return LoginResult.OtherError;
- }
- }
- catch (System.Security.Authentication.AuthenticationException)
- {
- return LoginResult.SSLError;
- }
- catch (System.IO.IOException e)
- {
- if (e.Message.Contains("authentication"))
- {
- return LoginResult.SSLError;
- }
- else return LoginResult.OtherError;
- }
- catch
- {
- return LoginResult.OtherError;
- }
- }
-
- ///
- /// Validates whether accessToken must be refreshed
- ///
- /// Will contain the cached access token previously returned by Minecraft.net
- /// Will contain the cached client token created on login
- /// Returns the status of the token (Valid, Invalid, etc.)
- ///
+ string json_request = "{\"agent\": { \"name\": \"Minecraft\", \"version\": 1 }, \"username\": \"" + jsonEncode(user) + "\", \"password\": \"" + jsonEncode(pass) + "\", \"clientToken\": \"" + jsonEncode(session.ClientID) + "\" }";
+ int code = doHTTPSPost("authserver.mojang.com", "/authenticate", json_request, ref result);
+ if (code == 200)
+ {
+ if (result.Contains("availableProfiles\":[]}"))
+ {
+ return LoginResult.NotPremium;
+ }
+ else
+ {
+ string[] temp = result.Split(new string[] { "accessToken\":\"" }, StringSplitOptions.RemoveEmptyEntries);
+ if (temp.Length >= 2) { session.ID = temp[1].Split('"')[0]; }
+ temp = result.Split(new string[] { "name\":\"" }, StringSplitOptions.RemoveEmptyEntries);
+ if (temp.Length >= 2) { session.PlayerName = temp[1].Split('"')[0]; }
+ temp = result.Split(new string[] { "availableProfiles\":[{\"id\":\"" }, StringSplitOptions.RemoveEmptyEntries);
+ if (temp.Length >= 2) { session.PlayerID = temp[1].Split('"')[0]; }
+ return LoginResult.Success;
+ }
+ }
+ else if (code == 403)
+ {
+ if (result.Contains("UserMigratedException"))
+ {
+ return LoginResult.AccountMigrated;
+ }
+ else return LoginResult.WrongPassword;
+ }
+ else if (code == 503)
+ {
+ return LoginResult.ServiceUnavailable;
+ }
+ else
+ {
+ ConsoleIO.WriteLineFormatted("§8Got error code from server: " + code);
+ return LoginResult.OtherError;
+ }
+ }
+ catch (System.Security.Authentication.AuthenticationException)
+ {
+ return LoginResult.SSLError;
+ }
+ catch (System.IO.IOException e)
+ {
+ if (e.Message.Contains("authentication"))
+ {
+ return LoginResult.SSLError;
+ }
+ else return LoginResult.OtherError;
+ }
+ catch
+ {
+ return LoginResult.OtherError;
+ }
+ }
+
+ ///
+ /// Validates whether accessToken must be refreshed
+ ///
+ /// Will contain the cached access token previously returned by Minecraft.net
+ /// Will contain the cached client token created on login
+ /// Returns the status of the token (Valid, Invalid, etc.)
+ ///
public static LoginResult GetTokenValidation(SessionToken session)
{
- try
- {
- string result = "";
- string json_request = "{\"accessToken\": \"" + jsonEncode(session.ID) + "\", \"clientToken\": \"" + jsonEncode(session.ClientID) + "\" }";
- int code = doHTTPSPost("authserver.mojang.com", "/validate", json_request, ref result);
- if (code == 204)
- {
- return LoginResult.Success;
- }
- else if (code == 403)
- {
- return LoginResult.LoginRequired;
+ try
+ {
+ string result = "";
+ string json_request = "{\"accessToken\": \"" + jsonEncode(session.ID) + "\", \"clientToken\": \"" + jsonEncode(session.ClientID) + "\" }";
+ int code = doHTTPSPost("authserver.mojang.com", "/validate", json_request, ref result);
+ if (code == 204)
+ {
+ return LoginResult.Success;
+ }
+ else if (code == 403)
+ {
+ return LoginResult.LoginRequired;
}
else
{
return LoginResult.OtherError;
- }
- }
- catch
- {
- return LoginResult.OtherError;
- }
- }
-
- ///
- /// Refreshes invalid token
- ///
- /// Login
- /// Will contain the new access token returned by Minecraft.net, if the refresh is successful
- /// Will contain the client token generated before sending to Minecraft.net
- /// Will contain the player's PlayerID, needed for multiplayer
- /// Returns the status of the new token request (Success, Failure, etc.)
- ///
- public static LoginResult GetNewToken(SessionToken currentsession, out SessionToken newsession)
- {
- newsession = new SessionToken();
- try
- {
- string result = "";
- string json_request = "{ \"accessToken\": \"" + jsonEncode(currentsession.ID) + "\", \"clientToken\": \"" + jsonEncode(currentsession.ClientID) + "\", \"selectedProfile\": { \"id\": \"" + jsonEncode(currentsession.PlayerID) + "\", \"name\": \"" + jsonEncode(currentsession.PlayerName) + "\" } }";
- int code = doHTTPSPost("authserver.mojang.com", "/refresh", json_request, ref result);
- if (code == 200)
- {
- if (result == null)
- {
- return LoginResult.NullError;
- }
- else {
- string[] temp = result.Split(new string[] { "accessToken\":\"" }, StringSplitOptions.RemoveEmptyEntries);
- if (temp.Length >= 2) { newsession.ID = temp[1].Split('"')[0]; }
- temp = result.Split(new string[] { "clientToken\":\"" }, StringSplitOptions.RemoveEmptyEntries);
- if (temp.Length >= 2) { newsession.ClientID = temp[1].Split('"')[0]; }
- temp = result.Split(new string[] { "name\":\"" }, StringSplitOptions.RemoveEmptyEntries);
- if (temp.Length >= 2) { newsession.PlayerName = temp[1].Split('"')[0]; }
- temp = result.Split(new string[] { "selectedProfile\":[{\"id\":\"" }, StringSplitOptions.RemoveEmptyEntries);
- if (temp.Length >= 2) { newsession.PlayerID = temp[1].Split('"')[0]; }
- return LoginResult.Success;
- }
- }
- else if (code == 403 && result.Contains("InvalidToken"))
- {
- return LoginResult.InvalidToken;
- }
- else
- {
- ConsoleIO.WriteLineFormatted("§8Got error code from server while refreshing authentication: " + code);
- return LoginResult.OtherError;
}
}
catch
{
return LoginResult.OtherError;
}
- }
-
- ///
- /// Check session using Mojang's Yggdrasil authentication scheme. Allows to join an online-mode server
- ///
- /// Username
- /// Session ID
- /// Server ID
- /// TRUE if session was successfully checked
-
- public static bool SessionCheck(string uuid, string accesstoken, string serverhash)
- {
- try
- {
- string result = "";
- string json_request = "{\"accessToken\":\"" + accesstoken + "\",\"selectedProfile\":\"" + uuid + "\",\"serverId\":\"" + serverhash + "\"}";
- int code = doHTTPSPost("sessionserver.mojang.com", "/session/minecraft/join", json_request, ref result);
- return (result == "");
- }
- catch { return false; }
- }
-
- public static void RealmsListWorlds(string username, string uuid, string accesstoken)
- {
- string result = "";
- string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username, Program.MCHighestVersion);
- doHTTPSGet("mcoapi.minecraft.net", "/worlds", cookies, ref result);
- Console.WriteLine(result);
- }
-
- ///
- /// Make a HTTPS GET request to the specified endpoint of the Mojang API
- ///
- /// Host to connect to
- /// Endpoint for making the request
- /// Cookies for making the request
- /// Request result
- /// HTTP Status code
-
- private static int doHTTPSGet(string host, string endpoint, string cookies, ref string result)
- {
- List http_request = new List();
- http_request.Add("GET " + endpoint + " HTTP/1.1");
- http_request.Add("Cookie: " + cookies);
- http_request.Add("Cache-Control: no-cache");
- http_request.Add("Pragma: no-cache");
- http_request.Add("Host: " + host);
- http_request.Add("User-Agent: Java/1.6.0_27");
- http_request.Add("Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7");
- http_request.Add("Connection: close");
- http_request.Add("");
- return doHTTPSRequest(http_request, host, ref result);
- }
-
- ///
- /// Make a HTTPS POST request to the specified endpoint of the Mojang API
- ///
- /// Host to connect to
- /// Endpoint for making the request
- /// Request payload
- /// Request result
- /// HTTP Status code
-
- private static int doHTTPSPost(string host, string endpoint, string request, ref string result)
- {
- List http_request = new List();
- http_request.Add("POST " + endpoint + " HTTP/1.1");
- http_request.Add("Host: " + host);
- http_request.Add("User-Agent: MCC/" + Program.Version);
- http_request.Add("Content-Type: application/json");
- http_request.Add("Content-Length: " + Encoding.ASCII.GetBytes(request).Length);
- http_request.Add("Connection: close");
- http_request.Add("");
- http_request.Add(request);
- return doHTTPSRequest(http_request, host, ref result);
- }
-
- ///
- /// Manual HTTPS request since we must directly use a TcpClient because of the proxy.
- /// This method connects to the server, enables SSL, do the request and read the response.
- ///
- /// Request headers and optional body (POST)
- /// Host to connect to
- /// Request result
- /// HTTP Status code
-
- private static int doHTTPSRequest(List headers, string host, ref string result)
- {
- string postResult = null;
- int statusCode = 520;
- AutoTimeout.Perform(() =>
- {
- TcpClient client = ProxyHandler.newTcpClient(host, 443, true);
- SslStream stream = new SslStream(client.GetStream());
- stream.AuthenticateAsClient(host);
- stream.Write(Encoding.ASCII.GetBytes(String.Join("\r\n", headers.ToArray())));
- System.IO.StreamReader sr = new System.IO.StreamReader(stream);
- string raw_result = sr.ReadToEnd();
- if (raw_result.StartsWith("HTTP/1.1"))
- {
- postResult = raw_result.Substring(raw_result.IndexOf("\r\n\r\n") + 4);
- statusCode = Settings.str2int(raw_result.Split(' ')[1]);
- }
- else statusCode = 520; //Web server is returning an unknown error
- }, TimeSpan.FromSeconds(30));
- result = postResult;
- return statusCode;
- }
-
- ///
- /// Encode a string to a json string.
- /// Will convert special chars to \u0000 unicode escape sequences.
- ///
- /// Source text
- /// Encoded text
-
- private static string jsonEncode(string text)
- {
- StringBuilder result = new StringBuilder();
- foreach (char c in text)
- {
- if ((c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z'))
- {
- result.Append(c);
- }
- else
- {
- result.AppendFormat(@"\u{0:x4}", (int)c);
- }
- }
-
- return result.ToString();
- }
- }
-}
+ }
+
+ ///
+ /// Refreshes invalid token
+ ///
+ /// Login
+ /// Will contain the new access token returned by Minecraft.net, if the refresh is successful
+ /// Will contain the client token generated before sending to Minecraft.net
+ /// Will contain the player's PlayerID, needed for multiplayer
+ /// Returns the status of the new token request (Success, Failure, etc.)
+ ///
+ public static LoginResult GetNewToken(SessionToken currentsession, out SessionToken newsession)
+ {
+ newsession = new SessionToken();
+ try
+ {
+ string result = "";
+ string json_request = "{ \"accessToken\": \"" + jsonEncode(currentsession.ID) + "\", \"clientToken\": \"" + jsonEncode(currentsession.ClientID) + "\", \"selectedProfile\": { \"id\": \"" + jsonEncode(currentsession.PlayerID) + "\", \"name\": \"" + jsonEncode(currentsession.PlayerName) + "\" } }";
+ int code = doHTTPSPost("authserver.mojang.com", "/refresh", json_request, ref result);
+ if (code == 200)
+ {
+ if (result == null)
+ {
+ return LoginResult.NullError;
+ }
+ else {
+ string[] temp = result.Split(new string[] { "accessToken\":\"" }, StringSplitOptions.RemoveEmptyEntries);
+ if (temp.Length >= 2) { newsession.ID = temp[1].Split('"')[0]; }
+ temp = result.Split(new string[] { "clientToken\":\"" }, StringSplitOptions.RemoveEmptyEntries);
+ if (temp.Length >= 2) { newsession.ClientID = temp[1].Split('"')[0]; }
+ temp = result.Split(new string[] { "name\":\"" }, StringSplitOptions.RemoveEmptyEntries);
+ if (temp.Length >= 2) { newsession.PlayerName = temp[1].Split('"')[0]; }
+ temp = result.Split(new string[] { "selectedProfile\":[{\"id\":\"" }, StringSplitOptions.RemoveEmptyEntries);
+ if (temp.Length >= 2) { newsession.PlayerID = temp[1].Split('"')[0]; }
+ return LoginResult.Success;
+ }
+ }
+ else if (code == 403 && result.Contains("InvalidToken"))
+ {
+ return LoginResult.InvalidToken;
+ }
+ else
+ {
+ ConsoleIO.WriteLineFormatted("§8Got error code from server while refreshing authentication: " + code);
+ return LoginResult.OtherError;
+ }
+ }
+ catch
+ {
+ return LoginResult.OtherError;
+ }
+ }
+
+ ///
+ /// Check session using Mojang's Yggdrasil authentication scheme. Allows to join an online-mode server
+ ///
+ /// Username
+ /// Session ID
+ /// Server ID
+ /// TRUE if session was successfully checked
+
+ public static bool SessionCheck(string uuid, string accesstoken, string serverhash)
+ {
+ try
+ {
+ string result = "";
+ string json_request = "{\"accessToken\":\"" + accesstoken + "\",\"selectedProfile\":\"" + uuid + "\",\"serverId\":\"" + serverhash + "\"}";
+ int code = doHTTPSPost("sessionserver.mojang.com", "/session/minecraft/join", json_request, ref result);
+ return (result == "");
+ }
+ catch { return false; }
+ }
+
+ public static void RealmsListWorlds(string username, string uuid, string accesstoken)
+ {
+ string result = "";
+ string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username, Program.MCHighestVersion);
+ doHTTPSGet("mcoapi.minecraft.net", "/worlds", cookies, ref result);
+ Console.WriteLine(result);
+ }
+
+ ///
+ /// Make a HTTPS GET request to the specified endpoint of the Mojang API
+ ///
+ /// Host to connect to
+ /// Endpoint for making the request
+ /// Cookies for making the request
+ /// Request result
+ /// HTTP Status code
+
+ private static int doHTTPSGet(string host, string endpoint, string cookies, ref string result)
+ {
+ List http_request = new List();
+ http_request.Add("GET " + endpoint + " HTTP/1.1");
+ http_request.Add("Cookie: " + cookies);
+ http_request.Add("Cache-Control: no-cache");
+ http_request.Add("Pragma: no-cache");
+ http_request.Add("Host: " + host);
+ http_request.Add("User-Agent: Java/1.6.0_27");
+ http_request.Add("Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7");
+ http_request.Add("Connection: close");
+ http_request.Add("");
+ return doHTTPSRequest(http_request, host, ref result);
+ }
+
+ ///
+ /// Make a HTTPS POST request to the specified endpoint of the Mojang API
+ ///
+ /// Host to connect to
+ /// Endpoint for making the request
+ /// Request payload
+ /// Request result
+ /// HTTP Status code
+
+ private static int doHTTPSPost(string host, string endpoint, string request, ref string result)
+ {
+ List http_request = new List();
+ http_request.Add("POST " + endpoint + " HTTP/1.1");
+ http_request.Add("Host: " + host);
+ http_request.Add("User-Agent: MCC/" + Program.Version);
+ http_request.Add("Content-Type: application/json");
+ http_request.Add("Content-Length: " + Encoding.ASCII.GetBytes(request).Length);
+ http_request.Add("Connection: close");
+ http_request.Add("");
+ http_request.Add(request);
+ return doHTTPSRequest(http_request, host, ref result);
+ }
+
+ ///
+ /// Manual HTTPS request since we must directly use a TcpClient because of the proxy.
+ /// This method connects to the server, enables SSL, do the request and read the response.
+ ///
+ /// Request headers and optional body (POST)
+ /// Host to connect to
+ /// Request result
+ /// HTTP Status code
+
+ private static int doHTTPSRequest(List headers, string host, ref string result)
+ {
+ string postResult = null;
+ int statusCode = 520;
+ AutoTimeout.Perform(() =>
+ {
+ TcpClient client = ProxyHandler.newTcpClient(host, 443, true);
+ SslStream stream = new SslStream(client.GetStream());
+ stream.AuthenticateAsClient(host);
+ stream.Write(Encoding.ASCII.GetBytes(String.Join("\r\n", headers.ToArray())));
+ System.IO.StreamReader sr = new System.IO.StreamReader(stream);
+ string raw_result = sr.ReadToEnd();
+ if (raw_result.StartsWith("HTTP/1.1"))
+ {
+ postResult = raw_result.Substring(raw_result.IndexOf("\r\n\r\n") + 4);
+ statusCode = Settings.str2int(raw_result.Split(' ')[1]);
+ }
+ else statusCode = 520; //Web server is returning an unknown error
+ }, TimeSpan.FromSeconds(30));
+ result = postResult;
+ return statusCode;
+ }
+
+ ///
+ /// Encode a string to a json string.
+ /// Will convert special chars to \u0000 unicode escape sequences.
+ ///
+ /// Source text
+ /// Encoded text
+
+ private static string jsonEncode(string text)
+ {
+ StringBuilder result = new StringBuilder();
+ foreach (char c in text)
+ {
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z'))
+ {
+ result.Append(c);
+ }
+ else
+ {
+ result.AppendFormat(@"\u{0:x4}", (int)c);
+ }
+ }
+
+ return result.ToString();
+ }
+ }
+}
diff --git a/MinecraftClient/Protocol/SessionToken.cs b/MinecraftClient/Protocol/SessionToken.cs
index 2d48a704..d00824f9 100644
--- a/MinecraftClient/Protocol/SessionToken.cs
+++ b/MinecraftClient/Protocol/SessionToken.cs
@@ -1,14 +1,21 @@
using System;
-
namespace MinecraftClient.Protocol
{
[Serializable]
public class SessionToken
{
- public string ID { get; set; } = string.Empty;
- public string PlayerName { get; set; } = string.Empty;
- public string PlayerID { get; set; } = string.Empty;
- public string ClientID { get; set; } = string.Empty;
+ public string ID { get; set; }
+ public string PlayerName { get; set; }
+ public string PlayerID { get; set; }
+ public string ClientID { get; set; }
+
+ public SessionToken()
+ {
+ ID = String.Empty;
+ PlayerName = String.Empty;
+ PlayerID = String.Empty;
+ ClientID = String.Empty;
+ }
}
}