root/branches/Abonament/BazaReklam.Updater/ICSharpCode.SharpZipLib/Zip/ZipNameTransform.cs @ 759

Wersja 597, 8.6 KB (wprowadzona przez marek, 17 years temu)

re #165

Line 
1// ZipNameTransform.cs
2//
3// Copyright 2005 John Reilly
4//
5// This program is free software; you can redistribute it and/or
6// modify it under the terms of the GNU General Public License
7// as published by the Free Software Foundation; either version 2
8// of the License, or (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18//
19// Linking this library statically or dynamically with other modules is
20// making a combined work based on this library.  Thus, the terms and
21// conditions of the GNU General Public License cover the whole
22// combination.
23//
24// As a special exception, the copyright holders of this library give you
25// permission to link this library with independent modules to produce an
26// executable, regardless of the license terms of these independent
27// modules, and to copy and distribute the resulting executable under
28// terms of your choice, provided that you also meet, for each linked
29// independent module, the terms and conditions of the license of that
30// module.  An independent module is a module which is not derived from
31// or based on this library.  If you modify this library, you may extend
32// this exception to your version of the library, but you are not
33// obligated to do so.  If you do not wish to do so, delete this
34// exception statement from your version.
35
36
37using System;
38using System.IO;
39using System.Text;
40
41using ICSharpCode.SharpZipLib.Core;
42
43namespace ICSharpCode.SharpZipLib.Zip
44{
45        /// <summary>
46        /// ZipNameTransform transforms names as per the Zip file naming convention.
47        /// </summary>
48        /// <remarks>The use of absolute names is supported although its use is not valid
49        /// according to Zip naming conventions, and should not be used if maximum compatability is desired.</remarks>
50        public class ZipNameTransform : INameTransform
51        {
52                #region Constructors
53                /// <summary>
54                /// Initialize a new instance of <see cref="ZipNameTransform"></see>
55                /// </summary>
56                public ZipNameTransform()
57                {
58                }
59
60                /// <summary>
61                /// Initialize a new instance of <see cref="ZipNameTransform"></see>
62                /// </summary>
63                /// <param name="trimPrefix">The string to trim from the front of paths if found.</param>
64                public ZipNameTransform(string trimPrefix)
65                {
66                        TrimPrefix = trimPrefix;
67                }
68                #endregion
69               
70                /// <summary>
71                /// Static constructor.
72                /// </summary>
73                static ZipNameTransform()
74                {
75                        char[] invalidPathChars;
76#if NET_1_0 || NET_1_1 || NETCF_1_0
77                        invalidPathChars = Path.InvalidPathChars;
78#else
79                        invalidPathChars = Path.GetInvalidPathChars();
80#endif
81                        int howMany = invalidPathChars.Length + 2;
82
83                        InvalidEntryCharsRelaxed = new char[howMany];
84                        Array.Copy(invalidPathChars, 0, InvalidEntryCharsRelaxed, 0, invalidPathChars.Length);
85                        InvalidEntryCharsRelaxed[howMany - 1] = '*';
86                        InvalidEntryCharsRelaxed[howMany - 2] = '?';
87
88                        howMany = invalidPathChars.Length + 4;
89                        InvalidEntryChars = new char[howMany];
90                        Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length);
91                        InvalidEntryChars[howMany - 1] = ':';
92                        InvalidEntryChars[howMany - 2] = '\\';
93                        InvalidEntryChars[howMany - 3] = '*';
94                        InvalidEntryChars[howMany - 4] = '?';
95                }
96
97                /// <summary>
98                /// Transform a windows directory name according to the Zip file naming conventions.
99                /// </summary>
100                /// <param name="name">The directory name to transform.</param>
101                /// <returns>The transformed name.</returns>
102                public string TransformDirectory(string name)
103                {
104                        name = TransformFile(name);
105                        if (name.Length > 0) {
106                                if ( !name.EndsWith("/") ) {
107                                        name += "/";
108                                }
109                        }
110                        else {
111                                throw new ZipException("Cannot have an empty directory name");
112                        }
113                        return name;
114                }
115               
116                /// <summary>
117                /// Transform a windows file name according to the Zip file naming conventions.
118                /// </summary>
119                /// <param name="name">The file name to transform.</param>
120                /// <returns>The transformed name.</returns>
121                public string TransformFile(string name)
122                {
123                        if (name != null) {
124                                string lowerName = name.ToLower();
125                                if ( (trimPrefix_ != null) && (lowerName.IndexOf(trimPrefix_) == 0) ) {
126                                        name = name.Substring(trimPrefix_.Length);
127                                }
128
129                                name = name.Replace(@"\", "/");
130                                name = WindowsPathUtils.DropPathRoot(name);
131
132                                // Drop any leading slashes.
133                                while ((name.Length > 0) && (name[0] == '/'))
134                                {
135                                        name = name.Remove(0, 1);
136                                }
137
138                                // Drop any trailing slashes.
139                                while ((name.Length > 0) && (name[name.Length - 1] == '/'))
140                                {
141                                        name = name.Remove(name.Length - 1, 1);
142                                }
143
144                                // Convert consecutive // characters to /
145                                int index = name.IndexOf("//");
146                                while (index >= 0)
147                                {
148                                        name = name.Remove(index, 1);
149                                        index = name.IndexOf("//");
150                                }
151
152                                name = MakeValidName(name, '_');
153                        }
154                        else {
155                                name = string.Empty;
156                        }
157                        return name;
158                }
159               
160                /// <summary>
161                /// Get/set the path prefix to be trimmed from paths if present.
162                /// </summary>
163                /// <remarks>The prefix is trimmed before any conversion from
164                /// a windows path is done.</remarks>
165                public string TrimPrefix
166                {
167                        get { return trimPrefix_; }
168                        set {
169                                trimPrefix_ = value;
170                                if (trimPrefix_ != null) {
171                                        trimPrefix_ = trimPrefix_.ToLower();
172                                }
173                        }
174                }
175
176                /// <summary>
177                /// Force a name to be valid by replacing invalid characters with a fixed value
178                /// </summary>
179                /// <param name="name">The name to force valid</param>
180                /// <param name="replacement">The replacement character to use.</param>
181                /// <returns>Returns a valid name</returns>
182                static string MakeValidName(string name, char replacement)
183                {
184                        int index = name.IndexOfAny(InvalidEntryChars);
185                        if (index >= 0) {
186                                StringBuilder builder = new StringBuilder(name);
187
188                                while (index >= 0 ) {
189                                        builder[index] = replacement;
190
191                                        if (index >= name.Length) {
192                                                index = -1;
193                                        }
194                                        else {
195                                                index = name.IndexOfAny(InvalidEntryChars, index + 1);
196                                        }
197                                }
198                                name = builder.ToString();
199                        }
200
201                        if (name.Length > 0xffff) {
202                                throw new PathTooLongException();
203                        }
204
205                        return name;
206                }
207
208                /// <summary>
209                /// Test a name to see if it is a valid name for a zip entry.
210                /// </summary>
211                /// <param name="name">The name to test.</param>
212                /// <param name="relaxed">If true checking is relaxed about windows file names and absolute paths.</param>
213                /// <returns>Returns true if the name is a valid zip name; false otherwise.</returns>
214                /// <remarks>Zip path names are actually in Unix format, and should only contain relative paths.
215                /// This means that any path stored should not contain a drive or
216                /// device letter, or a leading slash.  All slashes should forward slashes '/'.
217                /// An empty name is valid for a file where the input comes from standard input.
218                /// A null name is not considered valid.
219                /// </remarks>
220                public static bool IsValidName(string name, bool relaxed)
221                {
222                        bool result = (name != null);
223
224                        if ( result ) {
225                                if ( relaxed ) {
226                                        result = name.IndexOfAny(InvalidEntryCharsRelaxed) < 0;
227                                }
228                                else {
229                                        result =
230                                                (name.IndexOfAny(InvalidEntryChars) < 0) &&
231                                                (name.IndexOf('/') != 0);
232                                }
233                        }
234
235                        return result;
236                }
237
238                /// <summary>
239                /// Test a name to see if it is a valid name for a zip entry.
240                /// </summary>
241                /// <param name="name">The name to test.</param>
242                /// <returns>Returns true if the name is a valid zip name; false otherwise.</returns>
243                /// <remarks>Zip path names are actually in unix format,
244                /// and should only contain relative paths if a path is present.
245                /// This means that the path stored should not contain a drive or
246                /// device letter, or a leading slash.  All slashes should forward slashes '/'.
247                /// An empty name is valid where the input comes from standard input.
248                /// A null name is not considered valid.
249                /// </remarks>
250                public static bool IsValidName(string name)
251                {
252                        bool result =
253                                (name != null) &&
254                                (name.IndexOfAny(InvalidEntryChars) < 0) &&
255                                (name.IndexOf('/') != 0)
256                                ;
257                        return result;
258                }
259
260                #region Instance Fields
261                string trimPrefix_;
262                #endregion
263               
264                #region Class Fields
265                static readonly char[] InvalidEntryChars;
266                static readonly char[] InvalidEntryCharsRelaxed;
267                #endregion
268        }
269}
Notatka: Zobacz TracBrowser aby uzyskać więcej informacji.