mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-09 07:09:41 -04:00
Help in GUI should also use Chat.Format and should still show ampersands that are not followed by a valid colour code
This commit is contained in:
parent
84da13d10a
commit
3bbfe03789
@ -112,7 +112,7 @@ namespace MCGalaxy.Gui {
|
|||||||
void GetHelp(string toHelp) {
|
void GetHelp(string toHelp) {
|
||||||
ConsoleHelpPlayer p = new ConsoleHelpPlayer();
|
ConsoleHelpPlayer p = new ConsoleHelpPlayer();
|
||||||
Command.Find("Help").Use(p, toHelp);
|
Command.Find("Help").Use(p, toHelp);
|
||||||
Popup.Message(Colors.Strip(p.Messages), "Help for /" + toHelp);
|
Popup.Message(Colors.StripUsed(p.Messages), "Help for /" + toHelp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +125,7 @@ namespace MCGalaxy.Gui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void Message(byte type, string message) {
|
public override void Message(byte type, string message) {
|
||||||
|
message = Chat.Format(message, this);
|
||||||
Messages += message + "\r\n";
|
Messages += message + "\r\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,8 +245,8 @@ namespace MCGalaxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Removes all instances of % or & and the character that follows.
|
/// <summary> Removes all occurrences of % or & and the following character. </summary>
|
||||||
/// Does *not* check if the character pair makes a real color </summary>
|
/// <remarks> Does NOT check if the following character is actually a valid color code. </remarks>
|
||||||
public static string Strip(string value) {
|
public static string Strip(string value) {
|
||||||
if (value.IndexOf('%') == -1 && value.IndexOf('&') == -1) return value;
|
if (value.IndexOf('%') == -1 && value.IndexOf('&') == -1) return value;
|
||||||
char[] output = new char[value.Length];
|
char[] output = new char[value.Length];
|
||||||
@ -255,7 +255,7 @@ namespace MCGalaxy {
|
|||||||
for (int i = 0; i < value.Length; i++) {
|
for (int i = 0; i < value.Length; i++) {
|
||||||
char token = value[i];
|
char token = value[i];
|
||||||
if (token == '%' || token == '&') {
|
if (token == '%' || token == '&') {
|
||||||
i++; // Skip over the following color code.
|
i++; // Skip over the following color code
|
||||||
} else {
|
} else {
|
||||||
output[usedChars++] = token;
|
output[usedChars++] = token;
|
||||||
}
|
}
|
||||||
@ -263,8 +263,7 @@ namespace MCGalaxy {
|
|||||||
return new string(output, 0, usedChars);
|
return new string(output, 0, usedChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Removes all colors that are currently used.
|
/// <summary> Removes all occurrences of % and & that are followed by a used color code. </summary>
|
||||||
/// This means % or & may be kept if they are not followed a used color code </summary>
|
|
||||||
public static string StripUsed(string message) {
|
public static string StripUsed(string message) {
|
||||||
if (message.IndexOf('%') == -1 && message.IndexOf('&') == -1) return message;
|
if (message.IndexOf('%') == -1 && message.IndexOf('&') == -1) return message;
|
||||||
char[] output = new char[message.Length];
|
char[] output = new char[message.Length];
|
||||||
@ -272,10 +271,9 @@ namespace MCGalaxy {
|
|||||||
|
|
||||||
for (int i = 0; i < message.Length; i++) {
|
for (int i = 0; i < message.Length; i++) {
|
||||||
char c = message[i];
|
char c = message[i];
|
||||||
if ( (i < message.Length-1) &&
|
if ((c == '%' || c == '&') && (i < message.Length - 1) &&
|
||||||
(c == '%' || c == '&') &&
|
(IsStandard(message[i+1]) || IsDefined(message[i+1]))) {
|
||||||
(IsStandard(message[i+1]) || IsDefined(message[i+1])) ) {
|
i++; // Skip over the following color code
|
||||||
i++; // Skip over the following color code.
|
|
||||||
} else {
|
} else {
|
||||||
output[usedChars++] = c;
|
output[usedChars++] = c;
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,12 @@ namespace MCGalaxy.Network {
|
|||||||
|
|
||||||
/// <summary> Abstracts sending to/receiving from a network socket. </summary>
|
/// <summary> Abstracts sending to/receiving from a network socket. </summary>
|
||||||
public abstract class INetSocket {
|
public abstract class INetSocket {
|
||||||
protected INetProtocol protocol;
|
protected INetProtocol protocol;
|
||||||
|
|
||||||
/// <summary> Whether the socket has been closed/disconnected. </summary>
|
/// <summary> Whether the socket has been closed/disconnected. </summary>
|
||||||
public bool Disconnected;
|
public bool Disconnected;
|
||||||
/// <summary> The IP address of the remote end (i.e. client) of the socket. </summary>
|
|
||||||
public string IP;
|
|
||||||
|
|
||||||
|
/// <summary> Gets the IP address of the remote end (i.e. client) of the socket. </summary>
|
||||||
|
public abstract string IP { get; }
|
||||||
/// <summary> Sets whether this socket operates in low-latency mode (e.g. for TCP, disabes nagle's algorithm). </summary>
|
/// <summary> Sets whether this socket operates in low-latency mode (e.g. for TCP, disabes nagle's algorithm). </summary>
|
||||||
public abstract bool LowLatency { set; }
|
public abstract bool LowLatency { set; }
|
||||||
|
|
||||||
@ -129,8 +128,6 @@ namespace MCGalaxy.Network {
|
|||||||
|
|
||||||
public TcpSocket(Socket s) {
|
public TcpSocket(Socket s) {
|
||||||
socket = s;
|
socket = s;
|
||||||
IP = ((IPEndPoint)s.RemoteEndPoint).Address.ToString();
|
|
||||||
|
|
||||||
recvArgs.UserToken = this;
|
recvArgs.UserToken = this;
|
||||||
recvArgs.SetBuffer(recvBuffer, 0, recvBuffer.Length);
|
recvArgs.SetBuffer(recvBuffer, 0, recvBuffer.Length);
|
||||||
sendArgs.UserToken = this;
|
sendArgs.UserToken = this;
|
||||||
@ -143,6 +140,9 @@ namespace MCGalaxy.Network {
|
|||||||
ReceiveNextAsync();
|
ReceiveNextAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string IP {
|
||||||
|
get { return ((IPEndPoint)socket.RemoteEndPoint).Address.ToString(); }
|
||||||
|
}
|
||||||
public override bool LowLatency { set { socket.NoDelay = value; } }
|
public override bool LowLatency { set { socket.NoDelay = value; } }
|
||||||
|
|
||||||
|
|
||||||
@ -266,13 +266,11 @@ namespace MCGalaxy.Network {
|
|||||||
public sealed class WebSocket : INetSocket, INetProtocol {
|
public sealed class WebSocket : INetSocket, INetProtocol {
|
||||||
readonly INetSocket s;
|
readonly INetSocket s;
|
||||||
|
|
||||||
public WebSocket(INetSocket socket) {
|
public WebSocket(INetSocket socket) { s = socket; }
|
||||||
IP = socket.IP;
|
|
||||||
s = socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init taken care by underlying socket
|
// Init taken care by underlying socket
|
||||||
public override void Init() { }
|
public override void Init() { }
|
||||||
|
public override string IP { get { return s.IP; } }
|
||||||
public override bool LowLatency { set { s.LowLatency = value; } }
|
public override bool LowLatency { set { s.LowLatency = value; } }
|
||||||
|
|
||||||
bool readingHeaders = true;
|
bool readingHeaders = true;
|
||||||
@ -501,7 +499,6 @@ namespace MCGalaxy.Network {
|
|||||||
SslStream ssl;
|
SslStream ssl;
|
||||||
|
|
||||||
public SecureSocket(INetSocket socket) {
|
public SecureSocket(INetSocket socket) {
|
||||||
IP = socket.IP;
|
|
||||||
raw = socket;
|
raw = socket;
|
||||||
|
|
||||||
wrapper = new WrapperStream();
|
wrapper = new WrapperStream();
|
||||||
@ -512,7 +509,8 @@ namespace MCGalaxy.Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init taken care by underlying socket
|
// Init taken care by underlying socket
|
||||||
public override void Init() { }
|
public override void Init() { }
|
||||||
|
public override string IP { get { return raw.IP; } }
|
||||||
public override bool LowLatency { set { raw.LowLatency = value; } }
|
public override bool LowLatency { set { raw.LowLatency = value; } }
|
||||||
public override void Close() { raw.Close(); }
|
public override void Close() { raw.Close(); }
|
||||||
public void Disconnect() { Close(); }
|
public void Disconnect() { Close(); }
|
||||||
|
217
MCGalaxy/Network/WebSocketProtocol.cs
Normal file
217
MCGalaxy/Network/WebSocketProtocol.cs
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy)
|
||||||
|
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||||
|
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||||
|
not use this file except in compliance with the Licenses. You may
|
||||||
|
obtain a copy of the Licenses at
|
||||||
|
http://www.opensource.org/licenses/ecl2.php
|
||||||
|
http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the Licenses are distributed on an "AS IS"
|
||||||
|
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
or implied. See the Licenses for the specific language governing
|
||||||
|
permissions and limitations under the Licenses.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
namespace MCGalaxy.Network {
|
||||||
|
|
||||||
|
/// <summary> Abstracts WebSocket protocol handling. </summary>
|
||||||
|
public abstract class WebSocket2 : INetProtocol {
|
||||||
|
bool readingHeaders = true;
|
||||||
|
bool conn, upgrade, version, proto;
|
||||||
|
string verKey;
|
||||||
|
|
||||||
|
void AcceptConnection() {
|
||||||
|
const string fmt =
|
||||||
|
"HTTP/1.1 101 Switching Protocols\r\n" +
|
||||||
|
"Upgrade: websocket\r\n" +
|
||||||
|
"Connection: Upgrade\r\n" +
|
||||||
|
"Sec-WebSocket-Accept: {0}\r\n" +
|
||||||
|
"Sec-WebSocket-Protocol: ClassiCube\r\n" +
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
string key = verKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||||
|
SHA1 sha = SHA1.Create();
|
||||||
|
byte[] raw = sha.ComputeHash(Encoding.ASCII.GetBytes(key));
|
||||||
|
|
||||||
|
string headers = String.Format(fmt, Convert.ToBase64String(raw));
|
||||||
|
SendData(Encoding.ASCII.GetBytes(headers));
|
||||||
|
readingHeaders = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessHeader(string raw) {
|
||||||
|
// end of headers
|
||||||
|
if (raw.Length == 0) {
|
||||||
|
if (conn && upgrade && version && proto && verKey != null) {
|
||||||
|
AcceptConnection();
|
||||||
|
} else {
|
||||||
|
// don't pretend to be a http server (so IP:port isn't marked as one by bots)
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sep = raw.IndexOf(':');
|
||||||
|
if (sep == -1) return; // not a proper header
|
||||||
|
string key = raw.Substring(0, sep);
|
||||||
|
string val = raw.Substring(sep + 1).Trim();
|
||||||
|
|
||||||
|
if (key.CaselessEq("Connection")) {
|
||||||
|
conn = val.CaselessContains("Upgrade");
|
||||||
|
} else if (key.CaselessEq("Upgrade")) {
|
||||||
|
upgrade = val.CaselessEq("websocket");
|
||||||
|
} else if (key.CaselessEq("Sec-WebSocket-Version")) {
|
||||||
|
version = val.CaselessEq("13");
|
||||||
|
} else if (key.CaselessEq("Sec-WebSocket-Key")) {
|
||||||
|
verKey = val;
|
||||||
|
} else if (key.CaselessEq("Sec-WebSocket-Protocol")) {
|
||||||
|
proto = val.CaselessEq("ClassiCube");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadHeaders(byte[] buffer, int bufferLen) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < bufferLen - 1; ) {
|
||||||
|
int end = -1;
|
||||||
|
|
||||||
|
// find end of header
|
||||||
|
for (int j = i; j < bufferLen - 1; j++) {
|
||||||
|
if (buffer[j] != '\r' || buffer[j + 1] != '\n') continue;
|
||||||
|
end = j; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end == -1) break;
|
||||||
|
string value = Encoding.ASCII.GetString(buffer, i, end - i);
|
||||||
|
ProcessHeader(value);
|
||||||
|
i = end + 2;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int state, opcode, frameLen, maskRead, frameRead;
|
||||||
|
byte[] mask = new byte[4], frame;
|
||||||
|
|
||||||
|
const int state_header1 = 0;
|
||||||
|
const int state_header2 = 1;
|
||||||
|
const int state_extLen1 = 2;
|
||||||
|
const int state_extLen2 = 3;
|
||||||
|
const int state_mask = 4;
|
||||||
|
const int state_data = 5;
|
||||||
|
|
||||||
|
void DecodeFrame() {
|
||||||
|
for (int i = 0; i < frameLen; i++) {
|
||||||
|
frame[i] ^= mask[i & 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
// TODO: reply to ping frames
|
||||||
|
case 0x00:
|
||||||
|
case 0x02:
|
||||||
|
if (frameLen == 0) return;
|
||||||
|
HandleReceived(frame, frameLen);
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
// Connection is getting closed
|
||||||
|
Disconnect(1000); break;
|
||||||
|
default:
|
||||||
|
Disconnect(1003); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProcessData(byte[] data, int offset, int len) {
|
||||||
|
switch (state) {
|
||||||
|
case state_header1:
|
||||||
|
if (offset >= len) break;
|
||||||
|
opcode = data[offset++] & 0x0F;
|
||||||
|
state = state_header2;
|
||||||
|
goto case state_header2;
|
||||||
|
|
||||||
|
case state_header2:
|
||||||
|
if (offset >= len) break;
|
||||||
|
int flags = data[offset++] & 0x7F;
|
||||||
|
|
||||||
|
if (flags == 127) {
|
||||||
|
// unsupported 8 byte extended length
|
||||||
|
Disconnect(1009);
|
||||||
|
return len;
|
||||||
|
} else if (flags == 126) {
|
||||||
|
// two byte extended length
|
||||||
|
state = state_extLen1;
|
||||||
|
goto case state_extLen1;
|
||||||
|
} else {
|
||||||
|
// length is inline
|
||||||
|
frameLen = flags;
|
||||||
|
state = state_mask;
|
||||||
|
goto case state_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
case state_extLen1:
|
||||||
|
if (offset >= len) break;
|
||||||
|
frameLen = data[offset++] << 8;
|
||||||
|
state = state_extLen2;
|
||||||
|
goto case state_extLen2;
|
||||||
|
|
||||||
|
case state_extLen2:
|
||||||
|
if (offset >= len) break;
|
||||||
|
frameLen |= data[offset++];
|
||||||
|
state = state_mask;
|
||||||
|
goto case state_mask;
|
||||||
|
|
||||||
|
case state_mask:
|
||||||
|
for (; maskRead < 4; maskRead++) {
|
||||||
|
if (offset >= len) return offset;
|
||||||
|
mask[maskRead] = data[offset++];
|
||||||
|
}
|
||||||
|
|
||||||
|
state = state_data;
|
||||||
|
goto case state_data;
|
||||||
|
|
||||||
|
case state_data:
|
||||||
|
if (frame == null || frameLen > frame.Length) frame = new byte[frameLen];
|
||||||
|
int copy = Math.Min(len - offset, frameLen - frameRead);
|
||||||
|
|
||||||
|
Buffer.BlockCopy(data, offset, frame, frameRead, copy);
|
||||||
|
offset += copy; frameRead += copy;
|
||||||
|
|
||||||
|
if (frameRead == frameLen) {
|
||||||
|
DecodeFrame();
|
||||||
|
maskRead = 0;
|
||||||
|
frameRead = 0;
|
||||||
|
state = state_header1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int INetProtocol.ProcessReceived(byte[] buffer, int bufferLen) {
|
||||||
|
int offset = 0;
|
||||||
|
if (readingHeaders) {
|
||||||
|
offset = ReadHeaders(buffer, bufferLen);
|
||||||
|
if (readingHeaders) return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset < bufferLen) {
|
||||||
|
offset = ProcessData(buffer, offset, bufferLen);
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect() { Disconnect(1000); }
|
||||||
|
|
||||||
|
protected abstract void HandleReceived(byte[] data, int len);
|
||||||
|
|
||||||
|
protected abstract void Disconnect(int reason);
|
||||||
|
|
||||||
|
protected abstract void SendData(byte[] data);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user