mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-08 22:59:29 -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) {
|
||||
ConsoleHelpPlayer p = new ConsoleHelpPlayer();
|
||||
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) {
|
||||
message = Chat.Format(message, this);
|
||||
Messages += message + "\r\n";
|
||||
}
|
||||
}
|
||||
|
@ -245,8 +245,8 @@ namespace MCGalaxy {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Removes all instances of % or & and the character that follows.
|
||||
/// Does *not* check if the character pair makes a real color </summary>
|
||||
/// <summary> Removes all occurrences of % or & and the following character. </summary>
|
||||
/// <remarks> Does NOT check if the following character is actually a valid color code. </remarks>
|
||||
public static string Strip(string value) {
|
||||
if (value.IndexOf('%') == -1 && value.IndexOf('&') == -1) return value;
|
||||
char[] output = new char[value.Length];
|
||||
@ -255,7 +255,7 @@ namespace MCGalaxy {
|
||||
for (int i = 0; i < value.Length; i++) {
|
||||
char token = value[i];
|
||||
if (token == '%' || token == '&') {
|
||||
i++; // Skip over the following color code.
|
||||
i++; // Skip over the following color code
|
||||
} else {
|
||||
output[usedChars++] = token;
|
||||
}
|
||||
@ -263,8 +263,7 @@ namespace MCGalaxy {
|
||||
return new string(output, 0, usedChars);
|
||||
}
|
||||
|
||||
/// <summary> Removes all colors that are currently used.
|
||||
/// This means % or & may be kept if they are not followed a used color code </summary>
|
||||
/// <summary> Removes all occurrences of % and & that are followed by a used color code. </summary>
|
||||
public static string StripUsed(string message) {
|
||||
if (message.IndexOf('%') == -1 && message.IndexOf('&') == -1) return message;
|
||||
char[] output = new char[message.Length];
|
||||
@ -272,10 +271,9 @@ namespace MCGalaxy {
|
||||
|
||||
for (int i = 0; i < message.Length; i++) {
|
||||
char c = message[i];
|
||||
if ( (i < message.Length-1) &&
|
||||
(c == '%' || c == '&') &&
|
||||
(IsStandard(message[i+1]) || IsDefined(message[i+1])) ) {
|
||||
i++; // Skip over the following color code.
|
||||
if ((c == '%' || c == '&') && (i < message.Length - 1) &&
|
||||
(IsStandard(message[i+1]) || IsDefined(message[i+1]))) {
|
||||
i++; // Skip over the following color code
|
||||
} else {
|
||||
output[usedChars++] = c;
|
||||
}
|
||||
|
@ -27,13 +27,12 @@ namespace MCGalaxy.Network {
|
||||
|
||||
/// <summary> Abstracts sending to/receiving from a network socket. </summary>
|
||||
public abstract class INetSocket {
|
||||
protected INetProtocol protocol;
|
||||
|
||||
protected INetProtocol protocol;
|
||||
/// <summary> Whether the socket has been closed/disconnected. </summary>
|
||||
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>
|
||||
public abstract bool LowLatency { set; }
|
||||
|
||||
@ -129,8 +128,6 @@ namespace MCGalaxy.Network {
|
||||
|
||||
public TcpSocket(Socket s) {
|
||||
socket = s;
|
||||
IP = ((IPEndPoint)s.RemoteEndPoint).Address.ToString();
|
||||
|
||||
recvArgs.UserToken = this;
|
||||
recvArgs.SetBuffer(recvBuffer, 0, recvBuffer.Length);
|
||||
sendArgs.UserToken = this;
|
||||
@ -143,6 +140,9 @@ namespace MCGalaxy.Network {
|
||||
ReceiveNextAsync();
|
||||
}
|
||||
|
||||
public override string IP {
|
||||
get { return ((IPEndPoint)socket.RemoteEndPoint).Address.ToString(); }
|
||||
}
|
||||
public override bool LowLatency { set { socket.NoDelay = value; } }
|
||||
|
||||
|
||||
@ -266,13 +266,11 @@ namespace MCGalaxy.Network {
|
||||
public sealed class WebSocket : INetSocket, INetProtocol {
|
||||
readonly INetSocket s;
|
||||
|
||||
public WebSocket(INetSocket socket) {
|
||||
IP = socket.IP;
|
||||
s = socket;
|
||||
}
|
||||
public WebSocket(INetSocket socket) { s = socket; }
|
||||
|
||||
// Init taken care by underlying socket
|
||||
public override void Init() { }
|
||||
public override string IP { get { return s.IP; } }
|
||||
public override bool LowLatency { set { s.LowLatency = value; } }
|
||||
|
||||
bool readingHeaders = true;
|
||||
@ -501,7 +499,6 @@ namespace MCGalaxy.Network {
|
||||
SslStream ssl;
|
||||
|
||||
public SecureSocket(INetSocket socket) {
|
||||
IP = socket.IP;
|
||||
raw = socket;
|
||||
|
||||
wrapper = new WrapperStream();
|
||||
@ -512,7 +509,8 @@ namespace MCGalaxy.Network {
|
||||
}
|
||||
|
||||
// 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 void Close() { raw.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