/// <summary> /// UrlDecodes a string except chars forbidden in Windows filepaths /// </summary> 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; // per char for (int i = 0; i < length; i++) { char ch = url[i]; // PLUS char converts to SPACE if (ch == '+') { ch = ' '; // SPECIAL chars encoded in "%20" format } else if ((ch == '%') && (i < (length - 2))) { // unicode char (4 digit hex) if ((url[i + 1] == 'u') && (i < (length - 5))) { int num3 = HexToInt(url[i + 2]); int num4 = HexToInt(url[i + 3]); int num5 = HexToInt(url[i + 4]); int num6 = HexToInt(url[i + 5]); if (((num3 < 0) || (num4 < 0)) || ((num5 < 0) || (num6 < 0))) { goto Label_010B; } ch = (char)((((num3 << 12) | (num4 << 8)) | (num5 << 4)) | num6); i += 5; decoder.FlushBytes(false); // dont check previous stuff decoder.AddChar(ch, true); // CHECK IF CHAR OK WITH FILEPATH continue; } // ascii char (2 digit hex) int num7 = HexToInt(url[i + 1]); int num8 = HexToInt(url[i + 2]); if ((num7 >= 0) && (num8 >= 0)) { byte b = (byte)((num7 << 4) | num8); i += 2; decoder.FlushBytes(false); // dont check previous stuff decoder.AddByte(b); // check if unicode char ("%11%11") if (((i + 1) < (length - 2)) && (url[i + 1] == '%')) { // YES, unicode char num7 = HexToInt(url[i + 1]); num8 = HexToInt(url[i + 2]); if ((num7 >= 0) && (num8 >= 0)) { b = (byte)((num7 << 4) | num8); i += 2; decoder.AddByte(b); decoder.FlushBytes(true); // CHECK IF CHARS OK WITH FILEPATHS } } else { // NO, not unicode char decoder.FlushBytes(true); // CHECK IF CHARS OK WITH FILEPATHS } continue; } } Label_010B: if ((ch & 0xff80) == 0) { decoder.AddByte((byte)ch); } else { decoder.AddChar(ch, false); } } return(decoder.GetString()); }