ZipEntry.cs 127 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979
  1. // ZipEntry.cs
  2. // ------------------------------------------------------------------
  3. //
  4. // Copyright (c) 2006-2010 Dino Chiesa.
  5. // All rights reserved.
  6. //
  7. // This code module is part of DotNetZip, a zipfile class library.
  8. //
  9. // ------------------------------------------------------------------
  10. //
  11. // This code is licensed under the Microsoft Public License.
  12. // See the file License.txt for the license details.
  13. // More info on: http://dotnetzip.codeplex.com
  14. //
  15. // ------------------------------------------------------------------
  16. //
  17. // last saved (in emacs):
  18. // Time-stamp: <2011-August-06 17:25:53>
  19. //
  20. // ------------------------------------------------------------------
  21. //
  22. // This module defines the ZipEntry class, which models the entries within a zip file.
  23. //
  24. // Created: Tue, 27 Mar 2007 15:30
  25. //
  26. // ------------------------------------------------------------------
  27. using System;
  28. using System.IO;
  29. using Interop = System.Runtime.InteropServices;
  30. namespace Ionic.Zip
  31. {
  32. /// <summary>
  33. /// Represents a single entry in a ZipFile. Typically, applications get a ZipEntry
  34. /// by enumerating the entries within a ZipFile, or by adding an entry to a ZipFile.
  35. /// </summary>
  36. [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00004")]
  37. [Interop.ComVisible(true)]
  38. #if !NETCF
  39. [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)] // AutoDual
  40. #endif
  41. public partial class ZipEntry
  42. {
  43. /// <summary>
  44. /// Default constructor.
  45. /// </summary>
  46. /// <remarks>
  47. /// Applications should never need to call this directly. It is exposed to
  48. /// support COM Automation environments.
  49. /// </remarks>
  50. public ZipEntry()
  51. {
  52. _CompressionMethod = (Int16)CompressionMethod.Deflate;
  53. _CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
  54. _Encryption = EncryptionAlgorithm.None;
  55. _Source = ZipEntrySource.None;
  56. AlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
  57. AlternateEncodingUsage = ZipOption.Never;
  58. }
  59. /// <summary>
  60. /// The time and date at which the file indicated by the <c>ZipEntry</c> was
  61. /// last modified.
  62. /// </summary>
  63. ///
  64. /// <remarks>
  65. /// <para>
  66. /// The DotNetZip library sets the LastModified value for an entry, equal to
  67. /// the Last Modified time of the file in the filesystem. If an entry is
  68. /// added from a stream, the library uses <c>System.DateTime.Now</c> for this
  69. /// value, for the given entry.
  70. /// </para>
  71. ///
  72. /// <para>
  73. /// This property allows the application to retrieve and possibly set the
  74. /// LastModified value on an entry, to an arbitrary value. <see
  75. /// cref="System.DateTime"/> values with a <see cref="System.DateTimeKind" />
  76. /// setting of <c>DateTimeKind.Unspecified</c> are taken to be expressed as
  77. /// <c>DateTimeKind.Local</c>.
  78. /// </para>
  79. ///
  80. /// <para>
  81. /// Be aware that because of the way <see
  82. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWare's
  83. /// Zip specification</see> describes how times are stored in the zip file,
  84. /// the full precision of the <c>System.DateTime</c> datatype is not stored
  85. /// for the last modified time when saving zip files. For more information on
  86. /// how times are formatted, see the PKZip specification.
  87. /// </para>
  88. ///
  89. /// <para>
  90. /// The actual last modified time of a file can be stored in multiple ways in
  91. /// the zip file, and they are not mutually exclusive:
  92. /// </para>
  93. ///
  94. /// <list type="bullet">
  95. /// <item>
  96. /// In the so-called "DOS" format, which has a 2-second precision. Values
  97. /// are rounded to the nearest even second. For example, if the time on the
  98. /// file is 12:34:43, then it will be stored as 12:34:44. This first value
  99. /// is accessible via the <c>LastModified</c> property. This value is always
  100. /// present in the metadata for each zip entry. In some cases the value is
  101. /// invalid, or zero.
  102. /// </item>
  103. ///
  104. /// <item>
  105. /// In the so-called "Windows" or "NTFS" format, as an 8-byte integer
  106. /// quantity expressed as the number of 1/10 milliseconds (in other words
  107. /// the number of 100 nanosecond units) since January 1, 1601 (UTC). This
  108. /// format is how Windows represents file times. This time is accessible
  109. /// via the <c>ModifiedTime</c> property.
  110. /// </item>
  111. ///
  112. /// <item>
  113. /// In the "Unix" format, a 4-byte quantity specifying the number of seconds since
  114. /// January 1, 1970 UTC.
  115. /// </item>
  116. ///
  117. /// <item>
  118. /// In an older format, now deprecated but still used by some current
  119. /// tools. This format is also a 4-byte quantity specifying the number of
  120. /// seconds since January 1, 1970 UTC.
  121. /// </item>
  122. ///
  123. /// </list>
  124. ///
  125. /// <para>
  126. /// Zip tools and libraries will always at least handle (read or write) the
  127. /// DOS time, and may also handle the other time formats. Keep in mind that
  128. /// while the names refer to particular operating systems, there is nothing in
  129. /// the time formats themselves that prevents their use on other operating
  130. /// systems.
  131. /// </para>
  132. ///
  133. /// <para>
  134. /// When reading ZIP files, the DotNetZip library reads the Windows-formatted
  135. /// time, if it is stored in the entry, and sets both <c>LastModified</c> and
  136. /// <c>ModifiedTime</c> to that value. When writing ZIP files, the DotNetZip
  137. /// library by default will write both time quantities. It can also emit the
  138. /// Unix-formatted time if desired (See <see
  139. /// cref="EmitTimesInUnixFormatWhenSaving"/>.)
  140. /// </para>
  141. ///
  142. /// <para>
  143. /// The last modified time of the file created upon a call to
  144. /// <c>ZipEntry.Extract()</c> may be adjusted during extraction to compensate
  145. /// for differences in how the .NET Base Class Library deals with daylight
  146. /// saving time (DST) versus how the Windows filesystem deals with daylight
  147. /// saving time. Raymond Chen <see
  148. /// href="http://blogs.msdn.com/oldnewthing/archive/2003/10/24/55413.aspx">provides
  149. /// some good context</see>.
  150. /// </para>
  151. ///
  152. /// <para>
  153. /// In a nutshell: Daylight savings time rules change regularly. In 2007, for
  154. /// example, the inception week of DST changed. In 1977, DST was in place all
  155. /// year round. In 1945, likewise. And so on. Win32 does not attempt to
  156. /// guess which time zone rules were in effect at the time in question. It
  157. /// will render a time as "standard time" and allow the app to change to DST
  158. /// as necessary. .NET makes a different choice.
  159. /// </para>
  160. ///
  161. /// <para>
  162. /// Compare the output of FileInfo.LastWriteTime.ToString("f") with what you
  163. /// see in the Windows Explorer property sheet for a file that was last
  164. /// written to on the other side of the DST transition. For example, suppose
  165. /// the file was last modified on October 17, 2003, during DST but DST is not
  166. /// currently in effect. Explorer's file properties reports Thursday, October
  167. /// 17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17,
  168. /// 2003, 9:45 AM.
  169. /// </para>
  170. ///
  171. /// <para>
  172. /// Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific
  173. /// STANDARD Time. Even though October 17 of that year occurred during Pacific
  174. /// Daylight Time, Win32 displays the time as standard time because that's
  175. /// what time it is NOW.
  176. /// </para>
  177. ///
  178. /// <para>
  179. /// .NET BCL assumes that the current DST rules were in place at the time in
  180. /// question. So, .NET says, "Well, if the rules in effect now were also in
  181. /// effect on October 17, 2003, then that would be daylight time" so it
  182. /// displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time.
  183. /// </para>
  184. ///
  185. /// <para>
  186. /// So .NET gives a value which is more intuitively correct, but is also
  187. /// potentially incorrect, and which is not invertible. Win32 gives a value
  188. /// which is intuitively incorrect, but is strictly correct.
  189. /// </para>
  190. ///
  191. /// <para>
  192. /// Because of this funkiness, this library adds one hour to the LastModified
  193. /// time on the extracted file, if necessary. That is to say, if the time in
  194. /// question had occurred in what the .NET Base Class Library assumed to be
  195. /// DST. This assumption may be wrong given the constantly changing DST rules,
  196. /// but it is the best we can do.
  197. /// </para>
  198. ///
  199. /// </remarks>
  200. ///
  201. public DateTime LastModified
  202. {
  203. get { return _LastModified.ToLocalTime(); }
  204. set
  205. {
  206. _LastModified = (value.Kind == DateTimeKind.Unspecified)
  207. ? DateTime.SpecifyKind(value, DateTimeKind.Local)
  208. : value.ToLocalTime();
  209. _Mtime = Ionic.Zip.SharedUtilities.AdjustTime_Reverse(_LastModified).ToUniversalTime();
  210. _metadataChanged = true;
  211. }
  212. }
  213. /// <summary>
  214. /// Ability to set Last Modified DOS time to zero
  215. /// (for using with EmitTimesInWindowsFormatWhenSaving+EmitTimesInUnixFormatWhenSaving setted to false)
  216. /// some flasher hardware use as marker of first binary
  217. /// </summary>
  218. public bool DontEmitLastModified
  219. {
  220. get { return _dontEmitLastModified; }
  221. set { _dontEmitLastModified = value; }
  222. }
  223. int BufferSize
  224. {
  225. get
  226. {
  227. return _container.BufferSize;
  228. }
  229. }
  230. /// <summary>
  231. /// Last Modified time for the file represented by the entry.
  232. /// </summary>
  233. ///
  234. /// <remarks>
  235. ///
  236. /// <para>
  237. /// This value corresponds to the "last modified" time in the NTFS file times
  238. /// as described in <see
  239. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
  240. /// specification</see>. When getting this property, the value may be
  241. /// different from <see cref="LastModified" />. When setting the property,
  242. /// the <see cref="LastModified"/> property also gets set, but with a lower
  243. /// precision.
  244. /// </para>
  245. ///
  246. /// <para>
  247. /// Let me explain. It's going to take a while, so get
  248. /// comfortable. Originally, waaaaay back in 1989 when the ZIP specification
  249. /// was originally described by the esteemed Mr. Phil Katz, the dominant
  250. /// operating system of the time was MS-DOS. MSDOS stored file times with a
  251. /// 2-second precision, because, c'mon, <em>who is ever going to need better
  252. /// resolution than THAT?</em> And so ZIP files, regardless of the platform on
  253. /// which the zip file was created, store file times in exactly <see
  254. /// href="http://www.vsft.com/hal/dostime.htm">the same format that DOS used
  255. /// in 1989</see>.
  256. /// </para>
  257. ///
  258. /// <para>
  259. /// Since then, the ZIP spec has evolved, but the internal format for file
  260. /// timestamps remains the same. Despite the fact that the way times are
  261. /// stored in a zip file is rooted in DOS heritage, any program on any
  262. /// operating system can format a time in this way, and most zip tools and
  263. /// libraries DO - they round file times to the nearest even second and store
  264. /// it just like DOS did 25+ years ago.
  265. /// </para>
  266. ///
  267. /// <para>
  268. /// PKWare extended the ZIP specification to allow a zip file to store what
  269. /// are called "NTFS Times" and "Unix(tm) times" for a file. These are the
  270. /// <em>last write</em>, <em>last access</em>, and <em>file creation</em>
  271. /// times of a particular file. These metadata are not actually specific
  272. /// to NTFS or Unix. They are tracked for each file by NTFS and by various
  273. /// Unix filesystems, but they are also tracked by other filesystems, too.
  274. /// The key point is that the times are <em>formatted in the zip file</em>
  275. /// in the same way that NTFS formats the time (ticks since win32 epoch),
  276. /// or in the same way that Unix formats the time (seconds since Unix
  277. /// epoch). As with the DOS time, any tool or library running on any
  278. /// operating system is capable of formatting a time in one of these ways
  279. /// and embedding it into the zip file.
  280. /// </para>
  281. ///
  282. /// <para>
  283. /// These extended times are higher precision quantities than the DOS time.
  284. /// As described above, the (DOS) LastModified has a precision of 2 seconds.
  285. /// The Unix time is stored with a precision of 1 second. The NTFS time is
  286. /// stored with a precision of 0.0000001 seconds. The quantities are easily
  287. /// convertible, except for the loss of precision you may incur.
  288. /// </para>
  289. ///
  290. /// <para>
  291. /// A zip archive can store the {C,A,M} times in NTFS format, in Unix format,
  292. /// or not at all. Often a tool running on Unix or Mac will embed the times
  293. /// in Unix format (1 second precision), while WinZip running on Windows might
  294. /// embed the times in NTFS format (precision of of 0.0000001 seconds). When
  295. /// reading a zip file with these "extended" times, in either format,
  296. /// DotNetZip represents the values with the
  297. /// <c>ModifiedTime</c>, <c>AccessedTime</c> and <c>CreationTime</c>
  298. /// properties on the <c>ZipEntry</c>.
  299. /// </para>
  300. ///
  301. /// <para>
  302. /// While any zip application or library, regardless of the platform it
  303. /// runs on, could use any of the time formats allowed by the ZIP
  304. /// specification, not all zip tools or libraries do support all these
  305. /// formats. Storing the higher-precision times for each entry is
  306. /// optional for zip files, and many tools and libraries don't use the
  307. /// higher precision quantities at all. The old DOS time, represented by
  308. /// <see cref="LastModified"/>, is guaranteed to be present, though it
  309. /// sometimes unset.
  310. /// </para>
  311. ///
  312. /// <para>
  313. /// Ok, getting back to the question about how the <c>LastModified</c>
  314. /// property relates to this <c>ModifiedTime</c>
  315. /// property... <c>LastModified</c> is always set, while
  316. /// <c>ModifiedTime</c> is not. (The other times stored in the <em>NTFS
  317. /// times extension</em>, <c>CreationTime</c> and <c>AccessedTime</c> also
  318. /// may not be set on an entry that is read from an existing zip file.)
  319. /// When reading a zip file, then <c>LastModified</c> takes the DOS time
  320. /// that is stored with the file. If the DOS time has been stored as zero
  321. /// in the zipfile, then this library will use <c>DateTime.Now</c> for the
  322. /// <c>LastModified</c> value. If the ZIP file was created by an evolved
  323. /// tool, then there will also be higher precision NTFS or Unix times in
  324. /// the zip file. In that case, this library will read those times, and
  325. /// set <c>LastModified</c> and <c>ModifiedTime</c> to the same value, the
  326. /// one corresponding to the last write time of the file. If there are no
  327. /// higher precision times stored for the entry, then <c>ModifiedTime</c>
  328. /// remains unset (likewise <c>AccessedTime</c> and <c>CreationTime</c>),
  329. /// and <c>LastModified</c> keeps its DOS time.
  330. /// </para>
  331. ///
  332. /// <para>
  333. /// When creating zip files with this library, by default the extended time
  334. /// properties (<c>ModifiedTime</c>, <c>AccessedTime</c>, and
  335. /// <c>CreationTime</c>) are set on the ZipEntry instance, and these data are
  336. /// stored in the zip archive for each entry, in NTFS format. If you add an
  337. /// entry from an actual filesystem file, then the entry gets the actual file
  338. /// times for that file, to NTFS-level precision. If you add an entry from a
  339. /// stream, or a string, then the times get the value <c>DateTime.Now</c>. In
  340. /// this case <c>LastModified</c> and <c>ModifiedTime</c> will be identical,
  341. /// to 2 seconds of precision. You can explicitly set the
  342. /// <c>CreationTime</c>, <c>AccessedTime</c>, and <c>ModifiedTime</c> of an
  343. /// entry using the property setters. If you want to set all of those
  344. /// quantities, it's more efficient to use the <see
  345. /// cref="SetEntryTimes(DateTime, DateTime, DateTime)"/> method. Those
  346. /// changes are not made permanent in the zip file until you call <see
  347. /// cref="ZipFile.Save()"/> or one of its cousins.
  348. /// </para>
  349. ///
  350. /// <para>
  351. /// When creating a zip file, you can override the default behavior of
  352. /// this library for formatting times in the zip file, disabling the
  353. /// embedding of file times in NTFS format or enabling the storage of file
  354. /// times in Unix format, or both. You may want to do this, for example,
  355. /// when creating a zip file on Windows, that will be consumed on a Mac,
  356. /// by an application that is not hip to the "NTFS times" format. To do
  357. /// this, use the <see cref="EmitTimesInWindowsFormatWhenSaving"/> and
  358. /// <see cref="EmitTimesInUnixFormatWhenSaving"/> properties. A valid zip
  359. /// file may store the file times in both formats. But, there are no
  360. /// guarantees that a program running on Mac or Linux will gracefully
  361. /// handle the NTFS-formatted times when Unix times are present, or that a
  362. /// non-DotNetZip-powered application running on Windows will be able to
  363. /// handle file times in Unix format. DotNetZip will always do something
  364. /// reasonable; other libraries or tools may not. When in doubt, test.
  365. /// </para>
  366. ///
  367. /// <para>
  368. /// I'll bet you didn't think one person could type so much about time, eh?
  369. /// And reading it was so enjoyable, too! Well, in appreciation, <see
  370. /// href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">maybe you
  371. /// should donate</see>?
  372. /// </para>
  373. /// </remarks>
  374. ///
  375. /// <seealso cref="AccessedTime"/>
  376. /// <seealso cref="CreationTime"/>
  377. /// <seealso cref="Ionic.Zip.ZipEntry.LastModified"/>
  378. /// <seealso cref="SetEntryTimes"/>
  379. public DateTime ModifiedTime
  380. {
  381. get { return _Mtime; }
  382. set
  383. {
  384. SetEntryTimes(_Ctime, _Atime, value);
  385. }
  386. }
  387. /// <summary>
  388. /// Last Access time for the file represented by the entry.
  389. /// </summary>
  390. /// <remarks>
  391. /// This value may or may not be meaningful. If the <c>ZipEntry</c> was read from an existing
  392. /// Zip archive, this information may not be available. For an explanation of why, see
  393. /// <see cref="ModifiedTime"/>.
  394. /// </remarks>
  395. /// <seealso cref="ModifiedTime"/>
  396. /// <seealso cref="CreationTime"/>
  397. /// <seealso cref="SetEntryTimes"/>
  398. public DateTime AccessedTime
  399. {
  400. get { return _Atime; }
  401. set
  402. {
  403. SetEntryTimes(_Ctime, value, _Mtime);
  404. }
  405. }
  406. /// <summary>
  407. /// The file creation time for the file represented by the entry.
  408. /// </summary>
  409. ///
  410. /// <remarks>
  411. /// This value may or may not be meaningful. If the <c>ZipEntry</c> was read
  412. /// from an existing zip archive, and the creation time was not set on the entry
  413. /// when the zip file was created, then this property may be meaningless. For an
  414. /// explanation of why, see <see cref="ModifiedTime"/>.
  415. /// </remarks>
  416. /// <seealso cref="ModifiedTime"/>
  417. /// <seealso cref="AccessedTime"/>
  418. /// <seealso cref="SetEntryTimes"/>
  419. public DateTime CreationTime
  420. {
  421. get { return _Ctime; }
  422. set
  423. {
  424. SetEntryTimes(value, _Atime, _Mtime);
  425. }
  426. }
  427. /// <summary>
  428. /// Sets the NTFS Creation, Access, and Modified times for the given entry.
  429. /// </summary>
  430. ///
  431. /// <remarks>
  432. /// <para>
  433. /// When adding an entry from a file or directory, the Creation, Access, and
  434. /// Modified times for the given entry are automatically set from the
  435. /// filesystem values. When adding an entry from a stream or string, the
  436. /// values are implicitly set to DateTime.Now. The application may wish to
  437. /// set these values to some arbitrary value, before saving the archive, and
  438. /// can do so using the various setters. If you want to set all of the times,
  439. /// this method is more efficient.
  440. /// </para>
  441. ///
  442. /// <para>
  443. /// The values you set here will be retrievable with the <see
  444. /// cref="ModifiedTime"/>, <see cref="CreationTime"/> and <see
  445. /// cref="AccessedTime"/> properties.
  446. /// </para>
  447. ///
  448. /// <para>
  449. /// When this method is called, if both <see
  450. /// cref="EmitTimesInWindowsFormatWhenSaving"/> and <see
  451. /// cref="EmitTimesInUnixFormatWhenSaving"/> are false, then the
  452. /// <c>EmitTimesInWindowsFormatWhenSaving</c> flag is automatically set.
  453. /// </para>
  454. ///
  455. /// <para>
  456. /// DateTime values provided here without a DateTimeKind are assumed to be Local Time.
  457. /// </para>
  458. ///
  459. /// </remarks>
  460. /// <param name="created">the creation time of the entry.</param>
  461. /// <param name="accessed">the last access time of the entry.</param>
  462. /// <param name="modified">the last modified time of the entry.</param>
  463. ///
  464. /// <seealso cref="EmitTimesInWindowsFormatWhenSaving" />
  465. /// <seealso cref="EmitTimesInUnixFormatWhenSaving" />
  466. /// <seealso cref="AccessedTime"/>
  467. /// <seealso cref="CreationTime"/>
  468. /// <seealso cref="ModifiedTime"/>
  469. public void SetEntryTimes(DateTime created, DateTime accessed, DateTime modified)
  470. {
  471. _ntfsTimesAreSet = true;
  472. if (created == _zeroHour && created.Kind == _zeroHour.Kind) created = _win32Epoch;
  473. if (accessed == _zeroHour && accessed.Kind == _zeroHour.Kind) accessed = _win32Epoch;
  474. if (modified == _zeroHour && modified.Kind == _zeroHour.Kind) modified = _win32Epoch;
  475. _Ctime = created.ToUniversalTime();
  476. _Atime = accessed.ToUniversalTime();
  477. _Mtime = modified.ToUniversalTime();
  478. _LastModified = _Mtime;
  479. if (!_emitUnixTimes && !_emitNtfsTimes)
  480. _emitNtfsTimes = true;
  481. _metadataChanged = true;
  482. }
  483. /// <summary>
  484. /// Specifies whether the Creation, Access, and Modified times for the given
  485. /// entry will be emitted in "Windows format" when the zip archive is saved.
  486. /// </summary>
  487. ///
  488. /// <remarks>
  489. /// <para>
  490. /// An application creating a zip archive can use this flag to explicitly
  491. /// specify that the file times for the entry should or should not be stored
  492. /// in the zip archive in the format used by Windows. The default value of
  493. /// this property is <c>true</c>.
  494. /// </para>
  495. ///
  496. /// <para>
  497. /// When adding an entry from a file or directory, the Creation (<see
  498. /// cref="CreationTime"/>), Access (<see cref="AccessedTime"/>), and Modified
  499. /// (<see cref="ModifiedTime"/>) times for the given entry are automatically
  500. /// set from the filesystem values. When adding an entry from a stream or
  501. /// string, all three values are implicitly set to DateTime.Now. Applications
  502. /// can also explicitly set those times by calling <see
  503. /// cref="SetEntryTimes(DateTime, DateTime, DateTime)" />.
  504. /// </para>
  505. ///
  506. /// <para>
  507. /// <see
  508. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
  509. /// zip specification</see> describes multiple ways to format these times in a
  510. /// zip file. One is the format Windows applications normally use: 100ns ticks
  511. /// since Jan 1, 1601 UTC. The other is a format Unix applications typically
  512. /// use: seconds since January 1, 1970 UTC. Each format can be stored in an
  513. /// "extra field" in the zip entry when saving the zip archive. The former
  514. /// uses an extra field with a Header Id of 0x000A, while the latter uses a
  515. /// header ID of 0x5455.
  516. /// </para>
  517. ///
  518. /// <para>
  519. /// Not all zip tools and libraries can interpret these fields. Windows
  520. /// compressed folders is one that can read the Windows Format timestamps,
  521. /// while I believe the <see href="http://www.info-zip.org/">Infozip</see>
  522. /// tools can read the Unix format timestamps. Although the time values are
  523. /// easily convertible, subject to a loss of precision, some tools and
  524. /// libraries may be able to read only one or the other. DotNetZip can read or
  525. /// write times in either or both formats.
  526. /// </para>
  527. ///
  528. /// <para>
  529. /// The times stored are taken from <see cref="ModifiedTime"/>, <see
  530. /// cref="AccessedTime"/>, and <see cref="CreationTime"/>.
  531. /// </para>
  532. ///
  533. /// <para>
  534. /// This property is not mutually exclusive from the <see
  535. /// cref="ZipEntry.EmitTimesInUnixFormatWhenSaving"/> property. It is
  536. /// possible that a zip entry can embed the timestamps in both forms, one
  537. /// form, or neither. But, there are no guarantees that a program running on
  538. /// Mac or Linux will gracefully handle NTFS Formatted times, or that a
  539. /// non-DotNetZip-powered application running on Windows will be able to
  540. /// handle file times in Unix format. When in doubt, test.
  541. /// </para>
  542. ///
  543. /// <para>
  544. /// Normally you will use the <see
  545. /// cref="ZipFile.EmitTimesInWindowsFormatWhenSaving">ZipFile.EmitTimesInWindowsFormatWhenSaving</see>
  546. /// property, to specify the behavior for all entries in a zip, rather than
  547. /// the property on each individual entry.
  548. /// </para>
  549. ///
  550. /// </remarks>
  551. ///
  552. /// <seealso cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>
  553. /// <seealso cref="EmitTimesInUnixFormatWhenSaving"/>
  554. /// <seealso cref="CreationTime"/>
  555. /// <seealso cref="AccessedTime"/>
  556. /// <seealso cref="ModifiedTime"/>
  557. public bool EmitTimesInWindowsFormatWhenSaving
  558. {
  559. get
  560. {
  561. return _emitNtfsTimes;
  562. }
  563. set
  564. {
  565. _emitNtfsTimes = value;
  566. _metadataChanged = true;
  567. }
  568. }
  569. /// <summary>
  570. /// Specifies whether the Creation, Access, and Modified times for the given
  571. /// entry will be emitted in &quot;Unix(tm) format&quot; when the zip archive is saved.
  572. /// </summary>
  573. ///
  574. /// <remarks>
  575. /// <para>
  576. /// An application creating a zip archive can use this flag to explicitly
  577. /// specify that the file times for the entry should or should not be stored
  578. /// in the zip archive in the format used by Unix. By default this flag is
  579. /// <c>false</c>, meaning the Unix-format times are not stored in the zip
  580. /// archive.
  581. /// </para>
  582. ///
  583. /// <para>
  584. /// When adding an entry from a file or directory, the Creation (<see
  585. /// cref="CreationTime"/>), Access (<see cref="AccessedTime"/>), and Modified
  586. /// (<see cref="ModifiedTime"/>) times for the given entry are automatically
  587. /// set from the filesystem values. When adding an entry from a stream or
  588. /// string, all three values are implicitly set to DateTime.Now. Applications
  589. /// can also explicitly set those times by calling <see
  590. /// cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>.
  591. /// </para>
  592. ///
  593. /// <para>
  594. /// <see
  595. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
  596. /// zip specification</see> describes multiple ways to format these times in a
  597. /// zip file. One is the format Windows applications normally use: 100ns ticks
  598. /// since Jan 1, 1601 UTC. The other is a format Unix applications typically
  599. /// use: seconds since Jan 1, 1970 UTC. Each format can be stored in an
  600. /// "extra field" in the zip entry when saving the zip archive. The former
  601. /// uses an extra field with a Header Id of 0x000A, while the latter uses a
  602. /// header ID of 0x5455.
  603. /// </para>
  604. ///
  605. /// <para>
  606. /// Not all tools and libraries can interpret these fields. Windows
  607. /// compressed folders is one that can read the Windows Format timestamps,
  608. /// while I believe the <see href="http://www.info-zip.org/">Infozip</see>
  609. /// tools can read the Unix format timestamps. Although the time values are
  610. /// easily convertible, subject to a loss of precision, some tools and
  611. /// libraries may be able to read only one or the other. DotNetZip can read or
  612. /// write times in either or both formats.
  613. /// </para>
  614. ///
  615. /// <para>
  616. /// The times stored are taken from <see cref="ModifiedTime"/>, <see
  617. /// cref="AccessedTime"/>, and <see cref="CreationTime"/>.
  618. /// </para>
  619. ///
  620. /// <para>
  621. /// This property is not mutually exclusive from the <see
  622. /// cref="ZipEntry.EmitTimesInWindowsFormatWhenSaving"/> property. It is
  623. /// possible that a zip entry can embed the timestamps in both forms, one
  624. /// form, or neither. But, there are no guarantees that a program running on
  625. /// Mac or Linux will gracefully handle NTFS Formatted times, or that a
  626. /// non-DotNetZip-powered application running on Windows will be able to
  627. /// handle file times in Unix format. When in doubt, test.
  628. /// </para>
  629. ///
  630. /// <para>
  631. /// Normally you will use the <see
  632. /// cref="ZipFile.EmitTimesInUnixFormatWhenSaving">ZipFile.EmitTimesInUnixFormatWhenSaving</see>
  633. /// property, to specify the behavior for all entries, rather than the
  634. /// property on each individual entry.
  635. /// </para>
  636. /// </remarks>
  637. ///
  638. /// <seealso cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>
  639. /// <seealso cref="EmitTimesInWindowsFormatWhenSaving"/>
  640. /// <seealso cref="ZipFile.EmitTimesInUnixFormatWhenSaving"/>
  641. /// <seealso cref="CreationTime"/>
  642. /// <seealso cref="AccessedTime"/>
  643. /// <seealso cref="ModifiedTime"/>
  644. public bool EmitTimesInUnixFormatWhenSaving
  645. {
  646. get
  647. {
  648. return _emitUnixTimes;
  649. }
  650. set
  651. {
  652. _emitUnixTimes = value;
  653. _metadataChanged = true;
  654. }
  655. }
  656. /// <summary>
  657. /// The type of timestamp attached to the ZipEntry.
  658. /// </summary>
  659. ///
  660. /// <remarks>
  661. /// This property is valid only for a ZipEntry that was read from a zip archive.
  662. /// It indicates the type of timestamp attached to the entry.
  663. /// </remarks>
  664. ///
  665. /// <seealso cref="EmitTimesInWindowsFormatWhenSaving"/>
  666. /// <seealso cref="EmitTimesInUnixFormatWhenSaving"/>
  667. public ZipEntryTimestamp Timestamp
  668. {
  669. get
  670. {
  671. return _timestamp;
  672. }
  673. }
  674. /// <summary>
  675. /// The file attributes for the entry.
  676. /// </summary>
  677. ///
  678. /// <remarks>
  679. ///
  680. /// <para>
  681. /// The <see cref="System.IO.FileAttributes">attributes</see> in NTFS include
  682. /// ReadOnly, Archive, Hidden, System, and Indexed. When adding a
  683. /// <c>ZipEntry</c> to a ZipFile, these attributes are set implicitly when
  684. /// adding an entry from the filesystem. When adding an entry from a stream
  685. /// or string, the Attributes are not set implicitly. Regardless of the way
  686. /// an entry was added to a <c>ZipFile</c>, you can set the attributes
  687. /// explicitly if you like.
  688. /// </para>
  689. ///
  690. /// <para>
  691. /// When reading a <c>ZipEntry</c> from a <c>ZipFile</c>, the attributes are
  692. /// set according to the data stored in the <c>ZipFile</c>. If you extract the
  693. /// entry from the archive to a filesystem file, DotNetZip will set the
  694. /// attributes on the resulting file accordingly.
  695. /// </para>
  696. ///
  697. /// <para>
  698. /// The attributes can be set explicitly by the application. For example the
  699. /// application may wish to set the <c>FileAttributes.ReadOnly</c> bit for all
  700. /// entries added to an archive, so that on unpack, this attribute will be set
  701. /// on the extracted file. Any changes you make to this property are made
  702. /// permanent only when you call a <c>Save()</c> method on the <c>ZipFile</c>
  703. /// instance that contains the ZipEntry.
  704. /// </para>
  705. ///
  706. /// <para>
  707. /// For example, an application may wish to zip up a directory and set the
  708. /// ReadOnly bit on every file in the archive, so that upon later extraction,
  709. /// the resulting files will be marked as ReadOnly. Not every extraction tool
  710. /// respects these attributes, but if you unpack with DotNetZip, as for
  711. /// example in a self-extracting archive, then the attributes will be set as
  712. /// they are stored in the <c>ZipFile</c>.
  713. /// </para>
  714. ///
  715. /// <para>
  716. /// These attributes may not be interesting or useful if the resulting archive
  717. /// is extracted on a non-Windows platform. How these attributes get used
  718. /// upon extraction depends on the platform and tool used.
  719. /// </para>
  720. ///
  721. /// <para>
  722. /// This property is only partially supported in the Silverlight version
  723. /// of the library: applications can read attributes on entries within
  724. /// ZipFiles. But extracting entries within Silverlight will not set the
  725. /// attributes on the extracted files.
  726. /// </para>
  727. ///
  728. /// </remarks>
  729. public System.IO.FileAttributes Attributes
  730. {
  731. // workitem 7071
  732. get { return (System.IO.FileAttributes)_ExternalFileAttrs; }
  733. set
  734. {
  735. _ExternalFileAttrs = (int)value;
  736. // Since the application is explicitly setting the attributes, overwriting
  737. // whatever was there, we will explicitly set the Version made by field.
  738. // workitem 7926 - "version made by" OS should be zero for compat with WinZip
  739. _VersionMadeBy = (0 << 8) + 45; // v4.5 of the spec
  740. _metadataChanged = true;
  741. }
  742. }
  743. /// <summary>
  744. /// The name of the filesystem file, referred to by the ZipEntry.
  745. /// </summary>
  746. ///
  747. /// <remarks>
  748. /// <para>
  749. /// This property specifies the thing-to-be-zipped on disk, and is set only
  750. /// when the <c>ZipEntry</c> is being created from a filesystem file. If the
  751. /// <c>ZipFile</c> is instantiated by reading an existing .zip archive, then
  752. /// the LocalFileName will be <c>null</c> (<c>Nothing</c> in VB).
  753. /// </para>
  754. ///
  755. /// <para>
  756. /// When it is set, the value of this property may be different than <see
  757. /// cref="FileName"/>, which is the path used in the archive itself. If you
  758. /// call <c>Zip.AddFile("foop.txt", AlternativeDirectory)</c>, then the path
  759. /// used for the <c>ZipEntry</c> within the zip archive will be different
  760. /// than this path.
  761. /// </para>
  762. ///
  763. /// <para>
  764. /// If the entry is being added from a stream, then this is null (Nothing in VB).
  765. /// </para>
  766. ///
  767. /// </remarks>
  768. /// <seealso cref="FileName"/>
  769. internal string LocalFileName
  770. {
  771. get { return _LocalFileName; }
  772. }
  773. /// <summary>
  774. /// The name of the file contained in the ZipEntry.
  775. /// </summary>
  776. ///
  777. /// <remarks>
  778. ///
  779. /// <para>
  780. /// This is the name of the entry in the <c>ZipFile</c> itself. When creating
  781. /// a zip archive, if the <c>ZipEntry</c> has been created from a filesystem
  782. /// file, via a call to <see cref="ZipFile.AddFile(String,String)"/> or <see
  783. /// cref="ZipFile.AddItem(String,String)"/>, or a related overload, the value
  784. /// of this property is derived from the name of that file. The
  785. /// <c>FileName</c> property does not include drive letters, and may include a
  786. /// different directory path, depending on the value of the
  787. /// <c>directoryPathInArchive</c> parameter used when adding the entry into
  788. /// the <c>ZipFile</c>.
  789. /// </para>
  790. ///
  791. /// <para>
  792. /// In some cases there is no related filesystem file - for example when a
  793. /// <c>ZipEntry</c> is created using <see cref="ZipFile.AddEntry(string,
  794. /// string)"/> or one of the similar overloads. In this case, the value of
  795. /// this property is derived from the fileName and the directory path passed
  796. /// to that method.
  797. /// </para>
  798. ///
  799. /// <para>
  800. /// When reading a zip file, this property takes the value of the entry name
  801. /// as stored in the zip file. If you extract such an entry, the extracted
  802. /// file will take the name given by this property.
  803. /// </para>
  804. ///
  805. /// <para>
  806. /// Applications can set this property when creating new zip archives or when
  807. /// reading existing archives. When setting this property, the actual value
  808. /// that is set will replace backslashes with forward slashes, in accordance
  809. /// with <see
  810. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
  811. /// specification</see>, for compatibility with Unix(tm) and ... get
  812. /// this.... Amiga!
  813. /// </para>
  814. ///
  815. /// <para>
  816. /// If an application reads a <c>ZipFile</c> via <see
  817. /// cref="ZipFile.Read(String)"/> or a related overload, and then explicitly
  818. /// sets the FileName on an entry contained within the <c>ZipFile</c>, and
  819. /// then calls <see cref="ZipFile.Save()"/>, the application will effectively
  820. /// rename the entry within the zip archive.
  821. /// </para>
  822. ///
  823. /// <para>
  824. /// If an application sets the value of <c>FileName</c>, then calls
  825. /// <c>Extract()</c> on the entry, the entry is extracted to a file using the
  826. /// newly set value as the filename. The <c>FileName</c> value is made
  827. /// permanent in the zip archive only <em>after</em> a call to one of the
  828. /// <c>ZipFile.Save()</c> methods on the <c>ZipFile</c> that contains the
  829. /// ZipEntry.
  830. /// </para>
  831. ///
  832. /// <para>
  833. /// If an application attempts to set the <c>FileName</c> to a value that
  834. /// would result in a duplicate entry in the <c>ZipFile</c>, an exception is
  835. /// thrown.
  836. /// </para>
  837. ///
  838. /// <para>
  839. /// When a <c>ZipEntry</c> is contained within a <c>ZipFile</c>, applications
  840. /// cannot rename the entry within the context of a <c>foreach</c> (<c>For
  841. /// Each</c> in VB) loop, because of the way the <c>ZipFile</c> stores
  842. /// entries. If you need to enumerate through all the entries and rename one
  843. /// or more of them, use <see
  844. /// cref="ZipFile.EntriesSorted">ZipFile.EntriesSorted</see> as the
  845. /// collection. See also, <see
  846. /// cref="ZipFile.GetEnumerator()">ZipFile.GetEnumerator()</see>.
  847. /// </para>
  848. ///
  849. /// </remarks>
  850. public string FileName
  851. {
  852. get { return _FileNameInArchive; }
  853. set
  854. {
  855. if (_container.ZipFile == null)
  856. throw new ZipException("Cannot rename; this is not supported in ZipOutputStream/ZipInputStream.");
  857. // rename the entry!
  858. if (String.IsNullOrEmpty(value)) throw new ZipException("The FileName must be non empty and non-null.");
  859. var filename = ZipEntry.NameInArchive(value, null);
  860. // workitem 8180
  861. if (_FileNameInArchive == filename) return; // nothing to do
  862. // workitem 8047 - when renaming, must remove old and then add a new entry
  863. this._container.ZipFile.RemoveEntry(this);
  864. this._container.ZipFile.InternalAddEntry(filename, this);
  865. _FileNameInArchive = filename;
  866. _container.ZipFile.NotifyEntryChanged();
  867. _metadataChanged = true;
  868. }
  869. }
  870. /// <summary>
  871. /// The stream that provides content for the ZipEntry.
  872. /// </summary>
  873. ///
  874. /// <remarks>
  875. ///
  876. /// <para>
  877. /// The application can use this property to set the input stream for an
  878. /// entry on a just-in-time basis. Imagine a scenario where the application
  879. /// creates a <c>ZipFile</c> comprised of content obtained from hundreds of
  880. /// files, via calls to <c>AddFile()</c>. The DotNetZip library opens streams
  881. /// on these files on a just-in-time basis, only when writing the entry out to
  882. /// an external store within the scope of a <c>ZipFile.Save()</c> call. Only
  883. /// one input stream is opened at a time, as each entry is being written out.
  884. /// </para>
  885. ///
  886. /// <para>
  887. /// Now imagine a different application that creates a <c>ZipFile</c>
  888. /// with content obtained from hundreds of streams, added through <see
  889. /// cref="ZipFile.AddEntry(string, System.IO.Stream)"/>. Normally the
  890. /// application would supply an open stream to that call. But when large
  891. /// numbers of streams are being added, this can mean many open streams at one
  892. /// time, unnecessarily.
  893. /// </para>
  894. ///
  895. /// <para>
  896. /// To avoid this, call <see cref="ZipFile.AddEntry(String, OpenDelegate,
  897. /// CloseDelegate)"/> and specify delegates that open and close the stream at
  898. /// the time of Save.
  899. /// </para>
  900. ///
  901. ///
  902. /// <para>
  903. /// Setting the value of this property when the entry was not added from a
  904. /// stream (for example, when the <c>ZipEntry</c> was added with <see
  905. /// cref="ZipFile.AddFile(String)"/> or <see
  906. /// cref="ZipFile.AddDirectory(String)"/>, or when the entry was added by
  907. /// reading an existing zip archive) will throw an exception.
  908. /// </para>
  909. ///
  910. /// </remarks>
  911. ///
  912. public Stream InputStream
  913. {
  914. get { return _sourceStream; }
  915. set
  916. {
  917. if (this._Source != ZipEntrySource.Stream)
  918. throw new ZipException("You must not set the input stream for this entry.");
  919. _sourceWasJitProvided = true;
  920. _sourceStream = value;
  921. }
  922. }
  923. /// <summary>
  924. /// A flag indicating whether the InputStream was provided Just-in-time.
  925. /// </summary>
  926. ///
  927. /// <remarks>
  928. ///
  929. /// <para>
  930. /// When creating a zip archive, an application can obtain content for one or
  931. /// more of the <c>ZipEntry</c> instances from streams, using the <see
  932. /// cref="ZipFile.AddEntry(string, System.IO.Stream)"/> method. At the time
  933. /// of calling that method, the application can supply null as the value of
  934. /// the stream parameter. By doing so, the application indicates to the
  935. /// library that it will provide a stream for the entry on a just-in-time
  936. /// basis, at the time one of the <c>ZipFile.Save()</c> methods is called and
  937. /// the data for the various entries are being compressed and written out.
  938. /// </para>
  939. ///
  940. /// <para>
  941. /// In this case, the application can set the <see cref="InputStream"/>
  942. /// property, typically within the SaveProgress event (event type: <see
  943. /// cref="ZipProgressEventType.Saving_BeforeWriteEntry"/>) for that entry.
  944. /// </para>
  945. ///
  946. /// <para>
  947. /// The application will later want to call Close() and Dispose() on that
  948. /// stream. In the SaveProgress event, when the event type is <see
  949. /// cref="ZipProgressEventType.Saving_AfterWriteEntry"/>, the application can
  950. /// do so. This flag indicates that the stream has been provided by the
  951. /// application on a just-in-time basis and that it is the application's
  952. /// responsibility to call Close/Dispose on that stream.
  953. /// </para>
  954. ///
  955. /// </remarks>
  956. /// <seealso cref="InputStream"/>
  957. public bool InputStreamWasJitProvided
  958. {
  959. get { return _sourceWasJitProvided; }
  960. }
  961. /// <summary>
  962. /// An enum indicating the source of the ZipEntry.
  963. /// </summary>
  964. public ZipEntrySource Source
  965. {
  966. get { return _Source; }
  967. }
  968. /// <summary>
  969. /// The version of the zip engine needed to read the ZipEntry.
  970. /// </summary>
  971. ///
  972. /// <remarks>
  973. /// <para>
  974. /// This is a readonly property, indicating the version of <a
  975. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
  976. /// specification</a> that the extracting tool or library must support to
  977. /// extract the given entry. Generally higher versions indicate newer
  978. /// features. Older zip engines obviously won't know about new features, and
  979. /// won't be able to extract entries that depend on those newer features.
  980. /// </para>
  981. ///
  982. /// <list type="table">
  983. /// <listheader>
  984. /// <term>value</term>
  985. /// <description>Features</description>
  986. /// </listheader>
  987. ///
  988. /// <item>
  989. /// <term>20</term>
  990. /// <description>a basic Zip Entry, potentially using PKZIP encryption.
  991. /// </description>
  992. /// </item>
  993. ///
  994. /// <item>
  995. /// <term>45</term>
  996. /// <description>The ZIP64 extension is used on the entry.
  997. /// </description>
  998. /// </item>
  999. ///
  1000. /// <item>
  1001. /// <term>46</term>
  1002. /// <description> File is compressed using BZIP2 compression*</description>
  1003. /// </item>
  1004. ///
  1005. /// <item>
  1006. /// <term>50</term>
  1007. /// <description> File is encrypted using PkWare's DES, 3DES, (broken) RC2 or RC4</description>
  1008. /// </item>
  1009. ///
  1010. /// <item>
  1011. /// <term>51</term>
  1012. /// <description> File is encrypted using PKWare's AES encryption or corrected RC2 encryption.</description>
  1013. /// </item>
  1014. ///
  1015. /// <item>
  1016. /// <term>52</term>
  1017. /// <description> File is encrypted using corrected RC2-64 encryption**</description>
  1018. /// </item>
  1019. ///
  1020. /// <item>
  1021. /// <term>61</term>
  1022. /// <description> File is encrypted using non-OAEP key wrapping***</description>
  1023. /// </item>
  1024. ///
  1025. /// <item>
  1026. /// <term>63</term>
  1027. /// <description> File is compressed using LZMA, PPMd+, Blowfish, or Twofish</description>
  1028. /// </item>
  1029. ///
  1030. /// </list>
  1031. ///
  1032. /// <para>
  1033. /// There are other values possible, not listed here. DotNetZip supports
  1034. /// regular PKZip encryption, and ZIP64 extensions. DotNetZip cannot extract
  1035. /// entries that require a zip engine higher than 45.
  1036. /// </para>
  1037. ///
  1038. /// <para>
  1039. /// This value is set upon reading an existing zip file, or after saving a zip
  1040. /// archive.
  1041. /// </para>
  1042. /// </remarks>
  1043. public Int16 VersionNeeded
  1044. {
  1045. get { return _VersionNeeded; }
  1046. }
  1047. /// <summary>
  1048. /// The comment attached to the ZipEntry.
  1049. /// </summary>
  1050. ///
  1051. /// <remarks>
  1052. /// <para>
  1053. /// Each entry in a zip file can optionally have a comment associated to
  1054. /// it. The comment might be displayed by a zip tool during extraction, for
  1055. /// example.
  1056. /// </para>
  1057. ///
  1058. /// <para>
  1059. /// By default, the <c>Comment</c> is encoded in IBM437 code page. You can
  1060. /// specify an alternative with <see cref="AlternateEncoding"/> and
  1061. /// <see cref="AlternateEncodingUsage"/>.
  1062. /// </para>
  1063. /// </remarks>
  1064. /// <seealso cref="AlternateEncoding"/>
  1065. /// <seealso cref="AlternateEncodingUsage"/>
  1066. public string Comment
  1067. {
  1068. get { return _Comment; }
  1069. set
  1070. {
  1071. _Comment = value;
  1072. _metadataChanged = true;
  1073. }
  1074. }
  1075. /// <summary>
  1076. /// Indicates whether the entry requires ZIP64 extensions.
  1077. /// </summary>
  1078. ///
  1079. /// <remarks>
  1080. ///
  1081. /// <para>
  1082. /// This property is null (Nothing in VB) until a <c>Save()</c> method on the
  1083. /// containing <see cref="ZipFile"/> instance has been called. The property is
  1084. /// non-null (<c>HasValue</c> is true) only after a <c>Save()</c> method has
  1085. /// been called.
  1086. /// </para>
  1087. ///
  1088. /// <para>
  1089. /// After the containing <c>ZipFile</c> has been saved, the Value of this
  1090. /// property is true if any of the following three conditions holds: the
  1091. /// uncompressed size of the entry is larger than 0xFFFFFFFF; the compressed
  1092. /// size of the entry is larger than 0xFFFFFFFF; the relative offset of the
  1093. /// entry within the zip archive is larger than 0xFFFFFFFF. These quantities
  1094. /// are not known until a <c>Save()</c> is attempted on the zip archive and
  1095. /// the compression is applied.
  1096. /// </para>
  1097. ///
  1098. /// <para>
  1099. /// If none of the three conditions holds, then the <c>Value</c> is false.
  1100. /// </para>
  1101. ///
  1102. /// <para>
  1103. /// A <c>Value</c> of false does not indicate that the entry, as saved in the
  1104. /// zip archive, does not use ZIP64. It merely indicates that ZIP64 is
  1105. /// <em>not required</em>. An entry may use ZIP64 even when not required if
  1106. /// the <see cref="ZipFile.UseZip64WhenSaving"/> property on the containing
  1107. /// <c>ZipFile</c> instance is set to <see cref="Zip64Option.Always"/>, or if
  1108. /// the <see cref="ZipFile.UseZip64WhenSaving"/> property on the containing
  1109. /// <c>ZipFile</c> instance is set to <see cref="Zip64Option.AsNecessary"/>
  1110. /// and the output stream was not seekable.
  1111. /// </para>
  1112. ///
  1113. /// </remarks>
  1114. /// <seealso cref="OutputUsedZip64"/>
  1115. public Nullable<bool> RequiresZip64
  1116. {
  1117. get
  1118. {
  1119. return _entryRequiresZip64;
  1120. }
  1121. }
  1122. /// <summary>
  1123. /// Indicates whether the entry actually used ZIP64 extensions, as it was most
  1124. /// recently written to the output file or stream.
  1125. /// </summary>
  1126. ///
  1127. /// <remarks>
  1128. ///
  1129. /// <para>
  1130. /// This Nullable property is null (Nothing in VB) until a <c>Save()</c>
  1131. /// method on the containing <see cref="ZipFile"/> instance has been
  1132. /// called. <c>HasValue</c> is true only after a <c>Save()</c> method has been
  1133. /// called.
  1134. /// </para>
  1135. ///
  1136. /// <para>
  1137. /// The value of this property for a particular <c>ZipEntry</c> may change
  1138. /// over successive calls to <c>Save()</c> methods on the containing ZipFile,
  1139. /// even if the file that corresponds to the <c>ZipEntry</c> does not. This
  1140. /// may happen if other entries contained in the <c>ZipFile</c> expand,
  1141. /// causing the offset for this particular entry to exceed 0xFFFFFFFF.
  1142. /// </para>
  1143. /// </remarks>
  1144. /// <seealso cref="RequiresZip64"/>
  1145. public Nullable<bool> OutputUsedZip64
  1146. {
  1147. get { return _OutputUsesZip64; }
  1148. }
  1149. /// <summary>
  1150. /// The bitfield for the entry as defined in the zip spec. You probably
  1151. /// never need to look at this.
  1152. /// </summary>
  1153. ///
  1154. /// <remarks>
  1155. /// <para>
  1156. /// You probably do not need to concern yourself with the contents of this
  1157. /// property, but in case you do:
  1158. /// </para>
  1159. ///
  1160. /// <list type="table">
  1161. /// <listheader>
  1162. /// <term>bit</term>
  1163. /// <description>meaning</description>
  1164. /// </listheader>
  1165. ///
  1166. /// <item>
  1167. /// <term>0</term>
  1168. /// <description>set if encryption is used.</description>
  1169. /// </item>
  1170. ///
  1171. /// <item>
  1172. /// <term>1-2</term>
  1173. /// <description>
  1174. /// set to determine whether normal, max, fast deflation. DotNetZip library
  1175. /// always leaves these bits unset when writing (indicating "normal"
  1176. /// deflation"), but can read an entry with any value here.
  1177. /// </description>
  1178. /// </item>
  1179. ///
  1180. /// <item>
  1181. /// <term>3</term>
  1182. /// <description>
  1183. /// Indicates that the Crc32, Compressed and Uncompressed sizes are zero in the
  1184. /// local header. This bit gets set on an entry during writing a zip file, when
  1185. /// it is saved to a non-seekable output stream.
  1186. /// </description>
  1187. /// </item>
  1188. ///
  1189. ///
  1190. /// <item>
  1191. /// <term>4</term>
  1192. /// <description>reserved for "enhanced deflating". This library doesn't do enhanced deflating.</description>
  1193. /// </item>
  1194. ///
  1195. /// <item>
  1196. /// <term>5</term>
  1197. /// <description>set to indicate the zip is compressed patched data. This library doesn't do that.</description>
  1198. /// </item>
  1199. ///
  1200. /// <item>
  1201. /// <term>6</term>
  1202. /// <description>
  1203. /// set if PKWare's strong encryption is used (must also set bit 1 if bit 6 is
  1204. /// set). This bit is not set if WinZip's AES encryption is set.</description>
  1205. /// </item>
  1206. ///
  1207. /// <item>
  1208. /// <term>7</term>
  1209. /// <description>not used</description>
  1210. /// </item>
  1211. ///
  1212. /// <item>
  1213. /// <term>8</term>
  1214. /// <description>not used</description>
  1215. /// </item>
  1216. ///
  1217. /// <item>
  1218. /// <term>9</term>
  1219. /// <description>not used</description>
  1220. /// </item>
  1221. ///
  1222. /// <item>
  1223. /// <term>10</term>
  1224. /// <description>not used</description>
  1225. /// </item>
  1226. ///
  1227. /// <item>
  1228. /// <term>11</term>
  1229. /// <description>
  1230. /// Language encoding flag (EFS). If this bit is set, the filename and comment
  1231. /// fields for this file must be encoded using UTF-8. This library currently
  1232. /// does not support UTF-8.
  1233. /// </description>
  1234. /// </item>
  1235. ///
  1236. /// <item>
  1237. /// <term>12</term>
  1238. /// <description>Reserved by PKWARE for enhanced compression.</description>
  1239. /// </item>
  1240. ///
  1241. /// <item>
  1242. /// <term>13</term>
  1243. /// <description>
  1244. /// Used when encrypting the Central Directory to indicate selected data
  1245. /// values in the Local Header are masked to hide their actual values. See
  1246. /// the section in <a
  1247. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
  1248. /// specification</a> describing the Strong Encryption Specification for
  1249. /// details.
  1250. /// </description>
  1251. /// </item>
  1252. ///
  1253. /// <item>
  1254. /// <term>14</term>
  1255. /// <description>Reserved by PKWARE.</description>
  1256. /// </item>
  1257. ///
  1258. /// <item>
  1259. /// <term>15</term>
  1260. /// <description>Reserved by PKWARE.</description>
  1261. /// </item>
  1262. ///
  1263. /// </list>
  1264. ///
  1265. /// </remarks>
  1266. public Int16 BitField
  1267. {
  1268. get { return _BitField; }
  1269. }
  1270. /// <summary>
  1271. /// The compression method employed for this ZipEntry.
  1272. /// </summary>
  1273. ///
  1274. /// <remarks>
  1275. ///
  1276. /// <para>
  1277. /// <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">The
  1278. /// Zip specification</see> allows a variety of compression methods. This
  1279. /// library supports just two: 0x08 = Deflate. 0x00 = Store (no compression),
  1280. /// for reading or writing.
  1281. /// </para>
  1282. ///
  1283. /// <para>
  1284. /// When reading an entry from an existing zipfile, the value you retrieve
  1285. /// here indicates the compression method used on the entry by the original
  1286. /// creator of the zip. When writing a zipfile, you can specify either 0x08
  1287. /// (Deflate) or 0x00 (None). If you try setting something else, you will get
  1288. /// an exception.
  1289. /// </para>
  1290. ///
  1291. /// <para>
  1292. /// You may wish to set <c>CompressionMethod</c> to <c>CompressionMethod.None</c> (0)
  1293. /// when zipping already-compressed data like a jpg, png, or mp3 file.
  1294. /// This can save time and cpu cycles.
  1295. /// </para>
  1296. ///
  1297. /// <para>
  1298. /// When setting this property on a <c>ZipEntry</c> that is read from an
  1299. /// existing zip file, calling <c>ZipFile.Save()</c> will cause the new
  1300. /// CompressionMethod to be used on the entry in the newly saved zip file.
  1301. /// </para>
  1302. ///
  1303. /// <para>
  1304. /// Setting this property may have the side effect of modifying the
  1305. /// <c>CompressionLevel</c> property. If you set the <c>CompressionMethod</c> to a
  1306. /// value other than <c>None</c>, and <c>CompressionLevel</c> is previously
  1307. /// set to <c>None</c>, then <c>CompressionLevel</c> will be set to
  1308. /// <c>Default</c>.
  1309. /// </para>
  1310. /// </remarks>
  1311. ///
  1312. /// <seealso cref="CompressionMethod"/>
  1313. ///
  1314. /// <example>
  1315. /// In this example, the first entry added to the zip archive uses the default
  1316. /// behavior - compression is used where it makes sense. The second entry,
  1317. /// the MP3 file, is added to the archive without being compressed.
  1318. /// <code>
  1319. /// using (ZipFile zip = new ZipFile(ZipFileToCreate))
  1320. /// {
  1321. /// ZipEntry e1= zip.AddFile(@"notes\Readme.txt");
  1322. /// ZipEntry e2= zip.AddFile(@"music\StopThisTrain.mp3");
  1323. /// e2.CompressionMethod = CompressionMethod.None;
  1324. /// zip.Save();
  1325. /// }
  1326. /// </code>
  1327. ///
  1328. /// <code lang="VB">
  1329. /// Using zip As New ZipFile(ZipFileToCreate)
  1330. /// zip.AddFile("notes\Readme.txt")
  1331. /// Dim e2 as ZipEntry = zip.AddFile("music\StopThisTrain.mp3")
  1332. /// e2.CompressionMethod = CompressionMethod.None
  1333. /// zip.Save
  1334. /// End Using
  1335. /// </code>
  1336. /// </example>
  1337. public CompressionMethod CompressionMethod
  1338. {
  1339. get { return (CompressionMethod)_CompressionMethod; }
  1340. set
  1341. {
  1342. if (value == (CompressionMethod)_CompressionMethod) return; // nothing to do.
  1343. if (value != CompressionMethod.None && value != CompressionMethod.Deflate
  1344. #if BZIP
  1345. && value != CompressionMethod.BZip2
  1346. #endif
  1347. )
  1348. throw new InvalidOperationException("Unsupported compression method.");
  1349. // If the source is a zip archive and there was encryption on the
  1350. // entry, changing the compression method is not supported.
  1351. // if (this._Source == ZipEntrySource.ZipFile && _sourceIsEncrypted)
  1352. // throw new InvalidOperationException("Cannot change compression method on encrypted entries read from archives.");
  1353. _CompressionMethod = (Int16)value;
  1354. if (_CompressionMethod == (Int16)Ionic.Zip.CompressionMethod.None)
  1355. _CompressionLevel = Ionic.Zlib.CompressionLevel.None;
  1356. else if (CompressionLevel == Ionic.Zlib.CompressionLevel.None)
  1357. _CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
  1358. if (_container.ZipFile != null) _container.ZipFile.NotifyEntryChanged();
  1359. _restreamRequiredOnSave = true;
  1360. }
  1361. }
  1362. /// <summary>
  1363. /// Sets the compression level to be used for the entry when saving the zip
  1364. /// archive. This applies only for CompressionMethod = DEFLATE.
  1365. /// </summary>
  1366. ///
  1367. /// <remarks>
  1368. /// <para>
  1369. /// When using the DEFLATE compression method, Varying the compression
  1370. /// level used on entries can affect the size-vs-speed tradeoff when
  1371. /// compression and decompressing data streams or files.
  1372. /// </para>
  1373. ///
  1374. /// <para>
  1375. /// If you do not set this property, the default compression level is used,
  1376. /// which normally gives a good balance of compression efficiency and
  1377. /// compression speed. In some tests, using <c>BestCompression</c> can
  1378. /// double the time it takes to compress, while delivering just a small
  1379. /// increase in compression efficiency. This behavior will vary with the
  1380. /// type of data you compress. If you are in doubt, just leave this setting
  1381. /// alone, and accept the default.
  1382. /// </para>
  1383. ///
  1384. /// <para>
  1385. /// When setting this property on a <c>ZipEntry</c> that is read from an
  1386. /// existing zip file, calling <c>ZipFile.Save()</c> will cause the new
  1387. /// <c>CompressionLevel</c> to be used on the entry in the newly saved zip file.
  1388. /// </para>
  1389. ///
  1390. /// <para>
  1391. /// Setting this property may have the side effect of modifying the
  1392. /// <c>CompressionMethod</c> property. If you set the <c>CompressionLevel</c>
  1393. /// to a value other than <c>None</c>, <c>CompressionMethod</c> will be set
  1394. /// to <c>Deflate</c>, if it was previously <c>None</c>.
  1395. /// </para>
  1396. ///
  1397. /// <para>
  1398. /// Setting this property has no effect if the <c>CompressionMethod</c> is something
  1399. /// other than <c>Deflate</c> or <c>None</c>.
  1400. /// </para>
  1401. /// </remarks>
  1402. ///
  1403. /// <seealso cref="CompressionMethod"/>
  1404. public Ionic.Zlib.CompressionLevel CompressionLevel
  1405. {
  1406. get
  1407. {
  1408. return _CompressionLevel;
  1409. }
  1410. set
  1411. {
  1412. if (_CompressionMethod != (short)CompressionMethod.Deflate &&
  1413. _CompressionMethod != (short)CompressionMethod.None)
  1414. return ; // no effect
  1415. if (value == Ionic.Zlib.CompressionLevel.Default &&
  1416. _CompressionMethod == (short)CompressionMethod.Deflate) return; // nothing to do
  1417. _CompressionLevel = value;
  1418. if (value == Ionic.Zlib.CompressionLevel.None &&
  1419. _CompressionMethod == (short)CompressionMethod.None)
  1420. return; // nothing more to do
  1421. if (_CompressionLevel == Ionic.Zlib.CompressionLevel.None)
  1422. _CompressionMethod = (short) Ionic.Zip.CompressionMethod.None;
  1423. else
  1424. _CompressionMethod = (short) Ionic.Zip.CompressionMethod.Deflate;
  1425. if (_container.ZipFile != null) _container.ZipFile.NotifyEntryChanged();
  1426. _restreamRequiredOnSave = true;
  1427. }
  1428. }
  1429. /// <summary>
  1430. /// The compressed size of the file, in bytes, within the zip archive.
  1431. /// </summary>
  1432. ///
  1433. /// <remarks>
  1434. /// When reading a <c>ZipFile</c>, this value is read in from the existing
  1435. /// zip file. When creating or updating a <c>ZipFile</c>, the compressed
  1436. /// size is computed during compression. Therefore the value on a
  1437. /// <c>ZipEntry</c> is valid after a call to <c>Save()</c> (or one of its
  1438. /// overloads) in that case.
  1439. /// </remarks>
  1440. ///
  1441. /// <seealso cref="Ionic.Zip.ZipEntry.UncompressedSize"/>
  1442. public Int64 CompressedSize
  1443. {
  1444. get { return _CompressedSize; }
  1445. }
  1446. /// <summary>
  1447. /// The size of the file, in bytes, before compression, or after extraction.
  1448. /// </summary>
  1449. ///
  1450. /// <remarks>
  1451. /// When reading a <c>ZipFile</c>, this value is read in from the existing
  1452. /// zip file. When creating or updating a <c>ZipFile</c>, the uncompressed
  1453. /// size is computed during compression. Therefore the value on a
  1454. /// <c>ZipEntry</c> is valid after a call to <c>Save()</c> (or one of its
  1455. /// overloads) in that case.
  1456. /// </remarks>
  1457. ///
  1458. /// <seealso cref="Ionic.Zip.ZipEntry.CompressedSize"/>
  1459. public Int64 UncompressedSize
  1460. {
  1461. get { return _UncompressedSize; }
  1462. }
  1463. /// <summary>
  1464. /// The ratio of compressed size to uncompressed size of the ZipEntry.
  1465. /// </summary>
  1466. ///
  1467. /// <remarks>
  1468. /// <para>
  1469. /// This is a ratio of the compressed size to the uncompressed size of the
  1470. /// entry, expressed as a double in the range of 0 to 100+. A value of 100
  1471. /// indicates no compression at all. It could be higher than 100 when the
  1472. /// compression algorithm actually inflates the data, as may occur for small
  1473. /// files, or uncompressible data that is encrypted.
  1474. /// </para>
  1475. ///
  1476. /// <para>
  1477. /// You could format it for presentation to a user via a format string of
  1478. /// "{3,5:F0}%" to see it as a percentage.
  1479. /// </para>
  1480. ///
  1481. /// <para>
  1482. /// If the size of the original uncompressed file is 0, implying a
  1483. /// denominator of 0, the return value will be zero.
  1484. /// </para>
  1485. ///
  1486. /// <para>
  1487. /// This property is valid after reading in an existing zip file, or after
  1488. /// saving the <c>ZipFile</c> that contains the ZipEntry. You cannot know the
  1489. /// effect of a compression transform until you try it.
  1490. /// </para>
  1491. ///
  1492. /// </remarks>
  1493. public Double CompressionRatio
  1494. {
  1495. get
  1496. {
  1497. if (UncompressedSize == 0) return 0;
  1498. return 100 * (1.0 - (1.0 * CompressedSize) / (1.0 * UncompressedSize));
  1499. }
  1500. }
  1501. /// <summary>
  1502. /// The 32-bit CRC (Cyclic Redundancy Check) on the contents of the ZipEntry.
  1503. /// </summary>
  1504. ///
  1505. /// <remarks>
  1506. ///
  1507. /// <para> You probably don't need to concern yourself with this. It is used
  1508. /// internally by DotNetZip to verify files or streams upon extraction. </para>
  1509. ///
  1510. /// <para> The value is a <see href="http://en.wikipedia.org/wiki/CRC32">32-bit
  1511. /// CRC</see> using 0xEDB88320 for the polynomial. This is the same CRC-32 used in
  1512. /// PNG, MPEG-2, and other protocols and formats. It is a read-only property; when
  1513. /// creating a Zip archive, the CRC for each entry is set only after a call to
  1514. /// <c>Save()</c> on the containing ZipFile. When reading an existing zip file, the value
  1515. /// of this property reflects the stored CRC for the entry. </para>
  1516. ///
  1517. /// </remarks>
  1518. public Int32 Crc
  1519. {
  1520. get { return _Crc32; }
  1521. }
  1522. /// <summary>
  1523. /// True if the entry is a directory (not a file).
  1524. /// This is a readonly property on the entry.
  1525. /// </summary>
  1526. public bool IsDirectory
  1527. {
  1528. get { return _IsDirectory; }
  1529. }
  1530. /// <summary>
  1531. /// A derived property that is <c>true</c> if the entry uses encryption.
  1532. /// </summary>
  1533. ///
  1534. /// <remarks>
  1535. /// <para>
  1536. /// This is a readonly property on the entry. When reading a zip file,
  1537. /// the value for the <c>ZipEntry</c> is determined by the data read
  1538. /// from the zip file. After saving a ZipFile, the value of this
  1539. /// property for each <c>ZipEntry</c> indicates whether encryption was
  1540. /// actually used (which will have been true if the <see
  1541. /// cref="Password"/> was set and the <see cref="Encryption"/> property
  1542. /// was something other than <see cref="EncryptionAlgorithm.None"/>.
  1543. /// </para>
  1544. /// </remarks>
  1545. public bool UsesEncryption
  1546. {
  1547. get { return (_Encryption_FromZipFile != EncryptionAlgorithm.None); }
  1548. }
  1549. /// <summary>
  1550. /// Set this to specify which encryption algorithm to use for the entry when
  1551. /// saving it to a zip archive.
  1552. /// </summary>
  1553. ///
  1554. /// <remarks>
  1555. ///
  1556. /// <para>
  1557. /// Set this property in order to encrypt the entry when the <c>ZipFile</c> is
  1558. /// saved. When setting this property, you must also set a <see
  1559. /// cref="Password"/> on the entry. If you set a value other than <see
  1560. /// cref="EncryptionAlgorithm.None"/> on this property and do not set a
  1561. /// <c>Password</c> then the entry will not be encrypted. The <c>ZipEntry</c>
  1562. /// data is encrypted as the <c>ZipFile</c> is saved, when you call <see
  1563. /// cref="ZipFile.Save()"/> or one of its cousins on the containing
  1564. /// <c>ZipFile</c> instance. You do not need to specify the <c>Encryption</c>
  1565. /// when extracting entries from an archive.
  1566. /// </para>
  1567. ///
  1568. /// <para>
  1569. /// The Zip specification from PKWare defines a set of encryption algorithms,
  1570. /// and the data formats for the zip archive that support them, and PKWare
  1571. /// supports those algorithms in the tools it produces. Other vendors of tools
  1572. /// and libraries, such as WinZip or Xceed, typically support <em>a
  1573. /// subset</em> of the algorithms specified by PKWare. These tools can
  1574. /// sometimes support additional different encryption algorithms and data
  1575. /// formats, not specified by PKWare. The AES Encryption specified and
  1576. /// supported by WinZip is the most popular example. This library supports a
  1577. /// subset of the complete set of algorithms specified by PKWare and other
  1578. /// vendors.
  1579. /// </para>
  1580. ///
  1581. /// <para>
  1582. /// There is no common, ubiquitous multi-vendor standard for strong encryption
  1583. /// within zip files. There is broad support for so-called "traditional" Zip
  1584. /// encryption, sometimes called Zip 2.0 encryption, as <see
  1585. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">specified
  1586. /// by PKWare</see>, but this encryption is considered weak and
  1587. /// breakable. This library currently supports the Zip 2.0 "weak" encryption,
  1588. /// and also a stronger WinZip-compatible AES encryption, using either 128-bit
  1589. /// or 256-bit key strength. If you want DotNetZip to support an algorithm
  1590. /// that is not currently supported, call the author of this library and maybe
  1591. /// we can talk business.
  1592. /// </para>
  1593. ///
  1594. /// <para>
  1595. /// The <see cref="ZipFile"/> class also has a <see
  1596. /// cref="ZipFile.Encryption"/> property. In most cases you will use
  1597. /// <em>that</em> property when setting encryption. This property takes
  1598. /// precedence over any <c>Encryption</c> set on the <c>ZipFile</c> itself.
  1599. /// Typically, you would use the per-entry Encryption when most entries in the
  1600. /// zip archive use one encryption algorithm, and a few entries use a
  1601. /// different one. If all entries in the zip file use the same Encryption,
  1602. /// then it is simpler to just set this property on the ZipFile itself, when
  1603. /// creating a zip archive.
  1604. /// </para>
  1605. ///
  1606. /// <para>
  1607. /// Some comments on updating archives: If you read a <c>ZipFile</c>, you can
  1608. /// modify the Encryption on an encrypted entry: you can remove encryption
  1609. /// from an entry that was encrypted; you can encrypt an entry that was not
  1610. /// encrypted previously; or, you can change the encryption algorithm. The
  1611. /// changes in encryption are not made permanent until you call Save() on the
  1612. /// <c>ZipFile</c>. To effect changes in encryption, the entry content is
  1613. /// streamed through several transformations, depending on the modification
  1614. /// the application has requested. For example if the entry is not encrypted
  1615. /// and the application sets <c>Encryption</c> to <c>PkzipWeak</c>, then at
  1616. /// the time of <c>Save()</c>, the original entry is read and decompressed,
  1617. /// then re-compressed and encrypted. Conversely, if the original entry is
  1618. /// encrypted with <c>PkzipWeak</c> encryption, and the application sets the
  1619. /// <c>Encryption</c> property to <c>WinZipAes128</c>, then at the time of
  1620. /// <c>Save()</c>, the original entry is decrypted via PKZIP encryption and
  1621. /// decompressed, then re-compressed and re-encrypted with AES. This all
  1622. /// happens automatically within the library, but it can be time-consuming for
  1623. /// large entries.
  1624. /// </para>
  1625. ///
  1626. /// <para>
  1627. /// Additionally, when updating archives, it is not possible to change the
  1628. /// password when changing the encryption algorithm. To change both the
  1629. /// algorithm and the password, you need to Save() the zipfile twice. First
  1630. /// set the <c>Encryption</c> to None, then call <c>Save()</c>. Then set the
  1631. /// <c>Encryption</c> to the new value (not "None"), then call <c>Save()</c>
  1632. /// once again.
  1633. /// </para>
  1634. ///
  1635. /// <para>
  1636. /// The WinZip AES encryption algorithms are not supported on the .NET Compact
  1637. /// Framework.
  1638. /// </para>
  1639. /// </remarks>
  1640. ///
  1641. /// <example>
  1642. /// <para>
  1643. /// This example creates a zip archive that uses encryption, and then extracts
  1644. /// entries from the archive. When creating the zip archive, the ReadMe.txt
  1645. /// file is zipped without using a password or encryption. The other file
  1646. /// uses encryption.
  1647. /// </para>
  1648. /// <code>
  1649. /// // Create a zip archive with AES Encryption.
  1650. /// using (ZipFile zip = new ZipFile())
  1651. /// {
  1652. /// zip.AddFile("ReadMe.txt")
  1653. /// ZipEntry e1= zip.AddFile("2008-Regional-Sales-Report.pdf");
  1654. /// e1.Encryption= EncryptionAlgorithm.WinZipAes256;
  1655. /// e1.Password= "Top.Secret.No.Peeking!";
  1656. /// zip.Save("EncryptedArchive.zip");
  1657. /// }
  1658. ///
  1659. /// // Extract a zip archive that uses AES Encryption.
  1660. /// // You do not need to specify the algorithm during extraction.
  1661. /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
  1662. /// {
  1663. /// // Specify the password that is used during extraction, for
  1664. /// // all entries that require a password:
  1665. /// zip.Password= "Top.Secret.No.Peeking!";
  1666. /// zip.ExtractAll("extractDirectory");
  1667. /// }
  1668. /// </code>
  1669. ///
  1670. /// <code lang="VB">
  1671. /// ' Create a zip that uses Encryption.
  1672. /// Using zip As New ZipFile()
  1673. /// zip.AddFile("ReadMe.txt")
  1674. /// Dim e1 as ZipEntry
  1675. /// e1= zip.AddFile("2008-Regional-Sales-Report.pdf")
  1676. /// e1.Encryption= EncryptionAlgorithm.WinZipAes256
  1677. /// e1.Password= "Top.Secret.No.Peeking!"
  1678. /// zip.Save("EncryptedArchive.zip")
  1679. /// End Using
  1680. ///
  1681. /// ' Extract a zip archive that uses AES Encryption.
  1682. /// ' You do not need to specify the algorithm during extraction.
  1683. /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
  1684. /// ' Specify the password that is used during extraction, for
  1685. /// ' all entries that require a password:
  1686. /// zip.Password= "Top.Secret.No.Peeking!"
  1687. /// zip.ExtractAll("extractDirectory")
  1688. /// End Using
  1689. /// </code>
  1690. ///
  1691. /// </example>
  1692. ///
  1693. /// <exception cref="System.InvalidOperationException">
  1694. /// Thrown in the setter if EncryptionAlgorithm.Unsupported is specified.
  1695. /// </exception>
  1696. ///
  1697. /// <seealso cref="Ionic.Zip.ZipEntry.Password">ZipEntry.Password</seealso>
  1698. /// <seealso cref="Ionic.Zip.ZipFile.Encryption">ZipFile.Encryption</seealso>
  1699. public EncryptionAlgorithm Encryption
  1700. {
  1701. get
  1702. {
  1703. return _Encryption;
  1704. }
  1705. set
  1706. {
  1707. if (value == _Encryption) return; // no change
  1708. if (value == EncryptionAlgorithm.Unsupported)
  1709. throw new InvalidOperationException("You may not set Encryption to that value.");
  1710. // If the source is a zip archive and there was encryption
  1711. // on the entry, this will not work. <XXX>
  1712. //if (this._Source == ZipEntrySource.ZipFile && _sourceIsEncrypted)
  1713. // throw new InvalidOperationException("You cannot change the encryption method on encrypted entries read from archives.");
  1714. _Encryption = value;
  1715. _restreamRequiredOnSave = true;
  1716. if (_container.ZipFile!=null)
  1717. _container.ZipFile.NotifyEntryChanged();
  1718. }
  1719. }
  1720. /// <summary>
  1721. /// The Password to be used when encrypting a <c>ZipEntry</c> upon
  1722. /// <c>ZipFile.Save()</c>, or when decrypting an entry upon Extract().
  1723. /// </summary>
  1724. ///
  1725. /// <remarks>
  1726. /// <para>
  1727. /// This is a write-only property on the entry. Set this to request that the
  1728. /// entry be encrypted when writing the zip archive, or set it to specify the
  1729. /// password to be used when extracting an existing entry that is encrypted.
  1730. /// </para>
  1731. ///
  1732. /// <para>
  1733. /// The password set here is implicitly used to encrypt the entry during the
  1734. /// <see cref="ZipFile.Save()"/> operation, or to decrypt during the <see
  1735. /// cref="Extract()"/> or <see cref="OpenReader()"/> operation. If you set
  1736. /// the Password on a <c>ZipEntry</c> after calling <c>Save()</c>, there is no
  1737. /// effect.
  1738. /// </para>
  1739. ///
  1740. /// <para>
  1741. /// Consider setting the <see cref="Encryption"/> property when using a
  1742. /// password. Answering concerns that the standard password protection
  1743. /// supported by all zip tools is weak, WinZip has extended the ZIP
  1744. /// specification with a way to use AES Encryption to protect entries in the
  1745. /// Zip file. Unlike the "PKZIP 2.0" encryption specified in the PKZIP
  1746. /// specification, <see href=
  1747. /// "http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES
  1748. /// Encryption</see> uses a standard, strong, tested, encryption
  1749. /// algorithm. DotNetZip can create zip archives that use WinZip-compatible
  1750. /// AES encryption, if you set the <see cref="Encryption"/> property. But,
  1751. /// archives created that use AES encryption may not be readable by all other
  1752. /// tools and libraries. For example, Windows Explorer cannot read a
  1753. /// "compressed folder" (a zip file) that uses AES encryption, though it can
  1754. /// read a zip file that uses "PKZIP encryption."
  1755. /// </para>
  1756. ///
  1757. /// <para>
  1758. /// The <see cref="ZipFile"/> class also has a <see cref="ZipFile.Password"/>
  1759. /// property. This property takes precedence over any password set on the
  1760. /// ZipFile itself. Typically, you would use the per-entry Password when most
  1761. /// entries in the zip archive use one password, and a few entries use a
  1762. /// different password. If all entries in the zip file use the same password,
  1763. /// then it is simpler to just set this property on the ZipFile itself,
  1764. /// whether creating a zip archive or extracting a zip archive.
  1765. /// </para>
  1766. ///
  1767. /// <para>
  1768. /// Some comments on updating archives: If you read a <c>ZipFile</c>, you
  1769. /// cannot modify the password on any encrypted entry, except by extracting
  1770. /// the entry with the original password (if any), removing the original entry
  1771. /// via <see cref="ZipFile.RemoveEntry(ZipEntry)"/>, and then adding a new
  1772. /// entry with a new Password.
  1773. /// </para>
  1774. ///
  1775. /// <para>
  1776. /// For example, suppose you read a <c>ZipFile</c>, and there is an encrypted
  1777. /// entry. Setting the Password property on that <c>ZipEntry</c> and then
  1778. /// calling <c>Save()</c> on the <c>ZipFile</c> does not update the password
  1779. /// on that entry in the archive. Neither is an exception thrown. Instead,
  1780. /// what happens during the <c>Save()</c> is the existing entry is copied
  1781. /// through to the new zip archive, in its original encrypted form. Upon
  1782. /// re-reading that archive, the entry can be decrypted with its original
  1783. /// password.
  1784. /// </para>
  1785. ///
  1786. /// <para>
  1787. /// If you read a ZipFile, and there is an un-encrypted entry, you can set the
  1788. /// <c>Password</c> on the entry and then call Save() on the ZipFile, and get
  1789. /// encryption on that entry.
  1790. /// </para>
  1791. ///
  1792. /// </remarks>
  1793. ///
  1794. /// <example>
  1795. /// <para>
  1796. /// This example creates a zip file with two entries, and then extracts the
  1797. /// entries from the zip file. When creating the zip file, the two files are
  1798. /// added to the zip file using password protection. Each entry uses a
  1799. /// different password. During extraction, each file is extracted with the
  1800. /// appropriate password.
  1801. /// </para>
  1802. /// <code>
  1803. /// // create a file with encryption
  1804. /// using (ZipFile zip = new ZipFile())
  1805. /// {
  1806. /// ZipEntry entry;
  1807. /// entry= zip.AddFile("Declaration.txt");
  1808. /// entry.Password= "123456!";
  1809. /// entry = zip.AddFile("Report.xls");
  1810. /// entry.Password= "1Secret!";
  1811. /// zip.Save("EncryptedArchive.zip");
  1812. /// }
  1813. ///
  1814. /// // extract entries that use encryption
  1815. /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
  1816. /// {
  1817. /// ZipEntry entry;
  1818. /// entry = zip["Declaration.txt"];
  1819. /// entry.Password = "123456!";
  1820. /// entry.Extract("extractDir");
  1821. /// entry = zip["Report.xls"];
  1822. /// entry.Password = "1Secret!";
  1823. /// entry.Extract("extractDir");
  1824. /// }
  1825. ///
  1826. /// </code>
  1827. ///
  1828. /// <code lang="VB">
  1829. /// Using zip As New ZipFile
  1830. /// Dim entry as ZipEntry
  1831. /// entry= zip.AddFile("Declaration.txt")
  1832. /// entry.Password= "123456!"
  1833. /// entry = zip.AddFile("Report.xls")
  1834. /// entry.Password= "1Secret!"
  1835. /// zip.Save("EncryptedArchive.zip")
  1836. /// End Using
  1837. ///
  1838. ///
  1839. /// ' extract entries that use encryption
  1840. /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
  1841. /// Dim entry as ZipEntry
  1842. /// entry = zip("Declaration.txt")
  1843. /// entry.Password = "123456!"
  1844. /// entry.Extract("extractDir")
  1845. /// entry = zip("Report.xls")
  1846. /// entry.Password = "1Secret!"
  1847. /// entry.Extract("extractDir")
  1848. /// End Using
  1849. ///
  1850. /// </code>
  1851. ///
  1852. /// </example>
  1853. ///
  1854. /// <seealso cref="Ionic.Zip.ZipEntry.Encryption"/>
  1855. /// <seealso cref="Ionic.Zip.ZipFile.Password">ZipFile.Password</seealso>
  1856. public string Password
  1857. {
  1858. set
  1859. {
  1860. _Password = value;
  1861. if (_Password == null)
  1862. {
  1863. _Encryption = EncryptionAlgorithm.None;
  1864. }
  1865. else
  1866. {
  1867. // We're setting a non-null password.
  1868. // For entries obtained from a zip file that are encrypted, we cannot
  1869. // simply restream (recompress, re-encrypt) the file data, because we
  1870. // need the old password in order to decrypt the data, and then we
  1871. // need the new password to encrypt. So, setting the password is
  1872. // never going to work on an entry that is stored encrypted in a zipfile.
  1873. // But it is not en error to set the password, obviously: callers will
  1874. // set the password in order to Extract encrypted archives.
  1875. // If the source is a zip archive and there was previously no encryption
  1876. // on the entry, then we must re-stream the entry in order to encrypt it.
  1877. if (this._Source == ZipEntrySource.ZipFile && !_sourceIsEncrypted)
  1878. _restreamRequiredOnSave = true;
  1879. if (Encryption == EncryptionAlgorithm.None)
  1880. {
  1881. _Encryption = EncryptionAlgorithm.PkzipWeak;
  1882. }
  1883. }
  1884. }
  1885. private get { return _Password; }
  1886. }
  1887. internal bool IsChanged
  1888. {
  1889. get
  1890. {
  1891. return _restreamRequiredOnSave | _metadataChanged;
  1892. }
  1893. }
  1894. /// <summary>
  1895. /// The action the library should take when extracting a file that already exists.
  1896. /// </summary>
  1897. ///
  1898. /// <remarks>
  1899. /// <para>
  1900. /// This property affects the behavior of the Extract methods (one of the
  1901. /// <c>Extract()</c> or <c>ExtractWithPassword()</c> overloads), when
  1902. /// extraction would would overwrite an existing filesystem file. If you do
  1903. /// not set this property, the library throws an exception when extracting
  1904. /// an entry would overwrite an existing file.
  1905. /// </para>
  1906. ///
  1907. /// <para>
  1908. /// This property has no effect when extracting to a stream, or when the file to be
  1909. /// extracted does not already exist.
  1910. /// </para>
  1911. ///
  1912. /// </remarks>
  1913. /// <seealso cref="Ionic.Zip.ZipFile.ExtractExistingFile"/>
  1914. ///
  1915. /// <example>
  1916. /// This example shows how to set the <c>ExtractExistingFile</c> property in
  1917. /// an <c>ExtractProgress</c> event, in response to user input. The
  1918. /// <c>ExtractProgress</c> event is invoked if and only if the
  1919. /// <c>ExtractExistingFile</c> property was previously set to
  1920. /// <c>ExtractExistingFileAction.InvokeExtractProgressEvent</c>.
  1921. /// <code lang="C#">
  1922. /// public static void ExtractProgress(object sender, ExtractProgressEventArgs e)
  1923. /// {
  1924. /// if (e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry)
  1925. /// Console.WriteLine("extract {0} ", e.CurrentEntry.FileName);
  1926. ///
  1927. /// else if (e.EventType == ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite)
  1928. /// {
  1929. /// ZipEntry entry = e.CurrentEntry;
  1930. /// string response = null;
  1931. /// // Ask the user if he wants overwrite the file
  1932. /// do
  1933. /// {
  1934. /// Console.Write("Overwrite {0} in {1} ? (y/n/C) ", entry.FileName, e.ExtractLocation);
  1935. /// response = Console.ReadLine();
  1936. /// Console.WriteLine();
  1937. ///
  1938. /// } while (response != null &amp;&amp; response[0]!='Y' &amp;&amp;
  1939. /// response[0]!='N' &amp;&amp; response[0]!='C');
  1940. ///
  1941. /// if (response[0]=='C')
  1942. /// e.Cancel = true;
  1943. /// else if (response[0]=='Y')
  1944. /// entry.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently;
  1945. /// else
  1946. /// entry.ExtractExistingFile= ExtractExistingFileAction.DoNotOverwrite;
  1947. /// }
  1948. /// }
  1949. /// </code>
  1950. /// </example>
  1951. public ExtractExistingFileAction ExtractExistingFile
  1952. {
  1953. get;
  1954. set;
  1955. }
  1956. /// <summary>
  1957. /// The action to take when an error is encountered while
  1958. /// opening or reading files as they are saved into a zip archive.
  1959. /// </summary>
  1960. ///
  1961. /// <remarks>
  1962. /// <para>
  1963. /// Errors can occur within a call to <see
  1964. /// cref="ZipFile.Save()">ZipFile.Save</see>, as the various files contained
  1965. /// in a ZipFile are being saved into the zip archive. During the
  1966. /// <c>Save</c>, DotNetZip will perform a <c>File.Open</c> on the file
  1967. /// associated to the ZipEntry, and then will read the entire contents of
  1968. /// the file as it is zipped. Either the open or the Read may fail, because
  1969. /// of lock conflicts or other reasons. Using this property, you can
  1970. /// specify the action to take when such errors occur.
  1971. /// </para>
  1972. ///
  1973. /// <para>
  1974. /// Typically you will NOT set this property on individual ZipEntry
  1975. /// instances. Instead, you will set the <see
  1976. /// cref="ZipFile.ZipErrorAction">ZipFile.ZipErrorAction</see> property on
  1977. /// the ZipFile instance, before adding any entries to the
  1978. /// <c>ZipFile</c>. If you do this, errors encountered on behalf of any of
  1979. /// the entries in the ZipFile will be handled the same way.
  1980. /// </para>
  1981. ///
  1982. /// <para>
  1983. /// But, if you use a <see cref="ZipFile.ZipError"/> handler, you will want
  1984. /// to set this property on the <c>ZipEntry</c> within the handler, to
  1985. /// communicate back to DotNetZip what you would like to do with the
  1986. /// particular error.
  1987. /// </para>
  1988. ///
  1989. /// </remarks>
  1990. /// <seealso cref="Ionic.Zip.ZipFile.ZipErrorAction"/>
  1991. /// <seealso cref="Ionic.Zip.ZipFile.ZipError"/>
  1992. public ZipErrorAction ZipErrorAction
  1993. {
  1994. get;
  1995. set;
  1996. }
  1997. /// <summary>
  1998. /// Indicates whether the entry was included in the most recent save.
  1999. /// </summary>
  2000. /// <remarks>
  2001. /// An entry can be excluded or skipped from a save if there is an error
  2002. /// opening or reading the entry.
  2003. /// </remarks>
  2004. /// <seealso cref="ZipErrorAction"/>
  2005. public bool IncludedInMostRecentSave
  2006. {
  2007. get
  2008. {
  2009. return !_skippedDuringSave;
  2010. }
  2011. }
  2012. /// <summary>
  2013. /// A callback that allows the application to specify the compression to use
  2014. /// for a given entry that is about to be added to the zip archive.
  2015. /// </summary>
  2016. ///
  2017. /// <remarks>
  2018. /// <para>
  2019. /// See <see cref="ZipFile.SetCompression" />
  2020. /// </para>
  2021. /// </remarks>
  2022. public SetCompressionCallback SetCompression
  2023. {
  2024. get;
  2025. set;
  2026. }
  2027. /// <summary>
  2028. /// Set to indicate whether to use UTF-8 encoding for filenames and comments.
  2029. /// </summary>
  2030. ///
  2031. /// <remarks>
  2032. ///
  2033. /// <para>
  2034. /// If this flag is set, the comment and filename for the entry will be
  2035. /// encoded with UTF-8, as described in <see
  2036. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
  2037. /// specification</see>, if necessary. "Necessary" means, the filename or
  2038. /// entry comment (if any) cannot be reflexively encoded and decoded using the
  2039. /// default code page, IBM437.
  2040. /// </para>
  2041. ///
  2042. /// <para>
  2043. /// Setting this flag to true is equivalent to setting <see
  2044. /// cref="ProvisionalAlternateEncoding"/> to <c>System.Text.Encoding.UTF8</c>.
  2045. /// </para>
  2046. ///
  2047. /// <para>
  2048. /// This flag has no effect or relation to the text encoding used within the
  2049. /// file itself.
  2050. /// </para>
  2051. ///
  2052. /// </remarks>
  2053. [Obsolete("Beginning with v1.9.1.6 of DotNetZip, this property is obsolete. It will be removed in a future version of the library. Your applications should use AlternateEncoding and AlternateEncodingUsage instead.")]
  2054. public bool UseUnicodeAsNecessary
  2055. {
  2056. get
  2057. {
  2058. return (AlternateEncoding == System.Text.Encoding.GetEncoding("UTF-8")) &&
  2059. (AlternateEncodingUsage == ZipOption.AsNecessary);
  2060. }
  2061. set
  2062. {
  2063. if (value)
  2064. {
  2065. AlternateEncoding = System.Text.Encoding.GetEncoding("UTF-8");
  2066. AlternateEncodingUsage = ZipOption.AsNecessary;
  2067. }
  2068. else
  2069. {
  2070. AlternateEncoding = Ionic.Zip.ZipFile.DefaultEncoding;
  2071. AlternateEncodingUsage = ZipOption.Never;
  2072. }
  2073. }
  2074. }
  2075. /// <summary>
  2076. /// The text encoding to use for the FileName and Comment on this ZipEntry,
  2077. /// when the default encoding is insufficient.
  2078. /// </summary>
  2079. ///
  2080. /// <remarks>
  2081. ///
  2082. /// <para>
  2083. /// Don't use this property. See <see cref='AlternateEncoding'/>.
  2084. /// </para>
  2085. ///
  2086. /// </remarks>
  2087. [Obsolete("This property is obsolete since v1.9.1.6. Use AlternateEncoding and AlternateEncodingUsage instead.", true)]
  2088. public System.Text.Encoding ProvisionalAlternateEncoding
  2089. {
  2090. get; set;
  2091. }
  2092. /// <summary>
  2093. /// Specifies the alternate text encoding used by this ZipEntry
  2094. /// </summary>
  2095. /// <remarks>
  2096. /// <para>
  2097. /// The default text encoding used in Zip files for encoding filenames and
  2098. /// comments is IBM437, which is something like a superset of ASCII. In
  2099. /// cases where this is insufficient, applications can specify an
  2100. /// alternate encoding.
  2101. /// </para>
  2102. /// <para>
  2103. /// When creating a zip file, the usage of the alternate encoding is
  2104. /// governed by the <see cref="AlternateEncodingUsage"/> property.
  2105. /// Typically you would set both properties to tell DotNetZip to employ an
  2106. /// encoding that is not IBM437 in the zipfile you are creating.
  2107. /// </para>
  2108. /// <para>
  2109. /// Keep in mind that because the ZIP specification states that the only
  2110. /// valid encodings to use are IBM437 and UTF-8, if you use something
  2111. /// other than that, then zip tools and libraries may not be able to
  2112. /// successfully read the zip archive you generate.
  2113. /// </para>
  2114. /// <para>
  2115. /// The zip specification states that applications should presume that
  2116. /// IBM437 is in use, except when a special bit is set, which indicates
  2117. /// UTF-8. There is no way to specify an arbitrary code page, within the
  2118. /// zip file itself. When you create a zip file encoded with gb2312 or
  2119. /// ibm861 or anything other than IBM437 or UTF-8, then the application
  2120. /// that reads the zip file needs to "know" which code page to use. In
  2121. /// some cases, the code page used when reading is chosen implicitly. For
  2122. /// example, WinRar uses the ambient code page for the host desktop
  2123. /// operating system. The pitfall here is that if you create a zip in
  2124. /// Copenhagen and send it to Tokyo, the reader of the zipfile may not be
  2125. /// able to decode successfully.
  2126. /// </para>
  2127. /// </remarks>
  2128. /// <example>
  2129. /// This example shows how to create a zipfile encoded with a
  2130. /// language-specific encoding:
  2131. /// <code>
  2132. /// using (var zip = new ZipFile())
  2133. /// {
  2134. /// zip.AlternateEnoding = System.Text.Encoding.GetEncoding("ibm861");
  2135. /// zip.AlternateEnodingUsage = ZipOption.Always;
  2136. /// zip.AddFileS(arrayOfFiles);
  2137. /// zip.Save("Myarchive-Encoded-in-IBM861.zip");
  2138. /// }
  2139. /// </code>
  2140. /// </example>
  2141. /// <seealso cref="ZipFile.AlternateEncodingUsage" />
  2142. public System.Text.Encoding AlternateEncoding
  2143. {
  2144. get; set;
  2145. }
  2146. /// <summary>
  2147. /// Describes if and when this instance should apply
  2148. /// AlternateEncoding to encode the FileName and Comment, when
  2149. /// saving.
  2150. /// </summary>
  2151. /// <seealso cref="ZipFile.AlternateEncoding" />
  2152. public ZipOption AlternateEncodingUsage
  2153. {
  2154. get; set;
  2155. }
  2156. // /// <summary>
  2157. // /// The text encoding actually used for this ZipEntry.
  2158. // /// </summary>
  2159. // ///
  2160. // /// <remarks>
  2161. // ///
  2162. // /// <para>
  2163. // /// This read-only property describes the encoding used by the
  2164. // /// <c>ZipEntry</c>. If the entry has been read in from an existing ZipFile,
  2165. // /// then it may take the value UTF-8, if the entry is coded to specify UTF-8.
  2166. // /// If the entry does not specify UTF-8, the typical case, then the encoding
  2167. // /// used is whatever the application specified in the call to
  2168. // /// <c>ZipFile.Read()</c>. If the application has used one of the overloads of
  2169. // /// <c>ZipFile.Read()</c> that does not accept an encoding parameter, then the
  2170. // /// encoding used is IBM437, which is the default encoding described in the
  2171. // /// ZIP specification. </para>
  2172. // ///
  2173. // /// <para>
  2174. // /// If the entry is being created, then the value of ActualEncoding is taken
  2175. // /// according to the logic described in the documentation for <see
  2176. // /// cref="ZipFile.ProvisionalAlternateEncoding" />. </para>
  2177. // ///
  2178. // /// <para>
  2179. // /// An application might be interested in retrieving this property to see if
  2180. // /// an entry read in from a file has used Unicode (UTF-8). </para>
  2181. // ///
  2182. // /// </remarks>
  2183. // ///
  2184. // /// <seealso cref="ZipFile.ProvisionalAlternateEncoding" />
  2185. // public System.Text.Encoding ActualEncoding
  2186. // {
  2187. // get
  2188. // {
  2189. // return _actualEncoding;
  2190. // }
  2191. // }
  2192. internal static string NameInArchive(String filename, string directoryPathInArchive)
  2193. {
  2194. string result = null;
  2195. if (directoryPathInArchive == null)
  2196. result = filename;
  2197. else
  2198. {
  2199. if (String.IsNullOrEmpty(directoryPathInArchive))
  2200. {
  2201. result = Path.GetFileName(filename);
  2202. }
  2203. else
  2204. {
  2205. // explicitly specify a pathname for this file
  2206. result = Path.Combine(directoryPathInArchive, Path.GetFileName(filename));
  2207. }
  2208. }
  2209. //result = Path.GetFullPath(result);
  2210. result = SharedUtilities.NormalizePathForUseInZipFile(result);
  2211. return result;
  2212. }
  2213. // workitem 9073
  2214. internal static ZipEntry CreateFromNothing(String nameInArchive)
  2215. {
  2216. return Create(nameInArchive, ZipEntrySource.None, null, null);
  2217. }
  2218. internal static ZipEntry CreateFromFile(String filename, string nameInArchive)
  2219. {
  2220. return Create(nameInArchive, ZipEntrySource.FileSystem, filename, null);
  2221. }
  2222. internal static ZipEntry CreateForStream(String entryName, Stream s)
  2223. {
  2224. return Create(entryName, ZipEntrySource.Stream, s, null);
  2225. }
  2226. internal static ZipEntry CreateForWriter(String entryName, WriteDelegate d)
  2227. {
  2228. return Create(entryName, ZipEntrySource.WriteDelegate, d, null);
  2229. }
  2230. internal static ZipEntry CreateForJitStreamProvider(string nameInArchive, OpenDelegate opener, CloseDelegate closer)
  2231. {
  2232. return Create(nameInArchive, ZipEntrySource.JitStream, opener, closer);
  2233. }
  2234. internal static ZipEntry CreateForZipOutputStream(string nameInArchive)
  2235. {
  2236. return Create(nameInArchive, ZipEntrySource.ZipOutputStream, null, null);
  2237. }
  2238. private static ZipEntry Create(string nameInArchive, ZipEntrySource source, Object arg1, Object arg2)
  2239. {
  2240. if (String.IsNullOrEmpty(nameInArchive))
  2241. throw new Ionic.Zip.ZipException("The entry name must be non-null and non-empty.");
  2242. ZipEntry entry = new ZipEntry();
  2243. // workitem 7071
  2244. // workitem 7926 - "version made by" OS should be zero for compat with WinZip
  2245. entry._VersionMadeBy = (0 << 8) + 45; // indicates the attributes are FAT Attributes, and v4.5 of the spec
  2246. entry._Source = source;
  2247. entry._Mtime = entry._Atime = entry._Ctime = DateTime.UtcNow;
  2248. if (source == ZipEntrySource.Stream)
  2249. {
  2250. entry._sourceStream = (arg1 as Stream); // may or may not be null
  2251. }
  2252. else if (source == ZipEntrySource.WriteDelegate)
  2253. {
  2254. entry._WriteDelegate = (arg1 as WriteDelegate); // may or may not be null
  2255. }
  2256. else if (source == ZipEntrySource.JitStream)
  2257. {
  2258. entry._OpenDelegate = (arg1 as OpenDelegate); // may or may not be null
  2259. entry._CloseDelegate = (arg2 as CloseDelegate); // may or may not be null
  2260. }
  2261. else if (source == ZipEntrySource.ZipOutputStream)
  2262. {
  2263. }
  2264. // workitem 9073
  2265. else if (source == ZipEntrySource.None)
  2266. {
  2267. // make this a valid value, for later.
  2268. entry._Source = ZipEntrySource.FileSystem;
  2269. }
  2270. else
  2271. {
  2272. String filename = (arg1 as String); // must not be null
  2273. if (String.IsNullOrEmpty(filename))
  2274. throw new Ionic.Zip.ZipException("The filename must be non-null and non-empty.");
  2275. try
  2276. {
  2277. // The named file may or may not exist at this time. For
  2278. // example, when adding a directory by name. We test existence
  2279. // when necessary: when saving the ZipFile, or when getting the
  2280. // attributes, and so on.
  2281. #if NETCF
  2282. // workitem 6878
  2283. // Ionic.Zip.SharedUtilities.AdjustTime_Win32ToDotNet
  2284. entry._Mtime = File.GetLastWriteTime(filename).ToUniversalTime();
  2285. entry._Ctime = File.GetCreationTime(filename).ToUniversalTime();
  2286. entry._Atime = File.GetLastAccessTime(filename).ToUniversalTime();
  2287. // workitem 7071
  2288. // can only get attributes of files that exist.
  2289. if (File.Exists(filename) || Directory.Exists(filename))
  2290. entry._ExternalFileAttrs = (int)NetCfFile.GetAttributes(filename);
  2291. #elif SILVERLIGHT
  2292. entry._Mtime =
  2293. entry._Ctime =
  2294. entry._Atime = System.DateTime.UtcNow;
  2295. entry._ExternalFileAttrs = (int)0;
  2296. #else
  2297. // workitem 6878??
  2298. entry._Mtime = File.GetLastWriteTime(filename).ToUniversalTime();
  2299. entry._Ctime = File.GetCreationTime(filename).ToUniversalTime();
  2300. entry._Atime = File.GetLastAccessTime(filename).ToUniversalTime();
  2301. // workitem 7071
  2302. // can only get attributes on files that exist.
  2303. if (File.Exists(filename) || Directory.Exists(filename))
  2304. entry._ExternalFileAttrs = (int)File.GetAttributes(filename);
  2305. #endif
  2306. entry._ntfsTimesAreSet = true;
  2307. entry._LocalFileName = Path.GetFullPath(filename); // workitem 8813
  2308. }
  2309. catch (System.IO.PathTooLongException ptle)
  2310. {
  2311. // workitem 14035
  2312. var msg = String.Format("The path is too long, filename={0}",
  2313. filename);
  2314. throw new ZipException(msg, ptle);
  2315. }
  2316. }
  2317. entry._LastModified = entry._Mtime;
  2318. entry._FileNameInArchive = SharedUtilities.NormalizePathForUseInZipFile(nameInArchive);
  2319. // We don't actually slurp in the file data until the caller invokes Write on this entry.
  2320. return entry;
  2321. }
  2322. internal void MarkAsDirectory()
  2323. {
  2324. _IsDirectory = true;
  2325. // workitem 6279
  2326. if (!_FileNameInArchive.EndsWith("/"))
  2327. _FileNameInArchive += "/";
  2328. }
  2329. /// <summary>
  2330. /// Indicates whether an entry is marked as a text file. Be careful when
  2331. /// using on this property. Unless you have a good reason, you should
  2332. /// probably ignore this property.
  2333. /// </summary>
  2334. ///
  2335. /// <remarks>
  2336. /// <para>
  2337. /// The ZIP format includes a provision for specifying whether an entry in
  2338. /// the zip archive is a text or binary file. This property exposes that
  2339. /// metadata item. Be careful when using this property: It's not clear
  2340. /// that this property as a firm meaning, across tools and libraries.
  2341. /// </para>
  2342. ///
  2343. /// <para>
  2344. /// To be clear, when reading a zip file, the property value may or may
  2345. /// not be set, and its value may or may not be valid. Not all entries
  2346. /// that you may think of as "text" entries will be so marked, and entries
  2347. /// marked as "text" are not guaranteed in any way to be text entries.
  2348. /// Whether the value is set and set correctly depends entirely on the
  2349. /// application that produced the zip file.
  2350. /// </para>
  2351. ///
  2352. /// <para>
  2353. /// There are many zip tools available, and when creating zip files, some
  2354. /// of them "respect" the IsText metadata field, and some of them do not.
  2355. /// Unfortunately, even when an application tries to do "the right thing",
  2356. /// it's not always clear what "the right thing" is.
  2357. /// </para>
  2358. ///
  2359. /// <para>
  2360. /// There's no firm definition of just what it means to be "a text file",
  2361. /// and the zip specification does not help in this regard. Twenty years
  2362. /// ago, text was ASCII, each byte was less than 127. IsText meant, all
  2363. /// bytes in the file were less than 127. These days, it is not the case
  2364. /// that all text files have all bytes less than 127. Any unicode file
  2365. /// may have bytes that are above 0x7f. The zip specification has nothing
  2366. /// to say on this topic. Therefore, it's not clear what IsText really
  2367. /// means.
  2368. /// </para>
  2369. ///
  2370. /// <para>
  2371. /// This property merely tells a reading application what is stored in the
  2372. /// metadata for an entry, without guaranteeing its validity or its
  2373. /// meaning.
  2374. /// </para>
  2375. ///
  2376. /// <para>
  2377. /// When DotNetZip is used to create a zipfile, it attempts to set this
  2378. /// field "correctly." For example, if a file ends in ".txt", this field
  2379. /// will be set. Your application may override that default setting. When
  2380. /// writing a zip file, you must set the property before calling
  2381. /// <c>Save()</c> on the ZipFile.
  2382. /// </para>
  2383. ///
  2384. /// <para>
  2385. /// When reading a zip file, a more general way to decide just what kind
  2386. /// of file is contained in a particular entry is to use the file type
  2387. /// database stored in the operating system. The operating system stores
  2388. /// a table that says, a file with .jpg extension is a JPG image file, a
  2389. /// file with a .xml extension is an XML document, a file with a .txt is a
  2390. /// pure ASCII text document, and so on. To get this information on
  2391. /// Windows, <see
  2392. /// href="http://www.codeproject.com/KB/cs/GetFileTypeAndIcon.aspx"> you
  2393. /// need to read and parse the registry.</see> </para>
  2394. /// </remarks>
  2395. ///
  2396. /// <example>
  2397. /// <code>
  2398. /// using (var zip = new ZipFile())
  2399. /// {
  2400. /// var e = zip.UpdateFile("Descriptions.mme", "");
  2401. /// e.IsText = true;
  2402. /// zip.Save(zipPath);
  2403. /// }
  2404. /// </code>
  2405. ///
  2406. /// <code lang="VB">
  2407. /// Using zip As New ZipFile
  2408. /// Dim e2 as ZipEntry = zip.AddFile("Descriptions.mme", "")
  2409. /// e.IsText= True
  2410. /// zip.Save(zipPath)
  2411. /// End Using
  2412. /// </code>
  2413. /// </example>
  2414. public bool IsText
  2415. {
  2416. // workitem 7801
  2417. get { return _IsText; }
  2418. set { _IsText = value; }
  2419. }
  2420. /// <summary>Provides a string representation of the instance.</summary>
  2421. /// <returns>a string representation of the instance.</returns>
  2422. public override String ToString()
  2423. {
  2424. return String.Format("ZipEntry::{0}", FileName);
  2425. }
  2426. internal Stream ArchiveStream
  2427. {
  2428. get
  2429. {
  2430. if (_archiveStream == null)
  2431. {
  2432. if (_container.ZipFile != null)
  2433. {
  2434. var zf = _container.ZipFile;
  2435. zf.Reset(false);
  2436. _archiveStream = zf.StreamForDiskNumber(_diskNumber);
  2437. }
  2438. else
  2439. {
  2440. _archiveStream = _container.ZipOutputStream.OutputStream;
  2441. }
  2442. }
  2443. return _archiveStream;
  2444. }
  2445. }
  2446. private void SetFdpLoh()
  2447. {
  2448. // The value for FileDataPosition has not yet been set.
  2449. // Therefore, seek to the local header, and figure the start of file data.
  2450. // workitem 8098: ok (restore)
  2451. long origPosition = this.ArchiveStream.Position;
  2452. try
  2453. {
  2454. this.ArchiveStream.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin);
  2455. // workitem 10178
  2456. Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);
  2457. }
  2458. catch (IOException exc1)
  2459. {
  2460. var description = String.Format("Exception seeking entry({0}) offset(0x{1:X8}) len(0x{2:X8})",
  2461. this.FileName, this._RelativeOffsetOfLocalHeader,
  2462. this.ArchiveStream.Length);
  2463. throw new BadStateException(description, exc1);
  2464. }
  2465. byte[] block = new byte[30];
  2466. this.ArchiveStream.Read(block, 0, block.Length);
  2467. // At this point we could verify the contents read from the local header
  2468. // with the contents read from the central header. We could, but don't need to.
  2469. // So we won't.
  2470. Int16 filenameLength = (short)(block[26] + block[27] * 256);
  2471. Int16 extraFieldLength = (short)(block[28] + block[29] * 256);
  2472. // Console.WriteLine(" pos 0x{0:X8} ({0})", this.ArchiveStream.Position);
  2473. // Console.WriteLine(" seek 0x{0:X8} ({0})", filenameLength + extraFieldLength);
  2474. this.ArchiveStream.Seek(filenameLength + extraFieldLength, SeekOrigin.Current);
  2475. // workitem 10178
  2476. Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);
  2477. this._LengthOfHeader = 30 + extraFieldLength + filenameLength +
  2478. GetLengthOfCryptoHeaderBytes(_Encryption_FromZipFile);
  2479. // Console.WriteLine(" ROLH 0x{0:X8} ({0})", _RelativeOffsetOfLocalHeader);
  2480. // Console.WriteLine(" LOH 0x{0:X8} ({0})", _LengthOfHeader);
  2481. // workitem 8098: ok (arithmetic)
  2482. this.__FileDataPosition = _RelativeOffsetOfLocalHeader + _LengthOfHeader;
  2483. // Console.WriteLine(" FDP 0x{0:X8} ({0})", __FileDataPosition);
  2484. // restore file position:
  2485. // workitem 8098: ok (restore)
  2486. this.ArchiveStream.Seek(origPosition, SeekOrigin.Begin);
  2487. // workitem 10178
  2488. Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);
  2489. }
  2490. #if AESCRYPTO
  2491. private static int GetKeyStrengthInBits(EncryptionAlgorithm a)
  2492. {
  2493. if (a == EncryptionAlgorithm.WinZipAes256) return 256;
  2494. else if (a == EncryptionAlgorithm.WinZipAes128) return 128;
  2495. return -1;
  2496. }
  2497. #endif
  2498. internal static int GetLengthOfCryptoHeaderBytes(EncryptionAlgorithm a)
  2499. {
  2500. //if ((_BitField & 0x01) != 0x01) return 0;
  2501. if (a == EncryptionAlgorithm.None) return 0;
  2502. #if AESCRYPTO
  2503. if (a == EncryptionAlgorithm.WinZipAes128 ||
  2504. a == EncryptionAlgorithm.WinZipAes256)
  2505. {
  2506. int KeyStrengthInBits = GetKeyStrengthInBits(a);
  2507. int sizeOfSaltAndPv = ((KeyStrengthInBits / 8 / 2) + 2);
  2508. return sizeOfSaltAndPv;
  2509. }
  2510. #endif
  2511. if (a == EncryptionAlgorithm.PkzipWeak)
  2512. return 12;
  2513. throw new ZipException("internal error");
  2514. }
  2515. internal long FileDataPosition
  2516. {
  2517. get
  2518. {
  2519. if (__FileDataPosition == -1)
  2520. SetFdpLoh();
  2521. return __FileDataPosition;
  2522. }
  2523. }
  2524. private int LengthOfHeader
  2525. {
  2526. get
  2527. {
  2528. if (_LengthOfHeader == 0)
  2529. SetFdpLoh();
  2530. return _LengthOfHeader;
  2531. }
  2532. }
  2533. private ZipCrypto _zipCrypto_forExtract;
  2534. private ZipCrypto _zipCrypto_forWrite;
  2535. #if AESCRYPTO
  2536. private WinZipAesCrypto _aesCrypto_forExtract;
  2537. private WinZipAesCrypto _aesCrypto_forWrite;
  2538. private Int16 _WinZipAesMethod;
  2539. #endif
  2540. internal DateTime _LastModified;
  2541. private bool _dontEmitLastModified;
  2542. private DateTime _Mtime, _Atime, _Ctime; // workitem 6878: NTFS quantities
  2543. private bool _ntfsTimesAreSet;
  2544. private bool _emitNtfsTimes = true;
  2545. private bool _emitUnixTimes; // by default, false
  2546. private bool _TrimVolumeFromFullyQualifiedPaths = true; // by default, trim them.
  2547. internal string _LocalFileName;
  2548. private string _FileNameInArchive;
  2549. internal Int16 _VersionNeeded;
  2550. internal Int16 _BitField;
  2551. internal Int16 _CompressionMethod;
  2552. private Int16 _CompressionMethod_FromZipFile;
  2553. private Ionic.Zlib.CompressionLevel _CompressionLevel;
  2554. internal string _Comment;
  2555. private bool _IsDirectory;
  2556. private byte[] _CommentBytes;
  2557. internal Int64 _CompressedSize;
  2558. internal Int64 _CompressedFileDataSize; // CompressedSize less 12 bytes for the encryption header, if any
  2559. internal Int64 _UncompressedSize;
  2560. internal Int32 _TimeBlob;
  2561. private bool _crcCalculated;
  2562. internal Int32 _Crc32;
  2563. internal byte[] _Extra;
  2564. private bool _metadataChanged;
  2565. private bool _restreamRequiredOnSave;
  2566. private bool _sourceIsEncrypted;
  2567. private bool _skippedDuringSave;
  2568. private UInt32 _diskNumber;
  2569. private static System.Text.Encoding ibm437 = System.Text.Encoding.GetEncoding("IBM437");
  2570. //private System.Text.Encoding _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
  2571. private System.Text.Encoding _actualEncoding;
  2572. internal ZipContainer _container;
  2573. private long __FileDataPosition = -1;
  2574. private byte[] _EntryHeader;
  2575. internal Int64 _RelativeOffsetOfLocalHeader;
  2576. private Int64 _future_ROLH;
  2577. private Int64 _TotalEntrySize;
  2578. private int _LengthOfHeader;
  2579. private int _LengthOfTrailer;
  2580. internal bool _InputUsesZip64;
  2581. private UInt32 _UnsupportedAlgorithmId;
  2582. internal string _Password;
  2583. internal ZipEntrySource _Source;
  2584. internal EncryptionAlgorithm _Encryption;
  2585. internal EncryptionAlgorithm _Encryption_FromZipFile;
  2586. internal byte[] _WeakEncryptionHeader;
  2587. internal Stream _archiveStream;
  2588. private Stream _sourceStream;
  2589. private Nullable<Int64> _sourceStreamOriginalPosition;
  2590. private bool _sourceWasJitProvided;
  2591. private bool _ioOperationCanceled;
  2592. private bool _presumeZip64;
  2593. private Nullable<bool> _entryRequiresZip64;
  2594. private Nullable<bool> _OutputUsesZip64;
  2595. private bool _IsText; // workitem 7801
  2596. private ZipEntryTimestamp _timestamp;
  2597. private static System.DateTime _unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
  2598. private static System.DateTime _win32Epoch = System.DateTime.FromFileTimeUtc(0L);
  2599. private static System.DateTime _zeroHour = new System.DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc);
  2600. private WriteDelegate _WriteDelegate;
  2601. private OpenDelegate _OpenDelegate;
  2602. private CloseDelegate _CloseDelegate;
  2603. // summary
  2604. // The default size of the IO buffer for ZipEntry instances. Currently it is 8192 bytes.
  2605. // summary
  2606. //public const int IO_BUFFER_SIZE_DEFAULT = 8192; // 0x8000; // 0x4400
  2607. }
  2608. /// <summary>
  2609. /// An enum that specifies the type of timestamp available on the ZipEntry.
  2610. /// </summary>
  2611. ///
  2612. /// <remarks>
  2613. ///
  2614. /// <para>
  2615. /// The last modified time of a file can be stored in multiple ways in
  2616. /// a zip file, and they are not mutually exclusive:
  2617. /// </para>
  2618. ///
  2619. /// <list type="bullet">
  2620. /// <item>
  2621. /// In the so-called "DOS" format, which has a 2-second precision. Values
  2622. /// are rounded to the nearest even second. For example, if the time on the
  2623. /// file is 12:34:43, then it will be stored as 12:34:44. This first value
  2624. /// is accessible via the <c>LastModified</c> property. This value is always
  2625. /// present in the metadata for each zip entry. In some cases the value is
  2626. /// invalid, or zero.
  2627. /// </item>
  2628. ///
  2629. /// <item>
  2630. /// In the so-called "Windows" or "NTFS" format, as an 8-byte integer
  2631. /// quantity expressed as the number of 1/10 milliseconds (in other words
  2632. /// the number of 100 nanosecond units) since January 1, 1601 (UTC). This
  2633. /// format is how Windows represents file times. This time is accessible
  2634. /// via the <c>ModifiedTime</c> property.
  2635. /// </item>
  2636. ///
  2637. /// <item>
  2638. /// In the "Unix" format, a 4-byte quantity specifying the number of seconds since
  2639. /// January 1, 1970 UTC.
  2640. /// </item>
  2641. ///
  2642. /// <item>
  2643. /// In an older format, now deprecated but still used by some current
  2644. /// tools. This format is also a 4-byte quantity specifying the number of
  2645. /// seconds since January 1, 1970 UTC.
  2646. /// </item>
  2647. ///
  2648. /// </list>
  2649. ///
  2650. /// <para>
  2651. /// This bit field describes which of the formats were found in a <c>ZipEntry</c> that was read.
  2652. /// </para>
  2653. ///
  2654. /// </remarks>
  2655. [Flags]
  2656. public enum ZipEntryTimestamp
  2657. {
  2658. /// <summary>
  2659. /// Default value.
  2660. /// </summary>
  2661. None = 0,
  2662. /// <summary>
  2663. /// A DOS timestamp with 2-second precision.
  2664. /// </summary>
  2665. DOS = 1,
  2666. /// <summary>
  2667. /// A Windows timestamp with 100-ns precision.
  2668. /// </summary>
  2669. Windows = 2,
  2670. /// <summary>
  2671. /// A Unix timestamp with 1-second precision.
  2672. /// </summary>
  2673. Unix = 4,
  2674. /// <summary>
  2675. /// A Unix timestamp with 1-second precision, stored in InfoZip v1 format. This
  2676. /// format is outdated and is supported for reading archives only.
  2677. /// </summary>
  2678. InfoZip1 = 8,
  2679. }
  2680. /// <summary>
  2681. /// The method of compression to use for a particular ZipEntry.
  2682. /// </summary>
  2683. ///
  2684. /// <remarks>
  2685. /// <see
  2686. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWare's
  2687. /// ZIP Specification</see> describes a number of distinct
  2688. /// cmopression methods that can be used within a zip
  2689. /// file. DotNetZip supports a subset of them.
  2690. /// </remarks>
  2691. public enum CompressionMethod
  2692. {
  2693. /// <summary>
  2694. /// No compression at all. For COM environments, the value is 0 (zero).
  2695. /// </summary>
  2696. None = 0,
  2697. /// <summary>
  2698. /// DEFLATE compression, as described in <see
  2699. /// href="http://www.ietf.org/rfc/rfc1951.txt">IETF RFC
  2700. /// 1951</see>. This is the "normal" compression used in zip
  2701. /// files. For COM environments, the value is 8.
  2702. /// </summary>
  2703. Deflate = 8,
  2704. #if BZIP
  2705. /// <summary>
  2706. /// BZip2 compression, a compression algorithm developed by Julian Seward.
  2707. /// For COM environments, the value is 12.
  2708. /// </summary>
  2709. BZip2 = 12,
  2710. #endif
  2711. }
  2712. #if NETCF
  2713. internal class NetCfFile
  2714. {
  2715. public static int SetTimes(string filename, DateTime ctime, DateTime atime, DateTime mtime)
  2716. {
  2717. IntPtr hFile = (IntPtr) CreateFileCE(filename,
  2718. (uint)0x40000000L, // (uint)FileAccess.Write,
  2719. (uint)0x00000002L, // (uint)FileShare.Write,
  2720. 0,
  2721. (uint) 3, // == open existing
  2722. (uint)0, // flagsAndAttributes
  2723. 0);
  2724. if((int)hFile == -1)
  2725. {
  2726. // workitem 7944: don't throw on failure to set file times
  2727. // throw new ZipException("CreateFileCE Failed");
  2728. return Interop.Marshal.GetLastWin32Error();
  2729. }
  2730. SetFileTime(hFile,
  2731. BitConverter.GetBytes(ctime.ToFileTime()),
  2732. BitConverter.GetBytes(atime.ToFileTime()),
  2733. BitConverter.GetBytes(mtime.ToFileTime()));
  2734. CloseHandle(hFile);
  2735. return 0;
  2736. }
  2737. public static int SetLastWriteTime(string filename, DateTime mtime)
  2738. {
  2739. IntPtr hFile = (IntPtr) CreateFileCE(filename,
  2740. (uint)0x40000000L, // (uint)FileAccess.Write,
  2741. (uint)0x00000002L, // (uint)FileShare.Write,
  2742. 0,
  2743. (uint) 3, // == open existing
  2744. (uint)0, // flagsAndAttributes
  2745. 0);
  2746. if((int)hFile == -1)
  2747. {
  2748. // workitem 7944: don't throw on failure to set file time
  2749. // throw new ZipException(String.Format("CreateFileCE Failed ({0})",
  2750. // Interop.Marshal.GetLastWin32Error()));
  2751. return Interop.Marshal.GetLastWin32Error();
  2752. }
  2753. SetFileTime(hFile, null, null,
  2754. BitConverter.GetBytes(mtime.ToFileTime()));
  2755. CloseHandle(hFile);
  2756. return 0;
  2757. }
  2758. [Interop.DllImport("coredll.dll", EntryPoint="CreateFile", SetLastError=true)]
  2759. internal static extern int CreateFileCE(string lpFileName,
  2760. uint dwDesiredAccess,
  2761. uint dwShareMode,
  2762. int lpSecurityAttributes,
  2763. uint dwCreationDisposition,
  2764. uint dwFlagsAndAttributes,
  2765. int hTemplateFile);
  2766. [Interop.DllImport("coredll", EntryPoint="GetFileAttributes", SetLastError=true)]
  2767. internal static extern uint GetAttributes(string lpFileName);
  2768. [Interop.DllImport("coredll", EntryPoint="SetFileAttributes", SetLastError=true)]
  2769. internal static extern bool SetAttributes(string lpFileName, uint dwFileAttributes);
  2770. [Interop.DllImport("coredll", EntryPoint="SetFileTime", SetLastError=true)]
  2771. internal static extern bool SetFileTime(IntPtr hFile, byte[] lpCreationTime, byte[] lpLastAccessTime, byte[] lpLastWriteTime);
  2772. [Interop.DllImport("coredll.dll", SetLastError=true)]
  2773. internal static extern bool CloseHandle(IntPtr hObject);
  2774. }
  2775. #endif
  2776. }