You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

413 lines
12 KiB

  1. // ZipEntryFactory.cs
  2. //
  3. // Copyright 2006 John Reilly
  4. //
  5. // Copyright (C) 2001 Free Software Foundation, Inc.
  6. //
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the GNU General Public License
  9. // as published by the Free Software Foundation; either version 2
  10. // of the License, or (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program; if not, write to the Free Software
  19. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. //
  21. // Linking this library statically or dynamically with other modules is
  22. // making a combined work based on this library. Thus, the terms and
  23. // conditions of the GNU General Public License cover the whole
  24. // combination.
  25. //
  26. // As a special exception, the copyright holders of this library give you
  27. // permission to link this library with independent modules to produce an
  28. // executable, regardless of the license terms of these independent
  29. // modules, and to copy and distribute the resulting executable under
  30. // terms of your choice, provided that you also meet, for each linked
  31. // independent module, the terms and conditions of the license of that
  32. // module. An independent module is a module which is not derived from
  33. // or based on this library. If you modify this library, you may extend
  34. // this exception to your version of the library, but you are not
  35. // obligated to do so. If you do not wish to do so, delete this
  36. // exception statement from your version.
  37. using System;
  38. using System.IO;
  39. using Externals.Compression.Core;
  40. namespace Externals.Compression.Zip
  41. {
  42. /// <summary>
  43. /// Basic implementation of <see cref="IEntryFactory"></see>
  44. /// </summary>
  45. internal class ZipEntryFactory : IEntryFactory
  46. {
  47. #region Enumerations
  48. /// <summary>
  49. /// Defines the possible values to be used for the <see cref="ZipEntry.DateTime"/>.
  50. /// </summary>
  51. internal enum TimeSetting
  52. {
  53. /// <summary>
  54. /// Use the recorded LastWriteTime value for the file.
  55. /// </summary>
  56. LastWriteTime,
  57. /// <summary>
  58. /// Use the recorded LastWriteTimeUtc value for the file
  59. /// </summary>
  60. LastWriteTimeUtc,
  61. /// <summary>
  62. /// Use the recorded CreateTime value for the file.
  63. /// </summary>
  64. CreateTime,
  65. /// <summary>
  66. /// Use the recorded CreateTimeUtc value for the file.
  67. /// </summary>
  68. CreateTimeUtc,
  69. /// <summary>
  70. /// Use the recorded LastAccessTime value for the file.
  71. /// </summary>
  72. LastAccessTime,
  73. /// <summary>
  74. /// Use the recorded LastAccessTimeUtc value for the file.
  75. /// </summary>
  76. LastAccessTimeUtc,
  77. /// <summary>
  78. /// Use a fixed value.
  79. /// </summary>
  80. /// <remarks>The actual <see cref="DateTime"/> value used can be
  81. /// specified via the <see cref="ZipEntryFactory(DateTime)"/> constructor or
  82. /// using the <see cref="ZipEntryFactory(TimeSetting)"/> with the setting set
  83. /// to <see cref="TimeSetting.Fixed"/> which will use the <see cref="DateTime"/> when this class was constructed.
  84. /// The <see cref="FixedDateTime"/> property can also be used to set this value.</remarks>
  85. Fixed,
  86. }
  87. #endregion
  88. #region Constructors
  89. /// <summary>
  90. /// Initialise a new instance of the <see cref="ZipEntryFactory"/> class.
  91. /// </summary>
  92. /// <remarks>A default <see cref="INameTransform"/>, and the LastWriteTime for files is used.</remarks>
  93. public ZipEntryFactory()
  94. {
  95. nameTransform_ = new ZipNameTransform();
  96. }
  97. /// <summary>
  98. /// Initialise a new instance of <see cref="ZipEntryFactory"/> using the specified <see cref="TimeSetting"/>
  99. /// </summary>
  100. /// <param name="timeSetting">The <see cref="TimeSetting">time setting</see> to use when creating <see cref="ZipEntry">Zip entries</see>.</param>
  101. public ZipEntryFactory(TimeSetting timeSetting)
  102. {
  103. timeSetting_ = timeSetting;
  104. nameTransform_ = new ZipNameTransform();
  105. }
  106. /// <summary>
  107. /// Initialise a new instance of <see cref="ZipEntryFactory"/> using the specified <see cref="DateTime"/>
  108. /// </summary>
  109. /// <param name="time">The time to set all <see cref="ZipEntry.DateTime"/> values to.</param>
  110. public ZipEntryFactory(DateTime time)
  111. {
  112. timeSetting_ = TimeSetting.Fixed;
  113. FixedDateTime = time;
  114. nameTransform_ = new ZipNameTransform();
  115. }
  116. #endregion
  117. #region Properties
  118. /// <summary>
  119. /// Get / set the <see cref="INameTransform"/> to be used when creating new <see cref="ZipEntry"/> values.
  120. /// </summary>
  121. /// <remarks>
  122. /// Setting this property to null will cause a default <see cref="ZipNameTransform">name transform</see> to be used.
  123. /// </remarks>
  124. public INameTransform NameTransform
  125. {
  126. get { return nameTransform_; }
  127. set
  128. {
  129. if (value == null) {
  130. nameTransform_ = new ZipNameTransform();
  131. }
  132. else {
  133. nameTransform_ = value;
  134. }
  135. }
  136. }
  137. /// <summary>
  138. /// Get / set the <see cref="TimeSetting"/> in use.
  139. /// </summary>
  140. public TimeSetting Setting
  141. {
  142. get { return timeSetting_; }
  143. set { timeSetting_ = value; }
  144. }
  145. /// <summary>
  146. /// Get / set the <see cref="DateTime"/> value to use when <see cref="Setting"/> is set to <see cref="TimeSetting.Fixed"/>
  147. /// </summary>
  148. public DateTime FixedDateTime
  149. {
  150. get { return fixedDateTime_; }
  151. set
  152. {
  153. if (value.Year < 1970) {
  154. throw new ArgumentException("Value is too old to be valid", "value");
  155. }
  156. fixedDateTime_ = value;
  157. }
  158. }
  159. /// <summary>
  160. /// A bitmask defining the attributes to be retrieved from the actual file.
  161. /// </summary>
  162. /// <remarks>The default is to get all possible attributes from the actual file.</remarks>
  163. public int GetAttributes
  164. {
  165. get { return getAttributes_; }
  166. set { getAttributes_ = value; }
  167. }
  168. /// <summary>
  169. /// A bitmask defining which attributes are to be set on.
  170. /// </summary>
  171. /// <remarks>By default no attributes are set on.</remarks>
  172. public int SetAttributes
  173. {
  174. get { return setAttributes_; }
  175. set { setAttributes_ = value; }
  176. }
  177. /// <summary>
  178. /// Get set a value indicating wether unidoce text should be set on.
  179. /// </summary>
  180. public bool IsUnicodeText
  181. {
  182. get { return isUnicodeText_; }
  183. set { isUnicodeText_ = value; }
  184. }
  185. #endregion
  186. #region IEntryFactory Members
  187. /// <summary>
  188. /// Make a new <see cref="ZipEntry"/> for a file.
  189. /// </summary>
  190. /// <param name="fileName">The name of the file to create a new entry for.</param>
  191. /// <returns>Returns a new <see cref="ZipEntry"/> based on the <paramref name="fileName"/>.</returns>
  192. public ZipEntry MakeFileEntry(string fileName)
  193. {
  194. return MakeFileEntry(fileName, true);
  195. }
  196. /// <summary>
  197. /// Make a new <see cref="ZipEntry"/> from a name.
  198. /// </summary>
  199. /// <param name="fileName">The name of the file to create a new entry for.</param>
  200. /// <param name="useFileSystem">If true entry detail is retrieved from the file system if the file exists.</param>
  201. /// <returns>Returns a new <see cref="ZipEntry"/> based on the <paramref name="fileName"/>.</returns>
  202. public ZipEntry MakeFileEntry(string fileName, bool useFileSystem)
  203. {
  204. ZipEntry result = new ZipEntry(nameTransform_.TransformFile(fileName));
  205. result.IsUnicodeText = isUnicodeText_;
  206. int externalAttributes = 0;
  207. bool useAttributes = (setAttributes_ != 0);
  208. FileInfo fi = null;
  209. if (useFileSystem)
  210. {
  211. fi = new FileInfo(fileName);
  212. }
  213. if ((fi != null) && fi.Exists)
  214. {
  215. switch (timeSetting_)
  216. {
  217. case TimeSetting.CreateTime:
  218. result.DateTime = fi.CreationTime;
  219. break;
  220. case TimeSetting.CreateTimeUtc:
  221. #if NETCF_1_0 || NETCF_2_0
  222. result.DateTime = fi.CreationTime.ToUniversalTime();
  223. #else
  224. result.DateTime = fi.CreationTimeUtc;
  225. #endif
  226. break;
  227. case TimeSetting.LastAccessTime:
  228. result.DateTime = fi.LastAccessTime;
  229. break;
  230. case TimeSetting.LastAccessTimeUtc:
  231. #if NETCF_1_0 || NETCF_2_0
  232. result.DateTime = fi.LastAccessTime.ToUniversalTime();
  233. #else
  234. result.DateTime = fi.LastAccessTimeUtc;
  235. #endif
  236. break;
  237. case TimeSetting.LastWriteTime:
  238. result.DateTime = fi.LastWriteTime;
  239. break;
  240. case TimeSetting.LastWriteTimeUtc:
  241. #if NETCF_1_0 || NETCF_2_0
  242. result.DateTime = fi.LastWriteTime.ToUniversalTime();
  243. #else
  244. result.DateTime = fi.LastWriteTimeUtc;
  245. #endif
  246. break;
  247. case TimeSetting.Fixed:
  248. result.DateTime = fixedDateTime_;
  249. break;
  250. default:
  251. throw new ZipException("Unhandled time setting in MakeFileEntry");
  252. }
  253. result.Size = fi.Length;
  254. useAttributes = true;
  255. externalAttributes = ((int)fi.Attributes & getAttributes_);
  256. }
  257. else
  258. {
  259. if (timeSetting_ == TimeSetting.Fixed)
  260. {
  261. result.DateTime = fixedDateTime_;
  262. }
  263. }
  264. if (useAttributes)
  265. {
  266. externalAttributes |= setAttributes_;
  267. result.ExternalFileAttributes = externalAttributes;
  268. }
  269. return result;
  270. }
  271. /// <summary>
  272. /// Make a new <see cref="ZipEntry"></see> for a directory.
  273. /// </summary>
  274. /// <param name="directoryName">The raw untransformed name for the new directory</param>
  275. /// <returns>Returns a new <see cref="ZipEntry"></see> representing a directory.</returns>
  276. public ZipEntry MakeDirectoryEntry(string directoryName)
  277. {
  278. return MakeDirectoryEntry(directoryName, true);
  279. }
  280. /// <summary>
  281. /// Make a new <see cref="ZipEntry"></see> for a directory.
  282. /// </summary>
  283. /// <param name="directoryName">The raw untransformed name for the new directory</param>
  284. /// <param name="useFileSystem">If true entry detail is retrieved from the file system if the file exists.</param>
  285. /// <returns>Returns a new <see cref="ZipEntry"></see> representing a directory.</returns>
  286. public ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem)
  287. {
  288. ZipEntry result = new ZipEntry(nameTransform_.TransformDirectory(directoryName));
  289. result.IsUnicodeText = isUnicodeText_;
  290. result.Size = 0;
  291. int externalAttributes = 0;
  292. DirectoryInfo di = null;
  293. if (useFileSystem)
  294. {
  295. di = new DirectoryInfo(directoryName);
  296. }
  297. if ((di != null) && di.Exists)
  298. {
  299. switch (timeSetting_)
  300. {
  301. case TimeSetting.CreateTime:
  302. result.DateTime = di.CreationTime;
  303. break;
  304. case TimeSetting.CreateTimeUtc:
  305. #if NETCF_1_0 || NETCF_2_0
  306. result.DateTime = di.CreationTime.ToUniversalTime();
  307. #else
  308. result.DateTime = di.CreationTimeUtc;
  309. #endif
  310. break;
  311. case TimeSetting.LastAccessTime:
  312. result.DateTime = di.LastAccessTime;
  313. break;
  314. case TimeSetting.LastAccessTimeUtc:
  315. #if NETCF_1_0 || NETCF_2_0
  316. result.DateTime = di.LastAccessTime.ToUniversalTime();
  317. #else
  318. result.DateTime = di.LastAccessTimeUtc;
  319. #endif
  320. break;
  321. case TimeSetting.LastWriteTime:
  322. result.DateTime = di.LastWriteTime;
  323. break;
  324. case TimeSetting.LastWriteTimeUtc:
  325. #if NETCF_1_0 || NETCF_2_0
  326. result.DateTime = di.LastWriteTime.ToUniversalTime();
  327. #else
  328. result.DateTime = di.LastWriteTimeUtc;
  329. #endif
  330. break;
  331. case TimeSetting.Fixed:
  332. result.DateTime = fixedDateTime_;
  333. break;
  334. default:
  335. throw new ZipException("Unhandled time setting in MakeDirectoryEntry");
  336. }
  337. externalAttributes = ((int)di.Attributes & getAttributes_);
  338. }
  339. else
  340. {
  341. if (timeSetting_ == TimeSetting.Fixed)
  342. {
  343. result.DateTime = fixedDateTime_;
  344. }
  345. }
  346. // Always set directory attribute on.
  347. externalAttributes |= (setAttributes_ | 16);
  348. result.ExternalFileAttributes = externalAttributes;
  349. return result;
  350. }
  351. #endregion
  352. #region Instance Fields
  353. INameTransform nameTransform_;
  354. DateTime fixedDateTime_ = DateTime.Now;
  355. TimeSetting timeSetting_;
  356. bool isUnicodeText_;
  357. int getAttributes_ = -1;
  358. int setAttributes_;
  359. #endregion
  360. }
  361. }