· 8 years ago · Jan 26, 2018, 11:36 PM
1/*
2 * Copyright (c) 2011 Markus Olsson
3 * var mail = string.Join(".", new string[] {"j", "markus", "olsson"}) + string.Concat('@', "gmail.com");
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
6 * software and associated documentation files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
15 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 */
20
21
22using System;
23using System.Globalization;
24using System.Linq;
25using System.Text;
26using System.Net.Mime;
27
28namespace freakcode.Utilities
29{
30 public static class ContentDispositionUtils
31 {
32 // A bunch of characters most likely to be forbidden (or be troublesome to use) in a file system
33 private static char[] invalids = "<>:\"/\\|?*~".ToCharArray();
34
35 // We try to prevent theese characters from repeating in the resulting string.
36 private static char[] spacingCharacters = { ' ', '_', '-' };
37
38 /// <summary>
39 /// Normalizes the given file name removing diacritics and special characters so as to maximize
40 /// the compatibility with user agents regardless of system charsets. Note that this method does produce
41 /// a strictly compliant header since it will not quote the string if neccessary. Use the GetHeaderValue
42 /// in order to produce a proper header value for use directly with an HttpResponse. The return value
43 /// of this method can be used directly with the File* actionresults in ASP.NET MVC.
44 /// </summary>
45 /// <example>
46 /// Will convert "Übername / document.pdf" to "Ubername document.pdf" and "c:\foobar.pdf" to "c_foobar.pdf"
47 /// </example>
48 /// <exception cref="ArgumentNullException">fileName was null</exception>
49 /// <exception cref="ArgumentException">fileName contained invalid Unicode characters.</exception>
50 public static string NormalizeFileName(string fileName)
51 {
52 if (fileName == null)
53 throw new ArgumentNullException("fileName");
54
55 if (fileName.Length == 0)
56 return string.Empty;
57
58 // Normalize string in order to remove diacritics. This will convert
59 // the string into a fully canonical form; ie Åäö will be converted to A°a¨o¨
60 char[] normalized = fileName.Normalize(NormalizationForm.FormD).ToCharArray();
61
62 // Set up a buffer for our return string that is at most (in case there's no diacritics and no forbidden characters)
63 // the same length as our normalized string.
64 char[] buf = new char[normalized.Length];
65 int p = 0;
66
67 for (int i = 0; i < normalized.Length; i++)
68 {
69 char c = normalized[i];
70
71 // Remove all non spacing marks (ie modifiers to base characters, umlauts and such);
72 if (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.NonSpacingMark)
73 continue;
74
75 // Strip special characters and commonly forbidden file system characters
76 if (c < 32 || c > 126 || invalids.Contains(c))
77 c = '_';
78
79 // Prevent repeating spacing characters
80 if (p != 0 && spacingCharacters.Contains(c) && spacingCharacters.Contains(buf[p - 1]))
81 continue;
82
83 buf[p++] = c;
84 }
85
86 return new string(buf, 0, p);
87 }
88
89 /// <summary>
90 /// Returns a content-disposition attachment header value with a filename parameter containing
91 /// a normalized form of the provided filename (see NormalizeFileName for more information).
92 /// </summary>
93 /// <exception cref="ArgumentNullException">fileName was null</exception>
94 /// <exception cref="ArgumentException">fileName contained invalid Unicode characters.</exception>
95 public static string GetHeaderValue(string fileName)
96 {
97 if (fileName == null)
98 throw new ArgumentNullException("fileName");
99
100 var header = new ContentDisposition
101 {
102 FileName = NormalizeFileName(fileName)
103 };
104
105 return header.ToString();
106 }
107 }
108}