ZipEntryFactory.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. using System;
  2. using System.IO;
  3. using ICSharpCode.SharpZipLib.Core;
  4. namespace ICSharpCode.SharpZipLib.Zip
  5. {
  6. /// <summary>
  7. /// Basic implementation of <see cref="IEntryFactory"></see>
  8. /// </summary>
  9. public class ZipEntryFactory : IEntryFactory
  10. {
  11. #region Enumerations
  12. /// <summary>
  13. /// Defines the possible values to be used for the <see cref="ZipEntry.DateTime"/>.
  14. /// </summary>
  15. public enum TimeSetting
  16. {
  17. /// <summary>
  18. /// Use the recorded LastWriteTime value for the file.
  19. /// </summary>
  20. LastWriteTime,
  21. /// <summary>
  22. /// Use the recorded LastWriteTimeUtc value for the file
  23. /// </summary>
  24. LastWriteTimeUtc,
  25. /// <summary>
  26. /// Use the recorded CreateTime value for the file.
  27. /// </summary>
  28. CreateTime,
  29. /// <summary>
  30. /// Use the recorded CreateTimeUtc value for the file.
  31. /// </summary>
  32. CreateTimeUtc,
  33. /// <summary>
  34. /// Use the recorded LastAccessTime value for the file.
  35. /// </summary>
  36. LastAccessTime,
  37. /// <summary>
  38. /// Use the recorded LastAccessTimeUtc value for the file.
  39. /// </summary>
  40. LastAccessTimeUtc,
  41. /// <summary>
  42. /// Use a fixed value.
  43. /// </summary>
  44. /// <remarks>The actual <see cref="DateTime"/> value used can be
  45. /// specified via the <see cref="ZipEntryFactory(DateTime)"/> constructor or
  46. /// using the <see cref="ZipEntryFactory(TimeSetting)"/> with the setting set
  47. /// to <see cref="TimeSetting.Fixed"/> which will use the <see cref="DateTime"/> when this class was constructed.
  48. /// The <see cref="FixedDateTime"/> property can also be used to set this value.</remarks>
  49. Fixed,
  50. }
  51. #endregion
  52. #region Constructors
  53. /// <summary>
  54. /// Initialise a new instance of the <see cref="ZipEntryFactory"/> class.
  55. /// </summary>
  56. /// <remarks>A default <see cref="INameTransform"/>, and the LastWriteTime for files is used.</remarks>
  57. public ZipEntryFactory()
  58. {
  59. nameTransform_ = new ZipNameTransform();
  60. }
  61. /// <summary>
  62. /// Initialise a new instance of <see cref="ZipEntryFactory"/> using the specified <see cref="TimeSetting"/>
  63. /// </summary>
  64. /// <param name="timeSetting">The <see cref="TimeSetting">time setting</see> to use when creating <see cref="ZipEntry">Zip entries</see>.</param>
  65. public ZipEntryFactory(TimeSetting timeSetting)
  66. {
  67. timeSetting_ = timeSetting;
  68. nameTransform_ = new ZipNameTransform();
  69. }
  70. /// <summary>
  71. /// Initialise a new instance of <see cref="ZipEntryFactory"/> using the specified <see cref="DateTime"/>
  72. /// </summary>
  73. /// <param name="time">The time to set all <see cref="ZipEntry.DateTime"/> values to.</param>
  74. public ZipEntryFactory(DateTime time)
  75. {
  76. timeSetting_ = TimeSetting.Fixed;
  77. FixedDateTime = time;
  78. nameTransform_ = new ZipNameTransform();
  79. }
  80. #endregion
  81. #region Properties
  82. /// <summary>
  83. /// Get / set the <see cref="INameTransform"/> to be used when creating new <see cref="ZipEntry"/> values.
  84. /// </summary>
  85. /// <remarks>
  86. /// Setting this property to null will cause a default <see cref="ZipNameTransform">name transform</see> to be used.
  87. /// </remarks>
  88. public INameTransform NameTransform {
  89. get { return nameTransform_; }
  90. set {
  91. if (value == null) {
  92. nameTransform_ = new ZipNameTransform();
  93. } else {
  94. nameTransform_ = value;
  95. }
  96. }
  97. }
  98. /// <summary>
  99. /// Get / set the <see cref="TimeSetting"/> in use.
  100. /// </summary>
  101. public TimeSetting Setting {
  102. get { return timeSetting_; }
  103. set { timeSetting_ = value; }
  104. }
  105. /// <summary>
  106. /// Get / set the <see cref="DateTime"/> value to use when <see cref="Setting"/> is set to <see cref="TimeSetting.Fixed"/>
  107. /// </summary>
  108. public DateTime FixedDateTime {
  109. get { return fixedDateTime_; }
  110. set {
  111. if (value.Year < 1970) {
  112. throw new ArgumentException("Value is too old to be valid", "nameof(value)");
  113. }
  114. fixedDateTime_ = value;
  115. }
  116. }
  117. /// <summary>
  118. /// A bitmask defining the attributes to be retrieved from the actual file.
  119. /// </summary>
  120. /// <remarks>The default is to get all possible attributes from the actual file.</remarks>
  121. public int GetAttributes {
  122. get { return getAttributes_; }
  123. set { getAttributes_ = value; }
  124. }
  125. /// <summary>
  126. /// A bitmask defining which attributes are to be set on.
  127. /// </summary>
  128. /// <remarks>By default no attributes are set on.</remarks>
  129. public int SetAttributes {
  130. get { return setAttributes_; }
  131. set { setAttributes_ = value; }
  132. }
  133. /// <summary>
  134. /// Get set a value indicating wether unidoce text should be set on.
  135. /// </summary>
  136. public bool IsUnicodeText {
  137. get { return isUnicodeText_; }
  138. set { isUnicodeText_ = value; }
  139. }
  140. #endregion
  141. #region IEntryFactory Members
  142. /// <summary>
  143. /// Make a new <see cref="ZipEntry"/> for a file.
  144. /// </summary>
  145. /// <param name="fileName">The name of the file to create a new entry for.</param>
  146. /// <returns>Returns a new <see cref="ZipEntry"/> based on the <paramref name="fileName"/>.</returns>
  147. public ZipEntry MakeFileEntry(string fileName)
  148. {
  149. return MakeFileEntry(fileName, null, true);
  150. }
  151. /// <summary>
  152. /// Make a new <see cref="ZipEntry"/> for a file.
  153. /// </summary>
  154. /// <param name="fileName">The name of the file to create a new entry for.</param>
  155. /// <param name="useFileSystem">If true entry detail is retrieved from the file system if the file exists.</param>
  156. /// <returns>Returns a new <see cref="ZipEntry"/> based on the <paramref name="fileName"/>.</returns>
  157. public ZipEntry MakeFileEntry(string fileName, bool useFileSystem)
  158. {
  159. return MakeFileEntry(fileName, null, useFileSystem);
  160. }
  161. /// <summary>
  162. /// Make a new <see cref="ZipEntry"/> from a name.
  163. /// </summary>
  164. /// <param name="fileName">The name of the file to create a new entry for.</param>
  165. /// <param name="entryName">An alternative name to be used for the new entry. Null if not applicable.</param>
  166. /// <param name="useFileSystem">If true entry detail is retrieved from the file system if the file exists.</param>
  167. /// <returns>Returns a new <see cref="ZipEntry"/> based on the <paramref name="fileName"/>.</returns>
  168. public ZipEntry MakeFileEntry(string fileName, string entryName, bool useFileSystem)
  169. {
  170. var result = new ZipEntry(nameTransform_.TransformFile(!string.IsNullOrEmpty(entryName) ? entryName : fileName));
  171. result.IsUnicodeText = isUnicodeText_;
  172. int externalAttributes = 0;
  173. bool useAttributes = (setAttributes_ != 0);
  174. FileInfo fi = null;
  175. if (useFileSystem) {
  176. fi = new FileInfo(fileName);
  177. }
  178. if ((fi != null) && fi.Exists) {
  179. switch (timeSetting_) {
  180. case TimeSetting.CreateTime:
  181. result.DateTime = fi.CreationTime;
  182. break;
  183. case TimeSetting.CreateTimeUtc:
  184. result.DateTime = fi.CreationTimeUtc;
  185. break;
  186. case TimeSetting.LastAccessTime:
  187. result.DateTime = fi.LastAccessTime;
  188. break;
  189. case TimeSetting.LastAccessTimeUtc:
  190. result.DateTime = fi.LastAccessTimeUtc;
  191. break;
  192. case TimeSetting.LastWriteTime:
  193. result.DateTime = fi.LastWriteTime;
  194. break;
  195. case TimeSetting.LastWriteTimeUtc:
  196. result.DateTime = fi.LastWriteTimeUtc;
  197. break;
  198. case TimeSetting.Fixed:
  199. result.DateTime = fixedDateTime_;
  200. break;
  201. default:
  202. throw new ZipException("Unhandled time setting in MakeFileEntry");
  203. }
  204. result.Size = fi.Length;
  205. useAttributes = true;
  206. externalAttributes = ((int)fi.Attributes & getAttributes_);
  207. } else {
  208. if (timeSetting_ == TimeSetting.Fixed) {
  209. result.DateTime = fixedDateTime_;
  210. }
  211. }
  212. if (useAttributes) {
  213. externalAttributes |= setAttributes_;
  214. result.ExternalFileAttributes = externalAttributes;
  215. }
  216. return result;
  217. }
  218. /// <summary>
  219. /// Make a new <see cref="ZipEntry"></see> for a directory.
  220. /// </summary>
  221. /// <param name="directoryName">The raw untransformed name for the new directory</param>
  222. /// <returns>Returns a new <see cref="ZipEntry"></see> representing a directory.</returns>
  223. public ZipEntry MakeDirectoryEntry(string directoryName)
  224. {
  225. return MakeDirectoryEntry(directoryName, true);
  226. }
  227. /// <summary>
  228. /// Make a new <see cref="ZipEntry"></see> for a directory.
  229. /// </summary>
  230. /// <param name="directoryName">The raw untransformed name for the new directory</param>
  231. /// <param name="useFileSystem">If true entry detail is retrieved from the file system if the file exists.</param>
  232. /// <returns>Returns a new <see cref="ZipEntry"></see> representing a directory.</returns>
  233. public ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem)
  234. {
  235. var result = new ZipEntry(nameTransform_.TransformDirectory(directoryName));
  236. result.IsUnicodeText = isUnicodeText_;
  237. result.Size = 0;
  238. int externalAttributes = 0;
  239. DirectoryInfo di = null;
  240. if (useFileSystem) {
  241. di = new DirectoryInfo(directoryName);
  242. }
  243. if ((di != null) && di.Exists) {
  244. switch (timeSetting_) {
  245. case TimeSetting.CreateTime:
  246. result.DateTime = di.CreationTime;
  247. break;
  248. case TimeSetting.CreateTimeUtc:
  249. result.DateTime = di.CreationTimeUtc;
  250. break;
  251. case TimeSetting.LastAccessTime:
  252. result.DateTime = di.LastAccessTime;
  253. break;
  254. case TimeSetting.LastAccessTimeUtc:
  255. result.DateTime = di.LastAccessTimeUtc;
  256. break;
  257. case TimeSetting.LastWriteTime:
  258. result.DateTime = di.LastWriteTime;
  259. break;
  260. case TimeSetting.LastWriteTimeUtc:
  261. result.DateTime = di.LastWriteTimeUtc;
  262. break;
  263. case TimeSetting.Fixed:
  264. result.DateTime = fixedDateTime_;
  265. break;
  266. default:
  267. throw new ZipException("Unhandled time setting in MakeDirectoryEntry");
  268. }
  269. externalAttributes = ((int)di.Attributes & getAttributes_);
  270. } else {
  271. if (timeSetting_ == TimeSetting.Fixed) {
  272. result.DateTime = fixedDateTime_;
  273. }
  274. }
  275. // Always set directory attribute on.
  276. externalAttributes |= (setAttributes_ | 16);
  277. result.ExternalFileAttributes = externalAttributes;
  278. return result;
  279. }
  280. #endregion
  281. #region Instance Fields
  282. INameTransform nameTransform_;
  283. DateTime fixedDateTime_ = DateTime.Now;
  284. TimeSetting timeSetting_;
  285. bool isUnicodeText_;
  286. int getAttributes_ = -1;
  287. int setAttributes_;
  288. #endregion
  289. }
  290. }