~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to src/AddIns/Misc/Reports/ICSharpCode.Reports.Core/Project/Globals/FileUtility.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
 
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
 
3
 
 
4
using System;
 
5
using System.Collections.Generic;
 
6
using System.IO;
 
7
using System.Text;
 
8
using System.Text.RegularExpressions;
 
9
using System.Windows.Forms;
 
10
 
 
11
using Microsoft.Win32;
 
12
 
 
13
namespace ICSharpCode.Reports.Core.Globals
 
14
{
 
15
        /// <summary>
 
16
        /// A utility class related to file utilities.
 
17
        /// </summary>
 
18
        public sealed class FileUtility
 
19
        {
 
20
                readonly static char[] separators = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar, Path.VolumeSeparatorChar };
 
21
                const string fileNameRegEx = @"^([a-zA-Z]:)?[^:]+$";
 
22
                // This is an arbitrary limitation built into the .NET Framework.
 
23
                // Windows supports paths up to 32k length.
 
24
                public const int MaxPathLength = 260;
 
25
                
 
26
                private FileUtility()
 
27
                {
 
28
                }
 
29
                
 
30
                public static string Combine(params string[] paths)
 
31
                {
 
32
                        if (paths == null || paths.Length == 0) {
 
33
                                return String.Empty;
 
34
                        }
 
35
                        
 
36
                        string result = paths[0];
 
37
                        for (int i = 1; i < paths.Length; i++) {
 
38
                                result = Path.Combine(result, paths[i]);
 
39
                        }
 
40
                        return result;
 
41
                }
 
42
                
 
43
                public static bool IsUrl(string path)
 
44
                {
 
45
                        return path.IndexOf(':') >= 2;
 
46
                }
 
47
                
 
48
                /// <summary>
 
49
                /// Converts a given absolute path and a given base path to a path that leads
 
50
                /// from the base path to the absoulte path. (as a relative path)
 
51
                /// </summary>
 
52
                public static string GetRelativePath(string baseDirectoryPath, string absPath)
 
53
                {
 
54
                        if (IsUrl(absPath) || IsUrl(baseDirectoryPath)){
 
55
                                return absPath;
 
56
                        }
 
57
                        
 
58
                        baseDirectoryPath = NormalizePath(baseDirectoryPath);
 
59
                        absPath           = NormalizePath(absPath);
 
60
                        
 
61
                        string[] bPath = baseDirectoryPath.Split(separators);
 
62
                        string[] aPath = absPath.Split(separators);
 
63
                        int indx = 0;
 
64
                        for(; indx < Math.Min(bPath.Length, aPath.Length); ++indx){
 
65
                                if(!bPath[indx].Equals(aPath[indx], StringComparison.OrdinalIgnoreCase))
 
66
                                        break;
 
67
                        }
 
68
                        
 
69
                        if (indx == 0) {
 
70
                                return absPath;
 
71
                        }
 
72
                        
 
73
                        StringBuilder erg = new StringBuilder();
 
74
                        
 
75
                        if(indx == bPath.Length) {
 
76
//                              erg.Append('.');
 
77
//                              erg.Append(Path.DirectorySeparatorChar);
 
78
                        } else {
 
79
                                for (int i = indx; i < bPath.Length; ++i) {
 
80
                                        erg.Append("..");
 
81
                                        erg.Append(Path.DirectorySeparatorChar);
 
82
                                }
 
83
                        }
 
84
                        erg.Append(String.Join(Path.DirectorySeparatorChar.ToString(), aPath, indx, aPath.Length-indx));
 
85
                        return erg.ToString();
 
86
                }
 
87
                
 
88
                /// <summary>
 
89
                /// Converts a given relative path and a given base path to a path that leads
 
90
                /// to the relative path absoulte.
 
91
                /// </summary>
 
92
                public static string GetAbsolutePath(string baseDirectoryPath, string relPath)
 
93
                {
 
94
                        return NormalizePath(Path.Combine(baseDirectoryPath, relPath));
 
95
                }
 
96
                
 
97
                /// <summary>
 
98
                /// Gets the normalized version of fileName.
 
99
                /// Slashes are replaced with backslashes, backreferences "." and ".." are 'evaluated'.
 
100
                /// </summary>
 
101
                public static string NormalizePath(string fileName)
 
102
                {
 
103
                        if (string.IsNullOrEmpty(fileName)) return fileName;
 
104
                        
 
105
                        int i;
 
106
                        
 
107
                        bool isWeb = false;
 
108
                        for (i = 0; i < fileName.Length; i++) {
 
109
                                if (fileName[i] == '/' || fileName[i] == '\\')
 
110
                                        break;
 
111
                                if (fileName[i] == ':') {
 
112
                                        if (i > 1)
 
113
                                                isWeb = true;
 
114
                                        break;
 
115
                                }
 
116
                        }
 
117
                        
 
118
                        char outputSeparator = isWeb ? '/' : '\\';
 
119
                        
 
120
                        StringBuilder result = new StringBuilder();
 
121
                        if (isWeb == false && fileName.StartsWith(@"\\") || fileName.StartsWith("//")) {
 
122
                                i = 2;
 
123
                                result.Append(outputSeparator);
 
124
                        } else {
 
125
                                i = 0;
 
126
                        }
 
127
                        int segmentStartPos = i;
 
128
                        for (; i <= fileName.Length; i++) {
 
129
                                if (i == fileName.Length || fileName[i] == '/' || fileName[i] == '\\') {
 
130
                                        int segmentLength = i - segmentStartPos;
 
131
                                        switch (segmentLength) {
 
132
                                                case 0:
 
133
                                                        // ignore empty segment (if not in web mode)
 
134
                                                        if (isWeb) {
 
135
                                                                result.Append(outputSeparator);
 
136
                                                        }
 
137
                                                        break;
 
138
                                                case 1:
 
139
                                                        // ignore /./ segment, but append other one-letter segments
 
140
                                                        if (fileName[segmentStartPos] != '.') {
 
141
                                                                if (result.Length > 0) result.Append(outputSeparator);
 
142
                                                                result.Append(fileName[segmentStartPos]);
 
143
                                                        }
 
144
                                                        break;
 
145
                                                case 2:
 
146
                                                        if (fileName[segmentStartPos] == '.' && fileName[segmentStartPos + 1] == '.') {
 
147
                                                                // remove previous segment
 
148
                                                                int j;
 
149
                                                                for (j = result.Length - 1; j >= 0 && result[j] != outputSeparator; j--);
 
150
                                                                if (j > 0) {
 
151
                                                                        result.Length = j;
 
152
                                                                }
 
153
                                                                break;
 
154
                                                        } else {
 
155
                                                                // append normal segment
 
156
                                                                goto default;
 
157
                                                        }
 
158
                                                default:
 
159
                                                        if (result.Length > 0) result.Append(outputSeparator);
 
160
                                                        result.Append(fileName, segmentStartPos, segmentLength);
 
161
                                                        break;
 
162
                                        }
 
163
                                        segmentStartPos = i + 1; // remember start position for next segment
 
164
                                }
 
165
                        }
 
166
                        if (isWeb == false) {
 
167
                                if (result.Length > 0 && result[result.Length - 1] == outputSeparator) {
 
168
                                        result.Length -= 1;
 
169
                                }
 
170
                                if (result.Length == 2 && result[1] == ':') {
 
171
                                        result.Append(outputSeparator);
 
172
                                }
 
173
                        }
 
174
                        return result.ToString();
 
175
                }
 
176
                
 
177
                public static bool IsEqualFileName(string fileName1, string fileName2)
 
178
                {
 
179
                        return string.Equals(NormalizePath(fileName1),
 
180
                                             NormalizePath(fileName2),
 
181
                                             StringComparison.OrdinalIgnoreCase);
 
182
                }
 
183
                
 
184
                public static bool IsBaseDirectory(string baseDirectory, string testDirectory)
 
185
                {
 
186
                        try {
 
187
                                baseDirectory = NormalizePath(baseDirectory).ToUpperInvariant();
 
188
                                testDirectory = NormalizePath(testDirectory).ToUpperInvariant();
 
189
                                baseDirectory = baseDirectory.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
 
190
                                testDirectory = testDirectory.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
 
191
                                
 
192
                                if (baseDirectory[baseDirectory.Length - 1] != Path.DirectorySeparatorChar)
 
193
                                        baseDirectory += Path.DirectorySeparatorChar;
 
194
                                if (testDirectory[testDirectory.Length - 1] != Path.DirectorySeparatorChar)
 
195
                                        testDirectory += Path.DirectorySeparatorChar;
 
196
                                
 
197
                                return testDirectory.StartsWith(baseDirectory);
 
198
                        } catch (Exception) {
 
199
                                return false;
 
200
                        }
 
201
                }
 
202
                
 
203
                public static string RenameBaseDirectory(string fileName, string oldDirectory, string newDirectory)
 
204
                {
 
205
                        fileName     = NormalizePath(fileName);
 
206
                        oldDirectory = NormalizePath(oldDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
 
207
                        newDirectory = NormalizePath(newDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
 
208
                        if (IsBaseDirectory(oldDirectory, fileName)) {
 
209
                                if (fileName.Length == oldDirectory.Length) {
 
210
                                        return newDirectory;
 
211
                                }
 
212
                                return Path.Combine(newDirectory, fileName.Substring(oldDirectory.Length + 1));
 
213
                        }
 
214
                        return fileName;
 
215
                }
 
216
                
 
217
                
 
218
                /// <summary>
 
219
                /// This method checks the file fileName if it is valid.
 
220
                /// </summary>
 
221
                public static bool IsValidFileName(string fileName)
 
222
                {
 
223
                        // Fixme: 260 is the hardcoded maximal length for a path on my Windows XP system
 
224
                        //        I can't find a .NET property or method for determining this variable.
 
225
                        
 
226
                        if (fileName == null || fileName.Length == 0 || fileName.Length >= MaxPathLength) {
 
227
                                return false;
 
228
                        }
 
229
                        
 
230
                        // platform independend : check for invalid path chars
 
231
                        
 
232
                        if (fileName.IndexOfAny(Path.GetInvalidPathChars()) >= 0) {
 
233
                                return false;
 
234
                        }
 
235
                        if (fileName.IndexOf('?') >= 0 || fileName.IndexOf('*') >= 0) {
 
236
                                return false;
 
237
                        }
 
238
                        
 
239
                        if (!Regex.IsMatch(fileName, fileNameRegEx)) {
 
240
                                return false;
 
241
                        }
 
242
                        
 
243
                        // platform dependend : Check for invalid file names (DOS)
 
244
                        // this routine checks for follwing bad file names :
 
245
                        // CON, PRN, AUX, NUL, COM1-9 and LPT1-9
 
246
                        
 
247
                        string nameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
 
248
                        if (nameWithoutExtension != null) {
 
249
                                nameWithoutExtension = nameWithoutExtension.ToUpperInvariant();
 
250
                        }
 
251
                        
 
252
                        if (nameWithoutExtension == "CON" ||
 
253
                            nameWithoutExtension == "PRN" ||
 
254
                            nameWithoutExtension == "AUX" ||
 
255
                            nameWithoutExtension == "NUL") {
 
256
                                return false;
 
257
                        }
 
258
                        
 
259
                        char ch = nameWithoutExtension.Length == 4 ? nameWithoutExtension[3] : '\0';
 
260
                        
 
261
                        return !((nameWithoutExtension.StartsWith("COM") ||
 
262
                                  nameWithoutExtension.StartsWith("LPT")) &&
 
263
                                 Char.IsDigit(ch));
 
264
                }
 
265
                
 
266
                /// <summary>
 
267
                /// Checks that a single directory name (not the full path) is valid.
 
268
                /// </summary>
 
269
                public static bool IsValidDirectoryName(string name)
 
270
                {
 
271
                        if (String.IsNullOrEmpty(name)) {
 
272
                                throw new ArgumentNullException("name");
 
273
                        }
 
274
                        if (!IsValidFileName(name)) {
 
275
                                return false;
 
276
                        }
 
277
                        if (name.IndexOfAny(new char[]{Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar}) >= 0) {
 
278
                                return false;
 
279
                        }
 
280
                        if (name.Trim(' ').Length == 0) {
 
281
                                return false;
 
282
                        }
 
283
                        return true;
 
284
                }
 
285
                
 
286
                public static bool IsDirectory(string filename)
 
287
                {
 
288
                        if (String.IsNullOrEmpty(filename)) {
 
289
                                throw new ArgumentNullException("filename");
 
290
                        }
 
291
                        
 
292
                        if (!Directory.Exists(filename)) {
 
293
                                return false;
 
294
                        }
 
295
                        FileAttributes attr = File.GetAttributes(filename);
 
296
                        return (attr & FileAttributes.Directory) != 0;
 
297
                }
 
298
 
 
299
                //TODO This code is Windows specific
 
300
                static bool MatchN (string src, int srcidx, string pattern, int patidx)
 
301
                {
 
302
                        int patlen = pattern.Length;
 
303
                        int srclen = src.Length;
 
304
                        char next_char;
 
305
 
 
306
                        for (;;) {
 
307
                                if (patidx == patlen)
 
308
                                        return (srcidx == srclen);
 
309
                                next_char = pattern[patidx++];
 
310
                                if (next_char == '?') {
 
311
                                        if (srcidx == src.Length)
 
312
                                                return false;
 
313
                                        srcidx++;
 
314
                                }
 
315
                                else if (next_char != '*') {
 
316
                                        if ((srcidx == src.Length) || (src[srcidx] != next_char))
 
317
                                                return false;
 
318
                                        srcidx++;
 
319
                                }
 
320
                                else {
 
321
                                        if (patidx == pattern.Length)
 
322
                                                return true;
 
323
                                        while (srcidx < srclen) {
 
324
                                                if (MatchN(src, srcidx, pattern, patidx))
 
325
                                                        return true;
 
326
                                                srcidx++;
 
327
                                        }
 
328
                                        return false;
 
329
                                }
 
330
                        }
 
331
                }
 
332
 
 
333
                static bool Match(string src, string pattern)
 
334
                {
 
335
                        if (pattern[0] == '*') {
 
336
                                // common case optimization
 
337
                                int i = pattern.Length;
 
338
                                int j = src.Length;
 
339
                                while (--i > 0) {
 
340
                                        if (pattern[i] == '*')
 
341
                                                return MatchN(src, 0, pattern, 0);
 
342
                                        if (j-- == 0)
 
343
                                                return false;
 
344
                                        if ((pattern[i] != src[j]) && (pattern[i] != '?'))
 
345
                                                return false;
 
346
                                }
 
347
                                return true;
 
348
                        }
 
349
                        return MatchN(src, 0, pattern, 0);
 
350
                }
 
351
 
 
352
                public static bool MatchesPattern(string filename, string pattern)
 
353
                {
 
354
                        filename = filename.ToUpper(System.Globalization.CultureInfo.InstalledUICulture);
 
355
                        pattern = pattern.ToUpper();
 
356
                        string[] patterns = pattern.Split(';');
 
357
                        foreach (string p in patterns) {
 
358
                                if (Match(filename, p)) {
 
359
                                        return true;
 
360
                                }
 
361
                        }
 
362
                        return false;
 
363
                }
 
364
        }
 
365
}