using System; using System.Collections.Generic; using System.Linq; using System.Net.Mime; using System.Text; using System.Threading.Tasks; using Nancy; namespace Sony.Filtr.AdminAPI.Utility { public static class NancyExtensions { public static Response WithContentDispositionFileName(this Response response, string filename) { return response.WithHeader("Content-disposition", GetHeaderValue(filename)); } private static string GetHeaderValue(string fileName) { foreach (int num in fileName) { if (num > (int)sbyte.MaxValue) return CreateRfc2231HeaderValue(fileName); } return $"attachment; filename=\"{fileName}\""; } private static string CreateRfc2231HeaderValue(string filename) { StringBuilder builder = new StringBuilder("attachment; filename*=UTF-8''"); foreach (byte b in Encoding.UTF8.GetBytes(filename)) { if (IsByteValidHeaderValueCharacter(b)) builder.Append((char)b); else AddByteToStringBuilder(b, builder); } return builder.ToString(); } private static void AddByteToStringBuilder(byte b, StringBuilder builder) { builder.Append('%'); int num = (int)b; AddHexDigitToStringBuilder(num >> 4, builder); AddHexDigitToStringBuilder(num % 16, builder); } private static void AddHexDigitToStringBuilder(int digit, StringBuilder builder) { builder.Append("0123456789ABCDEF"[digit]); } private static bool IsByteValidHeaderValueCharacter(byte b) { if (48 <= b && b <= 57 || 97 <= b && b <= 122 || 65 <= b && b <= 90) return true; byte num = b; if (num <= 46U) { switch (num) { case 33: case 36: case 38: case 43: case 45: case 46: break; default: goto label_6; } } else if (num != 58 && (int)num != 95 && (int)num != 126) goto label_6; return true; label_6: return false; } } }