using System; using System.Text; namespace prBrowser { internal static class URLUtils { private class UrlDecoder { private int _bufferSize; private byte[] _byteBuffer; private char[] _charBuffer; private Encoding _encoding; private int _numBytes; private int _numChars; public bool forFilePaths = false; internal UrlDecoder(int bufferSize, Encoding encoding) { _bufferSize = bufferSize; _encoding = encoding; _charBuffer = new char[bufferSize]; } internal void AddByte(byte b) { if (_byteBuffer == null) { _byteBuffer = new byte[_bufferSize]; } _byteBuffer[_numBytes++] = b; } internal void AddChar(char ch, bool checkChar = false) { if (_numBytes > 0) { FlushBytes(); } if (checkChar && forFilePaths && !ch.SupportedInFilePath()) { AddChar('_'); int num = ch; AddString("0x" + num.ToString("X")); AddChar('_'); } else { _charBuffer[_numChars++] = ch; } } internal void AddString(string str) { if (_numBytes > 0) { FlushBytes(); } foreach (char ch in str) { _charBuffer[_numChars++] = ch; } } public void FlushBytes(bool checkChar = false) { if (_numBytes <= 0) { return; } if (checkChar && forFilePaths) { char[] newChars = _encoding.GetChars(_byteBuffer, 0, _numBytes); _numBytes = 0; char[] array = newChars; foreach (char ch in array) { AddChar(ch); } } else { _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars); _numBytes = 0; } } internal string GetString() { if (_numBytes > 0) { FlushBytes(); } if (_numChars > 0) { return new string(_charBuffer, 0, _numChars); } return string.Empty; } } public static string PathToURL(this string filePath, string removeBaseDir = null) { if (!filePath.CheckIfValid()) { return ""; } return "file:///" + filePath.Replace("\\", "/"); } public static bool IsURLOfflineFile(this string url) { return url.StartsWith("file://", StringComparison.Ordinal); } public static bool IsURLLocalhost(this string url) { return url.BeginsWith("http://localhost") || url.BeginsWith("localhost"); } public static string DecodeURL(this string url) { if (url == null) { return null; } int length = url.Length; UrlDecoder decoder = new UrlDecoder(length, Encoding.UTF8); for (int i = 0; i < length; i++) { char ch = url[i]; if (ch == '+') { ch = ' '; } else if (ch == '%' && i < length - 2) { if (url[i + 1] == 'u' && i < length - 5) { int num3 = url[i + 2].HexToInt(); int num4 = url[i + 3].HexToInt(); int num5 = url[i + 4].HexToInt(); int num6 = url[i + 5].HexToInt(); if (num3 >= 0 && num4 >= 0 && num5 >= 0 && num6 >= 0) { ch = (char)((num3 << 12) | (num4 << 8) | (num5 << 4) | num6); i += 5; decoder.AddChar(ch); continue; } } else { int num7 = url[i + 1].HexToInt(); int num8 = url[i + 2].HexToInt(); if (num7 >= 0 && num8 >= 0) { byte b = (byte)((num7 << 4) | num8); i += 2; decoder.AddByte(b); continue; } } } if ((ch & 0xFF80) == 0) { decoder.AddByte((byte)ch); } else { decoder.AddChar(ch); } } return decoder.GetString(); } public static int HexToInt(this char hex) { if (hex >= '0' && hex <= '9') { return hex - 48; } if (hex >= 'a' && hex <= 'f') { return hex - 97 + 10; } if (hex >= 'A' && hex <= 'F') { return hex - 65 + 10; } return -1; } public static string DecodeURLForFilepath(this string url) { if (url == null) { return null; } int length = url.Length; UrlDecoder decoder = new UrlDecoder(length * 10, Encoding.UTF8); decoder.forFilePaths = true; for (int i = 0; i < length; i++) { char ch = url[i]; if (ch == '+') { ch = ' '; } else if (ch == '%' && i < length - 2) { if (url[i + 1] == 'u' && i < length - 5) { int num3 = url[i + 2].HexToInt(); int num4 = url[i + 3].HexToInt(); int num5 = url[i + 4].HexToInt(); int num6 = url[i + 5].HexToInt(); if (num3 >= 0 && num4 >= 0 && num5 >= 0 && num6 >= 0) { ch = (char)((num3 << 12) | (num4 << 8) | (num5 << 4) | num6); i += 5; decoder.FlushBytes(); decoder.AddChar(ch, checkChar: true); continue; } } else { int num7 = url[i + 1].HexToInt(); int num8 = url[i + 2].HexToInt(); if (num7 >= 0 && num8 >= 0) { byte b = (byte)((num7 << 4) | num8); i += 2; decoder.FlushBytes(); decoder.AddByte(b); if (i + 1 < length - 2 && url[i + 1] == '%') { num7 = url[i + 1].HexToInt(); num8 = url[i + 2].HexToInt(); if (num7 >= 0 && num8 >= 0) { b = (byte)((num7 << 4) | num8); i += 2; decoder.AddByte(b); decoder.FlushBytes(checkChar: true); } } else { decoder.FlushBytes(checkChar: true); } continue; } } } if ((ch & 0xFF80) == 0) { decoder.AddByte((byte)ch); } else { decoder.AddChar(ch); } } return decoder.GetString(); } public static string EncodeURL(this string text) { return Uri.EscapeDataString(text); } } }