Don't convert percents to ampersands when part of url, fixes #420.

This commit is contained in:
UnknownShadow200 2017-09-01 14:25:22 +10:00
parent 5ee8c9c576
commit a933a360f8
3 changed files with 47 additions and 18 deletions

View File

@ -26,6 +26,8 @@ namespace MCGalaxy.Gui {
public static void Format(string message, Action<char, string> output) {
int index = 0;
char col = 'S';
message = Colors.Escape(message);
while (index < message.Length)
OutputPart(ref col, ref index, message, output);
}
@ -47,7 +49,7 @@ namespace MCGalaxy.Gui {
static int Next(int start, string message) {
for (int i = start; i < message.Length; i++) {
if (!(message[i] == '&' || message[i] == '%')) continue;
if (message[i] != '&') continue;
// No colour code follows this
if (i == message.Length - 1) return -1;

View File

@ -189,26 +189,53 @@ namespace MCGalaxy {
/// <summary> Converts percentage color codes to their actual/real color codes. </summary>
/// <remarks> Does not escape percentage codes that are part of urls. </remarks>
public static string Escape(string value) {
if (value.IndexOf('%') == -1) return value;
char[] chars = new char[value.Length];
for (int i = 0; i < chars.Length; i++) { chars[i] = value[i]; }
for (int i = 0; i < value.Length; i++ ) {
char c = value[i];
bool validCode = c == '%' && i < value.Length - 1;
if (!validCode) { chars[i] = c; continue; }
for (int i = 0; i < chars.Length;) {
int end = value.IndexOf(' ', i);
if (end == -1) end = value.Length;
char color = value[i + 1];
if (Map(ref color)) {
chars[i] = '&';
chars[i + 1] = color;
i++; continue;
}
chars[i] = '%';
if (!IsUrlAt(chars, i, end - i)) Escape(chars, i, end);
i = end + 1;
}
return new string(chars);
}
static bool IsUrlAt(char[] chars, int i, int len) {
const int prefixLen = 7; // "http://".Length
if (len < prefixLen) return false;
// skip color codes in url
while (len > 0 && chars[i] == '&') { len -= 2; i += 2; }
// Starts with "http" ?
if (len < prefixLen) return false;
if (chars[i] != 'h' || chars[i + 1] != 't' || chars[i + 2] != 't' || chars[i + 3] != 'p') return false;
len -= 4; i += 4;
// And then with "s://" or "://" ?
if (len >= 4 && chars[i] == 's' && chars[i + 1] == ':' && chars[i + 2] == '/' && chars[i + 3] == '/') return true;
if (len >= 3 && chars[i] == ':' && chars[i + 1] == '/' && chars[i + 2] == '/') return true;
return false;
}
static void Escape(char[] chars, int start, int end) {
for (int i = start; i < end; i++ ) {
char c = chars[i];
bool validCode = c == '%' && i < chars.Length - 1;
if (!validCode) continue;
char color = chars[i + 1];
if (!Map(ref color)) continue;
chars[i] = '&'; i++; // skip over color code
}
}
/// <summary> Removes all percentage and actual color codes from the given string. </summary>
public static string Strip(string value) {
if (value.IndexOf('%') == -1 && value.IndexOf('&') == -1) return value;
@ -320,7 +347,7 @@ namespace MCGalaxy {
}
}
/// <summary> Describes information about a color code. </summary>
/// <summary> Describes information about a color code. </summary>
public struct ColorDesc {
public char Code, Fallback;
public byte R, G, B, A;

View File

@ -33,10 +33,10 @@ namespace MCGalaxy.Commands.Maintenance {
if (!Formatter.ValidName(p, args[1], "player")) return;
if (PlayerInfo.FindExact(args[0]) != null) {
Player.Message(p, "\"{0}\" must be offline to use /infoswap.", args[0]); return;
Player.Message(p, "\"{0}\" must be offline to use %T/InfoSwap", args[0]); return;
}
if (PlayerInfo.FindExact(args[1]) != null) {
Player.Message(p, "\"{0}\" must be offline to use /infoswap.", args[1]); return;
Player.Message(p, "\"{0}\" must be offline to use %T/InfoSwap", args[1]); return;
}
string src = PlayerInfo.FindName(args[0]);
@ -51,10 +51,10 @@ namespace MCGalaxy.Commands.Maintenance {
Group srcGroup = Group.GroupIn(src);
Group dstGroup = Group.GroupIn(dst);
if (p != null && srcGroup.Permission >= p.Rank) {
Player.Message(p, "Cannot /infoswap for a player ranked equal or higher to yours."); return;
Player.Message(p, "Cannot %T/InfoSwap %Sfor a player ranked equal or higher to yours."); return;
}
if (p != null && dstGroup.Permission >= p.Rank) {
Player.Message(p, "Cannot /infoswap for a player ranked equal or higher to yours."); return;
Player.Message(p, "Cannot %T/InfoSwap %Sfor a player ranked equal or higher to yours."); return;
}
SwapStats(src, dst);