// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Text; namespace osu.Framework.IO.Network { public static class UrlEncoding { public static string UrlEncode(string str) { if (str == null) { return null; } return UrlEncode(str, Encoding.UTF8, false); } public static string UrlEncodeParam(string str) { if (str == null) { return null; } return UrlEncode(str, Encoding.UTF8, true); } public static string UrlEncode(string str, Encoding e, bool paramEncode) { if (str == null) { return null; } return Encoding.ASCII.GetString(UrlEncodeToBytes(str, e, paramEncode)); } public static byte[] UrlEncodeToBytes(string str, Encoding e, bool paramEncode) { if (str == null) { return null; } byte[] bytes = e.GetBytes(str); return urlEncodeBytesToBytesPublic(bytes, 0, bytes.Length, false, paramEncode); } private static byte[] urlEncodeBytesToBytesPublic(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue, bool paramEncode) { int num = 0; int num2 = 0; for (int i = 0; i < count; i++) { char ch = (char)bytes[offset + i]; if (paramEncode && ch == ' ') { num++; } else if (!IsSafe(ch)) { num2++; } } if (!alwaysCreateReturnValue && num == 0 && num2 == 0) { return bytes; } byte[] buffer = new byte[count + num2 * 2]; int num4 = 0; for (int j = 0; j < count; j++) { byte num6 = bytes[offset + j]; char ch2 = (char)num6; if (IsSafe(ch2)) { buffer[num4++] = num6; } else if (paramEncode && ch2 == ' ') { buffer[num4++] = 0x2b; } else { buffer[num4++] = 0x25; buffer[num4++] = (byte)IntToHex((num6 >> 4) & 15); buffer[num4++] = (byte)IntToHex(num6 & 15); } } return buffer; } public static bool IsSafe(char ch) { if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9') { return true; } switch (ch) { case '\'': case '(': case ')': case '*': case '-': case '.': case '_': case '!': return true; } return false; } public static char IntToHex(int n) { if (n <= 9) { return (char)(n + 0x30); } return (char)(n - 10 + 0x61); } } }