ZipEntry.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // ZipEntry.cs
  2. // Copyright (C) 2001 Mike Krueger
  3. //
  4. // This file was translated from java, it was part of the GNU Classpath
  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. namespace ICSharpCode.SharpZipLib.Zip
  39. {
  40. public enum CompressionMethod
  41. {
  42. Stored = 0,
  43. Deflated = 8,
  44. }
  45. /// <summary>
  46. /// This class represents a member of a zip archive. ZipFile and
  47. /// ZipInputStream will give you instances of this class as information
  48. /// about the members in an archive. On the other hand ZipOutputStream
  49. /// needs an instance of this class to create a new member.
  50. ///
  51. /// author of the original java version : Jochen Hoenicke
  52. /// </summary>
  53. public class ZipEntry : ICloneable
  54. {
  55. static int KNOWN_SIZE = 1;
  56. static int KNOWN_CSIZE = 2;
  57. static int KNOWN_CRC = 4;
  58. static int KNOWN_TIME = 8;
  59. string name;
  60. uint size;
  61. ushort version;
  62. uint compressedSize;
  63. uint crc;
  64. uint dosTime;
  65. ushort known = 0;
  66. CompressionMethod method = CompressionMethod.Deflated;
  67. byte[] extra = null;
  68. string comment = null;
  69. bool isCrypted;
  70. int zipFileIndex = -1; /* used by ZipFile */
  71. int flags; /* used by ZipOutputStream */
  72. int offset; /* used by ZipFile and ZipOutputStream */
  73. public bool IsEncrypted {
  74. get {
  75. return (flags & 1) != 0;
  76. }
  77. set {
  78. if (value) {
  79. flags |= 1;
  80. } else {
  81. flags &= ~1;
  82. }
  83. }
  84. }
  85. public int ZipFileIndex {
  86. get {
  87. return zipFileIndex;
  88. }
  89. set {
  90. zipFileIndex = value;
  91. }
  92. }
  93. public int Offset {
  94. get {
  95. return offset;
  96. }
  97. set {
  98. offset = value;
  99. }
  100. }
  101. public int Flags { // Stops having two things represent same concept in class (flag isCrypted removed)
  102. get {
  103. return flags;
  104. }
  105. set {
  106. flags = value;
  107. }
  108. }
  109. /// <summary>
  110. /// Creates a zip entry with the given name.
  111. /// </summary>
  112. /// <param name="name">
  113. /// the name. May include directory components separated by '/'.
  114. /// </param>
  115. public ZipEntry(string name)
  116. {
  117. if (name == null) {
  118. throw new System.ArgumentNullException("name");
  119. }
  120. this.DateTime = System.DateTime.Now;
  121. this.name = name;
  122. }
  123. /// <summary>
  124. /// Creates a copy of the given zip entry.
  125. /// </summary>
  126. /// <param name="e">
  127. /// the entry to copy.
  128. /// </param>
  129. public ZipEntry(ZipEntry e)
  130. {
  131. name = e.name;
  132. known = e.known;
  133. size = e.size;
  134. compressedSize = e.compressedSize;
  135. crc = e.crc;
  136. dosTime = e.dosTime;
  137. method = e.method;
  138. extra = e.extra;
  139. comment = e.comment;
  140. }
  141. public int Version {
  142. get {
  143. return version;
  144. }
  145. set {
  146. version = (ushort)value;
  147. }
  148. }
  149. public long DosTime {
  150. get {
  151. if ((known & KNOWN_TIME) == 0) {
  152. return 0;
  153. } else {
  154. return dosTime;
  155. }
  156. }
  157. set {
  158. this.dosTime = (uint)value;
  159. known |= (ushort)KNOWN_TIME;
  160. }
  161. }
  162. /// <summary>
  163. /// Gets/Sets the time of last modification of the entry.
  164. /// </summary>
  165. public DateTime DateTime {
  166. get {
  167. uint sec = 2 * (dosTime & 0x1f);
  168. uint min = (dosTime >> 5) & 0x3f;
  169. uint hrs = (dosTime >> 11) & 0x1f;
  170. uint day = (dosTime >> 16) & 0x1f;
  171. uint mon = ((dosTime >> 21) & 0xf);
  172. uint year = ((dosTime >> 25) & 0x7f) + 1980; /* since 1900 */
  173. return new System.DateTime((int)year, (int)mon, (int)day, (int)hrs, (int)min, (int)sec);
  174. }
  175. set {
  176. DosTime = ((uint)value.Year - 1980 & 0x7f) << 25 |
  177. ((uint)value.Month) << 21 |
  178. ((uint)value.Day) << 16 |
  179. ((uint)value.Hour) << 11 |
  180. ((uint)value.Minute) << 5 |
  181. ((uint)value.Second) >> 1;
  182. }
  183. }
  184. /// <summary>
  185. /// Returns the entry name. The path components in the entry are
  186. /// always separated by slashes ('/').
  187. /// </summary>
  188. public string Name {
  189. get {
  190. return name;
  191. }
  192. }
  193. // /// <summary>
  194. // /// Gets/Sets the time of last modification of the entry.
  195. // /// </summary>
  196. // /// <returns>
  197. // /// the time of last modification of the entry, or -1 if unknown.
  198. // /// </returns>
  199. // public long Time {
  200. // get {
  201. // return (known & KNOWN_TIME) != 0 ? time * 1000L : -1;
  202. // }
  203. // set {
  204. // this.time = (int) (value / 1000L);
  205. // this.known |= (ushort)KNOWN_TIME;
  206. // }
  207. // }
  208. /// <summary>
  209. /// Gets/Sets the size of the uncompressed data.
  210. /// </summary>
  211. /// <exception cref="System.ArgumentOutOfRangeException">
  212. /// if size is not in 0..0xffffffffL
  213. /// </exception>
  214. /// <returns>
  215. /// the size or -1 if unknown.
  216. /// </returns>
  217. public long Size {
  218. get {
  219. return (known & KNOWN_SIZE) != 0 ? (long)size : -1L;
  220. }
  221. set {
  222. if (((ulong)value & 0xFFFFFFFF00000000L) != 0) {
  223. throw new ArgumentOutOfRangeException("size");
  224. }
  225. this.size = (uint)value;
  226. this.known |= (ushort)KNOWN_SIZE;
  227. }
  228. }
  229. /// <summary>
  230. /// Gets/Sets the size of the compressed data.
  231. /// </summary>
  232. /// <exception cref="System.ArgumentOutOfRangeException">
  233. /// if csize is not in 0..0xffffffffL
  234. /// </exception>
  235. /// <returns>
  236. /// the size or -1 if unknown.
  237. /// </returns>
  238. public long CompressedSize {
  239. get {
  240. return (known & KNOWN_CSIZE) != 0 ? (long)compressedSize : -1L;
  241. }
  242. set {
  243. if (((ulong)value & 0xffffffff00000000L) != 0) {
  244. throw new ArgumentOutOfRangeException();
  245. }
  246. this.compressedSize = (uint)value;
  247. this.known |= (ushort)KNOWN_CSIZE;
  248. }
  249. }
  250. /// <summary>
  251. /// Gets/Sets the crc of the uncompressed data.
  252. /// </summary>
  253. /// <exception cref="System.ArgumentOutOfRangeException">
  254. /// if crc is not in 0..0xffffffffL
  255. /// </exception>
  256. /// <returns>
  257. /// the crc or -1 if unknown.
  258. /// </returns>
  259. public long Crc {
  260. get {
  261. return (known & KNOWN_CRC) != 0 ? crc & 0xffffffffL : -1L;
  262. }
  263. set {
  264. if (((ulong)crc & 0xffffffff00000000L) != 0)
  265. {
  266. throw new Exception();
  267. }
  268. this.crc = (uint)value;
  269. this.known |= (ushort)KNOWN_CRC;
  270. }
  271. }
  272. /// <summary>
  273. /// Gets/Sets the compression method. Only DEFLATED and STORED are supported.
  274. /// </summary>
  275. /// <exception cref="System.ArgumentOutOfRangeException">
  276. /// if method is not supported.
  277. /// </exception>
  278. /// <returns>
  279. /// the compression method or -1 if unknown.
  280. /// </returns>
  281. /// <see cref="ZipOutputStream.DEFLATED"/>
  282. /// <see cref="ZipOutputStream.STORED"/>
  283. public CompressionMethod CompressionMethod {
  284. get {
  285. return method;
  286. }
  287. set {
  288. this.method = value;
  289. }
  290. }
  291. /// <summary>
  292. /// Gets/Sets the extra data.
  293. /// </summary>
  294. /// <exception cref="System.ArgumentOutOfRangeException">
  295. /// if extra is longer than 0xffff bytes.
  296. /// </exception>
  297. /// <returns>
  298. /// the extra data or null if not set.
  299. /// </returns>
  300. public byte[] ExtraData {
  301. get {
  302. return extra;
  303. }
  304. set {
  305. if (value == null) {
  306. this.extra = null;
  307. return;
  308. }
  309. if (value.Length > 0xffff) {
  310. throw new System.ArgumentOutOfRangeException();
  311. }
  312. this.extra = value;
  313. try {
  314. int pos = 0;
  315. while (pos < extra.Length) {
  316. int sig = (extra[pos++] & 0xff) | (extra[pos++] & 0xff) << 8;
  317. int len = (extra[pos++] & 0xff) | (extra[pos++] & 0xff) << 8;
  318. if (sig == 0x5455) {
  319. /* extended time stamp, unix format by Rainer Prem <[email protected]> */
  320. int flags = extra[pos];
  321. if ((flags & 1) != 0) {
  322. int iTime = ((extra[pos+1] & 0xff) |
  323. (extra[pos+2] & 0xff) << 8 |
  324. (extra[pos+3] & 0xff) << 16 |
  325. (extra[pos+4] & 0xff) << 24);
  326. DateTime = (new DateTime ( 1970, 1, 1, 0, 0, 0 ) + new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime ();
  327. known |= (ushort)KNOWN_TIME;
  328. }
  329. }
  330. pos += len;
  331. }
  332. } catch (Exception) {
  333. /* be lenient */
  334. return;
  335. }
  336. }
  337. }
  338. /// <summary>
  339. /// Gets/Sets the entry comment.
  340. /// </summary>
  341. /// <exception cref="System.ArgumentOutOfRangeException">
  342. /// if comment is longer than 0xffff.
  343. /// </exception>
  344. /// <returns>
  345. /// the comment or null if not set.
  346. /// </returns>
  347. public string Comment {
  348. get {
  349. return comment;
  350. }
  351. set {
  352. if (value.Length > 0xffff)
  353. {
  354. throw new ArgumentOutOfRangeException();
  355. }
  356. this.comment = value;
  357. }
  358. }
  359. /// <summary>
  360. /// Gets true, if the entry is a directory. This is solely
  361. /// determined by the name, a trailing slash '/' marks a directory.
  362. /// </summary>
  363. public bool IsDirectory {
  364. get {
  365. int nlen = name.Length;
  366. return nlen > 0 && name[nlen - 1] == '/';
  367. }
  368. }
  369. /// <value>
  370. /// True, if the entry is encrypted.
  371. /// </value>
  372. public bool IsCrypted {
  373. get {
  374. return isCrypted;
  375. }
  376. set {
  377. isCrypted = value;
  378. }
  379. }
  380. /// <summary>
  381. /// Creates a copy of this zip entry.
  382. /// </summary>
  383. public object Clone()
  384. {
  385. return this.MemberwiseClone();
  386. }
  387. /// <summary>
  388. /// Gets the string representation of this ZipEntry. This is just
  389. /// the name as returned by getName().
  390. /// </summary>
  391. public override string ToString()
  392. {
  393. return name;
  394. }
  395. }
  396. }