ZipFile.cs 169 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965
  1. // ZipFile.cs
  2. //
  3. // Copyright (c) 2006-2010 Dino Chiesa
  4. // All rights reserved.
  5. //
  6. // This module is part of DotNetZip, a zipfile class library.
  7. // The class library reads and writes zip files, according to the format
  8. // described by PKware, at:
  9. // http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
  10. //
  11. //
  12. // There are other Zip class libraries available.
  13. //
  14. // - it is possible to read and write zip files within .NET via the J# runtime.
  15. // But some people don't like to install the extra DLL, which is no longer
  16. // supported by MS. And also, the J# libraries don't support advanced zip
  17. // features, like ZIP64, spanned archives, or AES encryption.
  18. //
  19. // - There are third-party GPL and LGPL libraries available. Some people don't
  20. // like the license, and some of them don't support all the ZIP features, like AES.
  21. //
  22. // - Finally, there are commercial tools (From ComponentOne, XCeed, etc). But
  23. // some people don't want to incur the cost.
  24. //
  25. // This alternative implementation is **not** GPL licensed. It is free of cost, and
  26. // does not require J#. It does require .NET 2.0. It balances a good set of
  27. // features, with ease of use and speed of performance.
  28. //
  29. // This code is released under the Microsoft Public License .
  30. // See the License.txt for details.
  31. //
  32. //
  33. // NB: This implementation originally relied on the
  34. // System.IO.Compression.DeflateStream base class in the .NET Framework
  35. // v2.0 base class library, but now includes a managed-code port of Zlib.
  36. //
  37. // Thu, 08 Oct 2009 17:04
  38. //
  39. using System;
  40. using System.IO;
  41. using System.Collections.Generic;
  42. using Interop = System.Runtime.InteropServices;
  43. namespace Ionic.Zip
  44. {
  45. /// <summary>
  46. /// The ZipFile type represents a zip archive file.
  47. /// </summary>
  48. ///
  49. /// <remarks>
  50. /// <para>
  51. /// This is the main type in the DotNetZip class library. This class reads and
  52. /// writes zip files, as defined in the <see
  53. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">specification
  54. /// for zip files described by PKWare</see>. The compression for this
  55. /// implementation is provided by a managed-code version of Zlib, included with
  56. /// DotNetZip in the classes in the Ionic.Zlib namespace.
  57. /// </para>
  58. ///
  59. /// <para>
  60. /// This class provides a general purpose zip file capability. Use it to read,
  61. /// create, or update zip files. When you want to create zip files using a
  62. /// <c>Stream</c> type to write the zip file, you may want to consider the <see
  63. /// cref="ZipOutputStream"/> class.
  64. /// </para>
  65. ///
  66. /// <para>
  67. /// Both the <c>ZipOutputStream</c> class and the <c>ZipFile</c> class can
  68. /// be used to create zip files. Both of them support many of the common zip
  69. /// features, including Unicode, different compression methods and levels,
  70. /// and ZIP64. They provide very similar performance when creating zip
  71. /// files.
  72. /// </para>
  73. ///
  74. /// <para>
  75. /// The <c>ZipFile</c> class is generally easier to use than
  76. /// <c>ZipOutputStream</c> and should be considered a higher-level interface. For
  77. /// example, when creating a zip file via calls to the <c>PutNextEntry()</c> and
  78. /// <c>Write()</c> methods on the <c>ZipOutputStream</c> class, the caller is
  79. /// responsible for opening the file, reading the bytes from the file, writing
  80. /// those bytes into the <c>ZipOutputStream</c>, setting the attributes on the
  81. /// <c>ZipEntry</c>, and setting the created, last modified, and last accessed
  82. /// timestamps on the zip entry. All of these things are done automatically by a
  83. /// call to <see cref="ZipFile.AddFile(string,string)">ZipFile.AddFile()</see>.
  84. /// For this reason, the <c>ZipOutputStream</c> is generally recommended for use
  85. /// only when your application emits arbitrary data, not necessarily data from a
  86. /// filesystem file, directly into a zip file, and does so using a <c>Stream</c>
  87. /// metaphor.
  88. /// </para>
  89. ///
  90. /// <para>
  91. /// Aside from the differences in programming model, there are other
  92. /// differences in capability between the two classes.
  93. /// </para>
  94. ///
  95. /// <list type="bullet">
  96. /// <item>
  97. /// <c>ZipFile</c> can be used to read and extract zip files, in addition to
  98. /// creating zip files. <c>ZipOutputStream</c> cannot read zip files. If you want
  99. /// to use a stream to read zip files, check out the <see cref="ZipInputStream"/> class.
  100. /// </item>
  101. ///
  102. /// <item>
  103. /// <c>ZipOutputStream</c> does not support the creation of segmented or spanned
  104. /// zip files.
  105. /// </item>
  106. ///
  107. /// <item>
  108. /// <c>ZipOutputStream</c> cannot produce a self-extracting archive.
  109. /// </item>
  110. /// </list>
  111. ///
  112. /// <para>
  113. /// Be aware that the <c>ZipFile</c> class implements the <see
  114. /// cref="System.IDisposable"/> interface. In order for <c>ZipFile</c> to
  115. /// produce a valid zip file, you use use it within a using clause (<c>Using</c>
  116. /// in VB), or call the <c>Dispose()</c> method explicitly. See the examples
  117. /// for how to employ a using clause.
  118. /// </para>
  119. ///
  120. /// </remarks>
  121. [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00005")]
  122. [Interop.ComVisible(true)]
  123. #if !NETCF
  124. [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)]
  125. #endif
  126. public partial class ZipFile :
  127. System.Collections.IEnumerable,
  128. System.Collections.Generic.IEnumerable<ZipEntry>,
  129. IDisposable
  130. {
  131. #region public properties
  132. /// <summary>
  133. /// Indicates whether to perform a full scan of the zip file when reading it.
  134. /// </summary>
  135. ///
  136. /// <remarks>
  137. ///
  138. /// <para>
  139. /// You almost never want to use this property.
  140. /// </para>
  141. ///
  142. /// <para>
  143. /// When reading a zip file, if this flag is <c>true</c> (<c>True</c> in
  144. /// VB), the entire zip archive will be scanned and searched for entries.
  145. /// For large archives, this can take a very, long time. The much more
  146. /// efficient default behavior is to read the zip directory, which is
  147. /// stored at the end of the zip file. But, in some cases the directory is
  148. /// corrupted and you need to perform a full scan of the zip file to
  149. /// determine the contents of the zip file. This property lets you do
  150. /// that, when necessary.
  151. /// </para>
  152. ///
  153. /// <para>
  154. /// This flag is effective only when calling <see
  155. /// cref="Initialize(string)"/>. Normally you would read a ZipFile with the
  156. /// static <see cref="ZipFile.Read(String)">ZipFile.Read</see>
  157. /// method. But you can't set the <c>FullScan</c> property on the
  158. /// <c>ZipFile</c> instance when you use a static factory method like
  159. /// <c>ZipFile.Read</c>.
  160. /// </para>
  161. ///
  162. /// </remarks>
  163. ///
  164. /// <example>
  165. ///
  166. /// This example shows how to read a zip file using the full scan approach,
  167. /// and then save it, thereby producing a corrected zip file.
  168. ///
  169. /// <code lang="C#">
  170. /// using (var zip = new ZipFile())
  171. /// {
  172. /// zip.FullScan = true;
  173. /// zip.Initialize(zipFileName);
  174. /// zip.Save(newName);
  175. /// }
  176. /// </code>
  177. ///
  178. /// <code lang="VB">
  179. /// Using zip As New ZipFile
  180. /// zip.FullScan = True
  181. /// zip.Initialize(zipFileName)
  182. /// zip.Save(newName)
  183. /// End Using
  184. /// </code>
  185. /// </example>
  186. ///
  187. public bool FullScan
  188. {
  189. get;
  190. set;
  191. }
  192. /// <summary>
  193. /// Whether to sort the ZipEntries before saving the file.
  194. /// </summary>
  195. ///
  196. /// <remarks>
  197. /// The default is false. If you have a large number of zip entries, the sort
  198. /// alone can consume significant time.
  199. /// </remarks>
  200. ///
  201. /// <example>
  202. /// <code lang="C#">
  203. /// using (var zip = new ZipFile())
  204. /// {
  205. /// zip.AddFiles(filesToAdd);
  206. /// zip.SortEntriesBeforeSaving = true;
  207. /// zip.Save(name);
  208. /// }
  209. /// </code>
  210. ///
  211. /// <code lang="VB">
  212. /// Using zip As New ZipFile
  213. /// zip.AddFiles(filesToAdd)
  214. /// zip.SortEntriesBeforeSaving = True
  215. /// zip.Save(name)
  216. /// End Using
  217. /// </code>
  218. /// </example>
  219. ///
  220. public bool SortEntriesBeforeSaving
  221. {
  222. get;
  223. set;
  224. }
  225. /// <summary>
  226. /// Indicates whether NTFS Reparse Points, like junctions, should be
  227. /// traversed during calls to <c>AddDirectory()</c>.
  228. /// </summary>
  229. ///
  230. /// <remarks>
  231. /// By default, calls to AddDirectory() will traverse NTFS reparse
  232. /// points, like mounted volumes, and directory junctions. An example
  233. /// of a junction is the "My Music" directory in Windows Vista. In some
  234. /// cases you may not want DotNetZip to traverse those directories. In
  235. /// that case, set this property to false.
  236. /// </remarks>
  237. ///
  238. /// <example>
  239. /// <code lang="C#">
  240. /// using (var zip = new ZipFile())
  241. /// {
  242. /// zip.AddDirectoryWillTraverseReparsePoints = false;
  243. /// zip.AddDirectory(dirToZip,"fodder");
  244. /// zip.Save(zipFileToCreate);
  245. /// }
  246. /// </code>
  247. /// </example>
  248. public bool AddDirectoryWillTraverseReparsePoints { get; set; }
  249. /// <summary>
  250. /// Size of the IO buffer used while saving.
  251. /// </summary>
  252. ///
  253. /// <remarks>
  254. ///
  255. /// <para>
  256. /// First, let me say that you really don't need to bother with this. It is
  257. /// here to allow for optimizations that you probably won't make! It will work
  258. /// fine if you don't set or get this property at all. Ok?
  259. /// </para>
  260. ///
  261. /// <para>
  262. /// Now that we have <em>that</em> out of the way, the fine print: This
  263. /// property affects the size of the buffer that is used for I/O for each
  264. /// entry contained in the zip file. When a file is read in to be compressed,
  265. /// it uses a buffer given by the size here. When you update a zip file, the
  266. /// data for unmodified entries is copied from the first zip file to the
  267. /// other, through a buffer given by the size here.
  268. /// </para>
  269. ///
  270. /// <para>
  271. /// Changing the buffer size affects a few things: first, for larger buffer
  272. /// sizes, the memory used by the <c>ZipFile</c>, obviously, will be larger
  273. /// during I/O operations. This may make operations faster for very much
  274. /// larger files. Last, for any given entry, when you use a larger buffer
  275. /// there will be fewer progress events during I/O operations, because there's
  276. /// one progress event generated for each time the buffer is filled and then
  277. /// emptied.
  278. /// </para>
  279. ///
  280. /// <para>
  281. /// The default buffer size is 8k. Increasing the buffer size may speed
  282. /// things up as you compress larger files. But there are no hard-and-fast
  283. /// rules here, eh? You won't know til you test it. And there will be a
  284. /// limit where ever larger buffers actually slow things down. So as I said
  285. /// in the beginning, it's probably best if you don't set or get this property
  286. /// at all.
  287. /// </para>
  288. ///
  289. /// </remarks>
  290. ///
  291. /// <example>
  292. /// This example shows how you might set a large buffer size for efficiency when
  293. /// dealing with zip entries that are larger than 1gb.
  294. /// <code lang="C#">
  295. /// using (ZipFile zip = new ZipFile())
  296. /// {
  297. /// zip.SaveProgress += this.zip1_SaveProgress;
  298. /// zip.AddDirectory(directoryToZip, "");
  299. /// zip.UseZip64WhenSaving = Zip64Option.Always;
  300. /// zip.BufferSize = 65536*8; // 65536 * 8 = 512k
  301. /// zip.Save(ZipFileToCreate);
  302. /// }
  303. /// </code>
  304. /// </example>
  305. public int BufferSize
  306. {
  307. get { return _BufferSize; }
  308. set { _BufferSize = value; }
  309. }
  310. /// <summary>
  311. /// Size of the work buffer to use for the ZLIB codec during compression.
  312. /// </summary>
  313. ///
  314. /// <remarks>
  315. /// <para>
  316. /// When doing ZLIB or Deflate compression, the library fills a buffer,
  317. /// then passes it to the compressor for compression. Then the library
  318. /// reads out the compressed bytes. This happens repeatedly until there
  319. /// is no more uncompressed data to compress. This property sets the
  320. /// size of the buffer that will be used for chunk-wise compression. In
  321. /// order for the setting to take effect, your application needs to set
  322. /// this property before calling one of the <c>ZipFile.Save()</c>
  323. /// overloads.
  324. /// </para>
  325. /// <para>
  326. /// Setting this affects the performance and memory efficiency of
  327. /// compression and decompression. For larger files, setting this to a
  328. /// larger size may improve compression performance, but the exact
  329. /// numbers vary depending on available memory, the size of the streams
  330. /// you are compressing, and a bunch of other variables. I don't have
  331. /// good firm recommendations on how to set it. You'll have to test it
  332. /// yourself. Or just leave it alone and accept the default.
  333. /// </para>
  334. /// </remarks>
  335. public int CodecBufferSize
  336. {
  337. get;
  338. set;
  339. }
  340. /// <summary>
  341. /// Indicates whether extracted files should keep their paths as
  342. /// stored in the zip archive.
  343. /// </summary>
  344. ///
  345. /// <remarks>
  346. /// <para>
  347. /// This property affects Extraction. It is not used when creating zip
  348. /// archives.
  349. /// </para>
  350. ///
  351. /// <para>
  352. /// With this property set to <c>false</c>, the default, extracting entries
  353. /// from a zip file will create files in the filesystem that have the full
  354. /// path associated to the entry within the zip file. With this property set
  355. /// to <c>true</c>, extracting entries from the zip file results in files
  356. /// with no path: the folders are "flattened."
  357. /// </para>
  358. ///
  359. /// <para>
  360. /// An example: suppose the zip file contains entries /directory1/file1.txt and
  361. /// /directory2/file2.txt. With <c>FlattenFoldersOnExtract</c> set to false,
  362. /// the files created will be \directory1\file1.txt and \directory2\file2.txt.
  363. /// With the property set to true, the files created are file1.txt and file2.txt.
  364. /// </para>
  365. ///
  366. /// </remarks>
  367. public bool FlattenFoldersOnExtract
  368. {
  369. get;
  370. set;
  371. }
  372. /// <summary>
  373. /// The compression strategy to use for all entries.
  374. /// </summary>
  375. ///
  376. /// <remarks>
  377. /// Set the Strategy used by the ZLIB-compatible compressor, when
  378. /// compressing entries using the DEFLATE method. Different compression
  379. /// strategies work better on different sorts of data. The strategy
  380. /// parameter can affect the compression ratio and the speed of
  381. /// compression but not the correctness of the compresssion. For more
  382. /// information see <see
  383. /// cref="Ionic.Zlib.CompressionStrategy">Ionic.Zlib.CompressionStrategy</see>.
  384. /// </remarks>
  385. public Ionic.Zlib.CompressionStrategy Strategy
  386. {
  387. get { return _Strategy; }
  388. set { _Strategy = value; }
  389. }
  390. /// <summary>
  391. /// The name of the <c>ZipFile</c>, on disk.
  392. /// </summary>
  393. ///
  394. /// <remarks>
  395. ///
  396. /// <para>
  397. /// When the <c>ZipFile</c> instance was created by reading an archive using
  398. /// one of the <c>ZipFile.Read</c> methods, this property represents the name
  399. /// of the zip file that was read. When the <c>ZipFile</c> instance was
  400. /// created by using the no-argument constructor, this value is <c>null</c>
  401. /// (<c>Nothing</c> in VB).
  402. /// </para>
  403. ///
  404. /// <para>
  405. /// If you use the no-argument constructor, and you then explicitly set this
  406. /// property, when you call <see cref="ZipFile.Save()"/>, this name will
  407. /// specify the name of the zip file created. Doing so is equivalent to
  408. /// calling <see cref="ZipFile.Save(String)"/>. When instantiating a
  409. /// <c>ZipFile</c> by reading from a stream or byte array, the <c>Name</c>
  410. /// property remains <c>null</c>. When saving to a stream, the <c>Name</c>
  411. /// property is implicitly set to <c>null</c>.
  412. /// </para>
  413. /// </remarks>
  414. public string Name
  415. {
  416. get { return _name; }
  417. set { _name = value; }
  418. }
  419. /// <summary>
  420. /// Sets the compression level to be used for entries subsequently added to
  421. /// the zip archive.
  422. /// </summary>
  423. ///
  424. /// <remarks>
  425. /// <para>
  426. /// Varying the compression level used on entries can affect the
  427. /// size-vs-speed tradeoff when compression and decompressing data streams
  428. /// or files.
  429. /// </para>
  430. ///
  431. /// <para>
  432. /// As with some other properties on the <c>ZipFile</c> class, like <see
  433. /// cref="Password"/>, <see cref="Encryption"/>, and <see
  434. /// cref="ZipErrorAction"/>, setting this property on a <c>ZipFile</c>
  435. /// instance will cause the specified <c>CompressionLevel</c> to be used on all
  436. /// <see cref="ZipEntry"/> items that are subsequently added to the
  437. /// <c>ZipFile</c> instance. If you set this property after you have added
  438. /// items to the <c>ZipFile</c>, but before you have called <c>Save()</c>,
  439. /// those items will not use the specified compression level.
  440. /// </para>
  441. ///
  442. /// <para>
  443. /// If you do not set this property, the default compression level is used,
  444. /// which normally gives a good balance of compression efficiency and
  445. /// compression speed. In some tests, using <c>BestCompression</c> can
  446. /// double the time it takes to compress, while delivering just a small
  447. /// increase in compression efficiency. This behavior will vary with the
  448. /// type of data you compress. If you are in doubt, just leave this setting
  449. /// alone, and accept the default.
  450. /// </para>
  451. /// </remarks>
  452. public Ionic.Zlib.CompressionLevel CompressionLevel
  453. {
  454. get;
  455. set;
  456. }
  457. /// <summary>
  458. /// The compression method for the zipfile.
  459. /// </summary>
  460. /// <remarks>
  461. /// <para>
  462. /// By default, the compression method is <c>CompressionMethod.Deflate.</c>
  463. /// </para>
  464. /// </remarks>
  465. /// <seealso cref="Ionic.Zip.CompressionMethod" />
  466. public Ionic.Zip.CompressionMethod CompressionMethod
  467. {
  468. get
  469. {
  470. return _compressionMethod;
  471. }
  472. set
  473. {
  474. _compressionMethod = value;
  475. }
  476. }
  477. /// <summary>
  478. /// A comment attached to the zip archive.
  479. /// </summary>
  480. ///
  481. /// <remarks>
  482. ///
  483. /// <para>
  484. /// This property is read/write. It allows the application to specify a
  485. /// comment for the <c>ZipFile</c>, or read the comment for the
  486. /// <c>ZipFile</c>. After setting this property, changes are only made
  487. /// permanent when you call a <c>Save()</c> method.
  488. /// </para>
  489. ///
  490. /// <para>
  491. /// According to <see
  492. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
  493. /// zip specification</see>, the comment is not encrypted, even if there is a
  494. /// password set on the zip file.
  495. /// </para>
  496. ///
  497. /// <para>
  498. /// The specification does not describe how to indicate the encoding used
  499. /// on a comment string. Many "compliant" zip tools and libraries use
  500. /// IBM437 as the code page for comments; DotNetZip, too, follows that
  501. /// practice. On the other hand, there are situations where you want a
  502. /// Comment to be encoded with something else, for example using code page
  503. /// 950 "Big-5 Chinese". To fill that need, DotNetZip will encode the
  504. /// comment following the same procedure it follows for encoding
  505. /// filenames: (a) if <see cref="AlternateEncodingUsage"/> is
  506. /// <c>Never</c>, it uses the default encoding (IBM437). (b) if <see
  507. /// cref="AlternateEncodingUsage"/> is <c>Always</c>, it always uses the
  508. /// alternate encoding (<see cref="AlternateEncoding"/>). (c) if <see
  509. /// cref="AlternateEncodingUsage"/> is <c>AsNecessary</c>, it uses the
  510. /// alternate encoding only if the default encoding is not sufficient for
  511. /// encoding the comment - in other words if decoding the result does not
  512. /// produce the original string. This decision is taken at the time of
  513. /// the call to <c>ZipFile.Save()</c>.
  514. /// </para>
  515. ///
  516. /// <para>
  517. /// When creating a zip archive using this library, it is possible to change
  518. /// the value of <see cref="AlternateEncoding" /> between each
  519. /// entry you add, and between adding entries and the call to
  520. /// <c>Save()</c>. Don't do this. It will likely result in a zip file that is
  521. /// not readable by any tool or application. For best interoperability, leave
  522. /// <see cref="AlternateEncoding"/> alone, or specify it only
  523. /// once, before adding any entries to the <c>ZipFile</c> instance.
  524. /// </para>
  525. ///
  526. /// </remarks>
  527. public string Comment
  528. {
  529. get { return _Comment; }
  530. set
  531. {
  532. _Comment = value;
  533. _contentsChanged = true;
  534. }
  535. }
  536. /// <summary>
  537. /// Specifies whether the Creation, Access, and Modified times for entries
  538. /// added to the zip file will be emitted in &#147;Windows format&#148;
  539. /// when the zip archive is saved.
  540. /// </summary>
  541. ///
  542. /// <remarks>
  543. /// <para>
  544. /// An application creating a zip archive can use this flag to explicitly
  545. /// specify that the file times for the entries should or should not be stored
  546. /// in the zip archive in the format used by Windows. By default this flag is
  547. /// <c>true</c>, meaning the Windows-format times are stored in the zip
  548. /// archive.
  549. /// </para>
  550. ///
  551. /// <para>
  552. /// When adding an entry from a file or directory, the Creation (<see
  553. /// cref="ZipEntry.CreationTime"/>), Access (<see
  554. /// cref="ZipEntry.AccessedTime"/>), and Modified (<see
  555. /// cref="ZipEntry.ModifiedTime"/>) times for the given entry are
  556. /// automatically set from the filesystem values. When adding an entry from a
  557. /// stream or string, all three values are implicitly set to
  558. /// <c>DateTime.Now</c>. Applications can also explicitly set those times by
  559. /// calling <see cref="ZipEntry.SetEntryTimes(DateTime, DateTime,
  560. /// DateTime)"/>.
  561. /// </para>
  562. ///
  563. /// <para>
  564. /// <see
  565. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
  566. /// zip specification</see> describes multiple ways to format these times in a
  567. /// zip file. One is the format Windows applications normally use: 100ns ticks
  568. /// since January 1, 1601 UTC. The other is a format Unix applications typically
  569. /// use: seconds since January 1, 1970 UTC. Each format can be stored in an
  570. /// "extra field" in the zip entry when saving the zip archive. The former
  571. /// uses an extra field with a Header Id of 0x000A, while the latter uses a
  572. /// header ID of 0x5455, although you probably don't need to know that.
  573. /// </para>
  574. ///
  575. /// <para>
  576. /// Not all tools and libraries can interpret these fields. Windows
  577. /// compressed folders is one that can read the Windows Format timestamps,
  578. /// while I believe <see href="http://www.info-zip.org/">the Infozip
  579. /// tools</see> can read the Unix format timestamps. Some tools and libraries
  580. /// may be able to read only one or the other. DotNetZip can read or write
  581. /// times in either or both formats.
  582. /// </para>
  583. ///
  584. /// <para>
  585. /// The times stored are taken from <see cref="ZipEntry.ModifiedTime"/>, <see
  586. /// cref="ZipEntry.AccessedTime"/>, and <see cref="ZipEntry.CreationTime"/>.
  587. /// </para>
  588. ///
  589. /// <para>
  590. /// The value set here applies to all entries subsequently added to the
  591. /// <c>ZipFile</c>.
  592. /// </para>
  593. ///
  594. /// <para>
  595. /// This property is not mutually exclusive of the <see
  596. /// cref="EmitTimesInUnixFormatWhenSaving" /> property. It is possible and
  597. /// legal and valid to produce a zip file that contains timestamps encoded in
  598. /// the Unix format as well as in the Windows format, in addition to the <see
  599. /// cref="ZipEntry.LastModified">LastModified</see> time attached to each
  600. /// entry in the archive, a time that is always stored in "DOS format". And,
  601. /// notwithstanding the names PKWare uses for these time formats, any of them
  602. /// can be read and written by any computer, on any operating system. But,
  603. /// there are no guarantees that a program running on Mac or Linux will
  604. /// gracefully handle a zip file with "Windows" formatted times, or that an
  605. /// application that does not use DotNetZip but runs on Windows will be able to
  606. /// handle file times in Unix format.
  607. /// </para>
  608. ///
  609. /// <para>
  610. /// When in doubt, test. Sorry, I haven't got a complete list of tools and
  611. /// which sort of timestamps they can use and will tolerate. If you get any
  612. /// good information and would like to pass it on, please do so and I will
  613. /// include that information in this documentation.
  614. /// </para>
  615. /// </remarks>
  616. ///
  617. /// <example>
  618. /// This example shows how to save a zip file that contains file timestamps
  619. /// in a format normally used by Unix.
  620. /// <code lang="C#">
  621. /// using (var zip = new ZipFile())
  622. /// {
  623. /// // produce a zip file the Mac will like
  624. /// zip.EmitTimesInWindowsFormatWhenSaving = false;
  625. /// zip.EmitTimesInUnixFormatWhenSaving = true;
  626. /// zip.AddDirectory(directoryToZip, "files");
  627. /// zip.Save(outputFile);
  628. /// }
  629. /// </code>
  630. ///
  631. /// <code lang="VB">
  632. /// Using zip As New ZipFile
  633. /// '' produce a zip file the Mac will like
  634. /// zip.EmitTimesInWindowsFormatWhenSaving = False
  635. /// zip.EmitTimesInUnixFormatWhenSaving = True
  636. /// zip.AddDirectory(directoryToZip, "files")
  637. /// zip.Save(outputFile)
  638. /// End Using
  639. /// </code>
  640. /// </example>
  641. ///
  642. /// <seealso cref="ZipEntry.EmitTimesInWindowsFormatWhenSaving" />
  643. /// <seealso cref="EmitTimesInUnixFormatWhenSaving" />
  644. public bool EmitTimesInWindowsFormatWhenSaving
  645. {
  646. get
  647. {
  648. return _emitNtfsTimes;
  649. }
  650. set
  651. {
  652. _emitNtfsTimes = value;
  653. }
  654. }
  655. /// <summary>
  656. /// Specifies whether the Creation, Access, and Modified times
  657. /// for entries added to the zip file will be emitted in "Unix(tm)
  658. /// format" when the zip archive is saved.
  659. /// </summary>
  660. ///
  661. /// <remarks>
  662. /// <para>
  663. /// An application creating a zip archive can use this flag to explicitly
  664. /// specify that the file times for the entries should or should not be stored
  665. /// in the zip archive in the format used by Unix. By default this flag is
  666. /// <c>false</c>, meaning the Unix-format times are not stored in the zip
  667. /// archive.
  668. /// </para>
  669. ///
  670. /// <para>
  671. /// When adding an entry from a file or directory, the Creation (<see
  672. /// cref="ZipEntry.CreationTime"/>), Access (<see
  673. /// cref="ZipEntry.AccessedTime"/>), and Modified (<see
  674. /// cref="ZipEntry.ModifiedTime"/>) times for the given entry are
  675. /// automatically set from the filesystem values. When adding an entry from a
  676. /// stream or string, all three values are implicitly set to DateTime.Now.
  677. /// Applications can also explicitly set those times by calling <see
  678. /// cref="ZipEntry.SetEntryTimes(DateTime, DateTime, DateTime)"/>.
  679. /// </para>
  680. ///
  681. /// <para>
  682. /// <see
  683. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
  684. /// zip specification</see> describes multiple ways to format these times in a
  685. /// zip file. One is the format Windows applications normally use: 100ns ticks
  686. /// since January 1, 1601 UTC. The other is a format Unix applications
  687. /// typically use: seconds since January 1, 1970 UTC. Each format can be
  688. /// stored in an "extra field" in the zip entry when saving the zip
  689. /// archive. The former uses an extra field with a Header Id of 0x000A, while
  690. /// the latter uses a header ID of 0x5455, although you probably don't need to
  691. /// know that.
  692. /// </para>
  693. ///
  694. /// <para>
  695. /// Not all tools and libraries can interpret these fields. Windows
  696. /// compressed folders is one that can read the Windows Format timestamps,
  697. /// while I believe the <see href="http://www.info-zip.org/">Infozip</see>
  698. /// tools can read the Unix format timestamps. Some tools and libraries may be
  699. /// able to read only one or the other. DotNetZip can read or write times in
  700. /// either or both formats.
  701. /// </para>
  702. ///
  703. /// <para>
  704. /// The times stored are taken from <see cref="ZipEntry.ModifiedTime"/>, <see
  705. /// cref="ZipEntry.AccessedTime"/>, and <see cref="ZipEntry.CreationTime"/>.
  706. /// </para>
  707. ///
  708. /// <para>
  709. /// This property is not mutually exclusive of the <see
  710. /// cref="EmitTimesInWindowsFormatWhenSaving" /> property. It is possible and
  711. /// legal and valid to produce a zip file that contains timestamps encoded in
  712. /// the Unix format as well as in the Windows format, in addition to the <see
  713. /// cref="ZipEntry.LastModified">LastModified</see> time attached to each
  714. /// entry in the zip archive, a time that is always stored in "DOS
  715. /// format". And, notwithstanding the names PKWare uses for these time
  716. /// formats, any of them can be read and written by any computer, on any
  717. /// operating system. But, there are no guarantees that a program running on
  718. /// Mac or Linux will gracefully handle a zip file with "Windows" formatted
  719. /// times, or that an application that does not use DotNetZip but runs on
  720. /// Windows will be able to handle file times in Unix format.
  721. /// </para>
  722. ///
  723. /// <para>
  724. /// When in doubt, test. Sorry, I haven't got a complete list of tools and
  725. /// which sort of timestamps they can use and will tolerate. If you get any
  726. /// good information and would like to pass it on, please do so and I will
  727. /// include that information in this documentation.
  728. /// </para>
  729. /// </remarks>
  730. ///
  731. /// <seealso cref="ZipEntry.EmitTimesInUnixFormatWhenSaving" />
  732. /// <seealso cref="EmitTimesInWindowsFormatWhenSaving" />
  733. public bool EmitTimesInUnixFormatWhenSaving
  734. {
  735. get
  736. {
  737. return _emitUnixTimes;
  738. }
  739. set
  740. {
  741. _emitUnixTimes = value;
  742. }
  743. }
  744. /// <summary>
  745. /// Indicates whether verbose output is sent to the <see
  746. /// cref="StatusMessageTextWriter"/> during <c>AddXxx()</c> and
  747. /// <c>ReadXxx()</c> operations.
  748. /// </summary>
  749. ///
  750. /// <remarks>
  751. /// This is a <em>synthetic</em> property. It returns true if the <see
  752. /// cref="StatusMessageTextWriter"/> is non-null.
  753. /// </remarks>
  754. internal bool Verbose
  755. {
  756. get { return (_StatusMessageTextWriter != null); }
  757. }
  758. /// <summary>
  759. /// Returns true if an entry by the given name exists in the ZipFile.
  760. /// </summary>
  761. ///
  762. /// <param name='name'>the name of the entry to find</param>
  763. /// <returns>true if an entry with the given name exists; otherwise false.
  764. /// </returns>
  765. public bool ContainsEntry(string name)
  766. {
  767. // workitem 12534
  768. return RetrievalEntries.ContainsKey(SharedUtilities.NormalizePathForUseInZipFile(name));
  769. }
  770. /// <summary>
  771. /// Indicates whether to perform case-sensitive matching on the filename when
  772. /// retrieving entries in the zipfile via the string-based indexer.
  773. /// </summary>
  774. ///
  775. /// <remarks>
  776. /// The default value is <c>false</c>, which means don't do case-sensitive
  777. /// matching. In other words, retrieving zip["ReadMe.Txt"] is the same as
  778. /// zip["readme.txt"]. It really makes sense to set this to <c>true</c> only
  779. /// if you are not running on Windows, which has case-insensitive
  780. /// filenames. But since this library is not built for non-Windows platforms,
  781. /// in most cases you should just leave this property alone.
  782. /// </remarks>
  783. public bool CaseSensitiveRetrieval
  784. {
  785. get
  786. {
  787. return _CaseSensitiveRetrieval;
  788. }
  789. set
  790. {
  791. _CaseSensitiveRetrieval = value;
  792. }
  793. }
  794. private Dictionary<string, ZipEntry> RetrievalEntries
  795. {
  796. get { return CaseSensitiveRetrieval ? _entries : _entriesInsensitive; }
  797. }
  798. /// <summary>
  799. /// Indicates whether to ignore duplicate files (report only the first entry)
  800. /// when loading a zipfile.
  801. /// </summary>
  802. ///
  803. /// <remarks>
  804. /// The default value is <c>false</c>, which will try to make all files
  805. /// available (duplicates will have a "copy" suffix appended to their name).
  806. /// Setting this to <c>true</c> prior to using <c>Initialize</c> to read a
  807. /// zipfile will prevent this and instead just ignore the duplicates.
  808. /// </remarks>
  809. public bool IgnoreDuplicateFiles
  810. {
  811. get { return _IgnoreDuplicateFiles; }
  812. set { _IgnoreDuplicateFiles = value; }
  813. }
  814. /// <summary>
  815. /// Indicates whether to encode entry filenames and entry comments using Unicode
  816. /// (UTF-8).
  817. /// </summary>
  818. ///
  819. /// <remarks>
  820. /// <para>
  821. /// <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">The
  822. /// PKWare zip specification</see> provides for encoding file names and file
  823. /// comments in either the IBM437 code page, or in UTF-8. This flag selects
  824. /// the encoding according to that specification. By default, this flag is
  825. /// false, and filenames and comments are encoded into the zip file in the
  826. /// IBM437 codepage. Setting this flag to true will specify that filenames
  827. /// and comments that cannot be encoded with IBM437 will be encoded with
  828. /// UTF-8.
  829. /// </para>
  830. ///
  831. /// <para>
  832. /// Zip files created with strict adherence to the PKWare specification with
  833. /// respect to UTF-8 encoding can contain entries with filenames containing
  834. /// any combination of Unicode characters, including the full range of
  835. /// characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other
  836. /// alphabets. However, because at this time, the UTF-8 portion of the PKWare
  837. /// specification is not broadly supported by other zip libraries and
  838. /// utilities, such zip files may not be readable by your favorite zip tool or
  839. /// archiver. In other words, interoperability will decrease if you set this
  840. /// flag to true.
  841. /// </para>
  842. ///
  843. /// <para>
  844. /// In particular, Zip files created with strict adherence to the PKWare
  845. /// specification with respect to UTF-8 encoding will not work well with
  846. /// Explorer in Windows XP or Windows Vista, because Windows compressed
  847. /// folders, as far as I know, do not support UTF-8 in zip files. Vista can
  848. /// read the zip files, but shows the filenames incorrectly. Unpacking from
  849. /// Windows Vista Explorer will result in filenames that have rubbish
  850. /// characters in place of the high-order UTF-8 bytes.
  851. /// </para>
  852. ///
  853. /// <para>
  854. /// Also, zip files that use UTF-8 encoding will not work well with Java
  855. /// applications that use the java.util.zip classes, as of v5.0 of the Java
  856. /// runtime. The Java runtime does not correctly implement the PKWare
  857. /// specification in this regard.
  858. /// </para>
  859. ///
  860. /// <para>
  861. /// As a result, we have the unfortunate situation that "correct" behavior by
  862. /// the DotNetZip library with regard to Unicode encoding of filenames during
  863. /// zip creation will result in zip files that are readable by strictly
  864. /// compliant and current tools (for example the most recent release of the
  865. /// commercial WinZip tool); but these zip files will not be readable by
  866. /// various other tools or libraries, including Windows Explorer.
  867. /// </para>
  868. ///
  869. /// <para>
  870. /// The DotNetZip library can read and write zip files with UTF8-encoded
  871. /// entries, according to the PKware spec. If you use DotNetZip for both
  872. /// creating and reading the zip file, and you use UTF-8, there will be no
  873. /// loss of information in the filenames. For example, using a self-extractor
  874. /// created by this library will allow you to unpack files correctly with no
  875. /// loss of information in the filenames.
  876. /// </para>
  877. ///
  878. /// <para>
  879. /// If you do not set this flag, it will remain false. If this flag is false,
  880. /// your <c>ZipFile</c> will encode all filenames and comments using the
  881. /// IBM437 codepage. This can cause "loss of information" on some filenames,
  882. /// but the resulting zipfile will be more interoperable with other
  883. /// utilities. As an example of the loss of information, diacritics can be
  884. /// lost. The o-tilde character will be down-coded to plain o. The c with a
  885. /// cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c.
  886. /// Likewise, the O-stroke character (Unicode 248), used in Danish and
  887. /// Norwegian, will be down-coded to plain o. Chinese characters cannot be
  888. /// represented in codepage IBM437; when using the default encoding, Chinese
  889. /// characters in filenames will be represented as ?. These are all examples
  890. /// of "information loss".
  891. /// </para>
  892. ///
  893. /// <para>
  894. /// The loss of information associated to the use of the IBM437 encoding is
  895. /// inconvenient, and can also lead to runtime errors. For example, using
  896. /// IBM437, any sequence of 4 Chinese characters will be encoded as ????. If
  897. /// your application creates a <c>ZipFile</c>, then adds two files, each with
  898. /// names of four Chinese characters each, this will result in a duplicate
  899. /// filename exception. In the case where you add a single file with a name
  900. /// containing four Chinese characters, calling Extract() on the entry that
  901. /// has question marks in the filename will result in an exception, because
  902. /// the question mark is not legal for use within filenames on Windows. These
  903. /// are just a few examples of the problems associated to loss of information.
  904. /// </para>
  905. ///
  906. /// <para>
  907. /// This flag is independent of the encoding of the content within the entries
  908. /// in the zip file. Think of the zip file as a container - it supports an
  909. /// encoding. Within the container are other "containers" - the file entries
  910. /// themselves. The encoding within those entries is independent of the
  911. /// encoding of the zip archive container for those entries.
  912. /// </para>
  913. ///
  914. /// <para>
  915. /// Rather than specify the encoding in a binary fashion using this flag, an
  916. /// application can specify an arbitrary encoding via the <see
  917. /// cref="ProvisionalAlternateEncoding"/> property. Setting the encoding
  918. /// explicitly when creating zip archives will result in non-compliant zip
  919. /// files that, curiously, are fairly interoperable. The challenge is, the
  920. /// PKWare specification does not provide for a way to specify that an entry
  921. /// in a zip archive uses a code page that is neither IBM437 nor UTF-8.
  922. /// Therefore if you set the encoding explicitly when creating a zip archive,
  923. /// you must take care upon reading the zip archive to use the same code page.
  924. /// If you get it wrong, the behavior is undefined and may result in incorrect
  925. /// filenames, exceptions, stomach upset, hair loss, and acne.
  926. /// </para>
  927. /// </remarks>
  928. /// <seealso cref="ProvisionalAlternateEncoding"/>
  929. [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.")]
  930. public bool UseUnicodeAsNecessary
  931. {
  932. get
  933. {
  934. return (_alternateEncoding == System.Text.Encoding.GetEncoding("UTF-8")) &&
  935. (_alternateEncodingUsage == ZipOption.AsNecessary);
  936. }
  937. set
  938. {
  939. if (value)
  940. {
  941. _alternateEncoding = System.Text.Encoding.GetEncoding("UTF-8");
  942. _alternateEncodingUsage = ZipOption.AsNecessary;
  943. }
  944. else
  945. {
  946. _alternateEncoding = Ionic.Zip.ZipFile.DefaultEncoding;
  947. _alternateEncodingUsage = ZipOption.Never;
  948. }
  949. }
  950. }
  951. /// <summary>
  952. /// Specify whether to use ZIP64 extensions when saving a zip archive.
  953. /// </summary>
  954. ///
  955. /// <remarks>
  956. ///
  957. /// <para>
  958. /// When creating a zip file, the default value for the property is <see
  959. /// cref="Zip64Option.Never"/>. <see cref="Zip64Option.AsNecessary"/> is
  960. /// safest, in the sense that you will not get an Exception if a pre-ZIP64
  961. /// limit is exceeded.
  962. /// </para>
  963. ///
  964. /// <para>
  965. /// You may set the property at any time before calling Save().
  966. /// </para>
  967. ///
  968. /// <para>
  969. /// When reading a zip file via the <c>Zipfile.Read()</c> method, DotNetZip
  970. /// will properly read ZIP64-endowed zip archives, regardless of the value of
  971. /// this property. DotNetZip will always read ZIP64 archives. This property
  972. /// governs only whether DotNetZip will write them. Therefore, when updating
  973. /// archives, be careful about setting this property after reading an archive
  974. /// that may use ZIP64 extensions.
  975. /// </para>
  976. ///
  977. /// <para>
  978. /// An interesting question is, if you have set this property to
  979. /// <c>AsNecessary</c>, and then successfully saved, does the resulting
  980. /// archive use ZIP64 extensions or not? To learn this, check the <see
  981. /// cref="OutputUsedZip64"/> property, after calling <c>Save()</c>.
  982. /// </para>
  983. ///
  984. /// <para>
  985. /// Have you thought about
  986. /// <see href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">donating</see>?
  987. /// </para>
  988. ///
  989. /// </remarks>
  990. /// <seealso cref="RequiresZip64"/>
  991. public Zip64Option UseZip64WhenSaving
  992. {
  993. get
  994. {
  995. return _zip64;
  996. }
  997. set
  998. {
  999. _zip64 = value;
  1000. }
  1001. }
  1002. /// <summary>
  1003. /// Indicates whether the archive requires ZIP64 extensions.
  1004. /// </summary>
  1005. ///
  1006. /// <remarks>
  1007. ///
  1008. /// <para>
  1009. /// This property is <c>null</c> (or <c>Nothing</c> in VB) if the archive has
  1010. /// not been saved, and there are fewer than 65334 <c>ZipEntry</c> items
  1011. /// contained in the archive.
  1012. /// </para>
  1013. ///
  1014. /// <para>
  1015. /// The <c>Value</c> is true if any of the following four conditions holds:
  1016. /// the uncompressed size of any entry is larger than 0xFFFFFFFF; the
  1017. /// compressed size of any entry is larger than 0xFFFFFFFF; the relative
  1018. /// offset of any entry within the zip archive is larger than 0xFFFFFFFF; or
  1019. /// there are more than 65534 entries in the archive. (0xFFFFFFFF =
  1020. /// 4,294,967,295). The result may not be known until a <c>Save()</c> is attempted
  1021. /// on the zip archive. The Value of this <see cref="System.Nullable"/>
  1022. /// property may be set only AFTER one of the Save() methods has been called.
  1023. /// </para>
  1024. ///
  1025. /// <para>
  1026. /// If none of the four conditions holds, and the archive has been saved, then
  1027. /// the <c>Value</c> is false.
  1028. /// </para>
  1029. ///
  1030. /// <para>
  1031. /// A <c>Value</c> of false does not indicate that the zip archive, as saved,
  1032. /// does not use ZIP64. It merely indicates that ZIP64 is not required. An
  1033. /// archive may use ZIP64 even when not required if the <see
  1034. /// cref="ZipFile.UseZip64WhenSaving"/> property is set to <see
  1035. /// cref="Zip64Option.Always"/>, or if the <see
  1036. /// cref="ZipFile.UseZip64WhenSaving"/> property is set to <see
  1037. /// cref="Zip64Option.AsNecessary"/> and the output stream was not
  1038. /// seekable. Use the <see cref="OutputUsedZip64"/> property to determine if
  1039. /// the most recent <c>Save()</c> method resulted in an archive that utilized
  1040. /// the ZIP64 extensions.
  1041. /// </para>
  1042. ///
  1043. /// </remarks>
  1044. /// <seealso cref="UseZip64WhenSaving"/>
  1045. /// <seealso cref="OutputUsedZip64"/>
  1046. public Nullable<bool> RequiresZip64
  1047. {
  1048. get
  1049. {
  1050. if (_entries.Count > 65534)
  1051. return new Nullable<bool>(true);
  1052. // If the <c>ZipFile</c> has not been saved or if the contents have changed, then
  1053. // it is not known if ZIP64 is required.
  1054. if (!_hasBeenSaved || _contentsChanged) return null;
  1055. // Whether ZIP64 is required is knowable.
  1056. foreach (ZipEntry e in _entries.Values)
  1057. {
  1058. if (e.RequiresZip64.Value) return new Nullable<bool>(true);
  1059. }
  1060. return new Nullable<bool>(false);
  1061. }
  1062. }
  1063. /// <summary>
  1064. /// Indicates whether the most recent <c>Save()</c> operation used ZIP64 extensions.
  1065. /// </summary>
  1066. ///
  1067. /// <remarks>
  1068. /// <para>
  1069. /// The use of ZIP64 extensions within an archive is not always necessary, and
  1070. /// for interoperability concerns, it may be desired to NOT use ZIP64 if
  1071. /// possible. The <see cref="ZipFile.UseZip64WhenSaving"/> property can be
  1072. /// set to use ZIP64 extensions only when necessary. In those cases,
  1073. /// Sometimes applications want to know whether a Save() actually used ZIP64
  1074. /// extensions. Applications can query this read-only property to learn
  1075. /// whether ZIP64 has been used in a just-saved <c>ZipFile</c>.
  1076. /// </para>
  1077. ///
  1078. /// <para>
  1079. /// The value is <c>null</c> (or <c>Nothing</c> in VB) if the archive has not
  1080. /// been saved.
  1081. /// </para>
  1082. ///
  1083. /// <para>
  1084. /// Non-null values (<c>HasValue</c> is true) indicate whether ZIP64
  1085. /// extensions were used during the most recent <c>Save()</c> operation. The
  1086. /// ZIP64 extensions may have been used as required by any particular entry
  1087. /// because of its uncompressed or compressed size, or because the archive is
  1088. /// larger than 4294967295 bytes, or because there are more than 65534 entries
  1089. /// in the archive, or because the <c>UseZip64WhenSaving</c> property was set
  1090. /// to <see cref="Zip64Option.Always"/>, or because the
  1091. /// <c>UseZip64WhenSaving</c> property was set to <see
  1092. /// cref="Zip64Option.AsNecessary"/> and the output stream was not seekable.
  1093. /// The value of this property does not indicate the reason the ZIP64
  1094. /// extensions were used.
  1095. /// </para>
  1096. ///
  1097. /// </remarks>
  1098. /// <seealso cref="UseZip64WhenSaving"/>
  1099. /// <seealso cref="RequiresZip64"/>
  1100. public Nullable<bool> OutputUsedZip64
  1101. {
  1102. get
  1103. {
  1104. return _OutputUsesZip64;
  1105. }
  1106. }
  1107. /// <summary>
  1108. /// Indicates whether the most recent <c>Read()</c> operation read a zip file that uses
  1109. /// ZIP64 extensions.
  1110. /// </summary>
  1111. ///
  1112. /// <remarks>
  1113. /// This property will return null (Nothing in VB) if you've added an entry after reading
  1114. /// the zip file.
  1115. /// </remarks>
  1116. public Nullable<bool> InputUsesZip64
  1117. {
  1118. get
  1119. {
  1120. if (_entries.Count > 65534)
  1121. return true;
  1122. foreach (ZipEntry e in this)
  1123. {
  1124. // if any entry was added after reading the zip file, then the result is null
  1125. if (e.Source != ZipEntrySource.ZipFile) return null;
  1126. // if any entry read from the zip used zip64, then the result is true
  1127. if (e._InputUsesZip64) return true;
  1128. }
  1129. return false;
  1130. }
  1131. }
  1132. /// <summary>
  1133. /// The text encoding to use when writing new entries to the <c>ZipFile</c>,
  1134. /// for those entries that cannot be encoded with the default (IBM437)
  1135. /// encoding; or, the text encoding that was used when reading the entries
  1136. /// from the <c>ZipFile</c>.
  1137. /// </summary>
  1138. ///
  1139. /// <remarks>
  1140. /// <para>
  1141. /// In <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">its
  1142. /// zip specification</see>, PKWare describes two options for encoding
  1143. /// filenames and comments: using IBM437 or UTF-8. But, some archiving tools
  1144. /// or libraries do not follow the specification, and instead encode
  1145. /// characters using the system default code page. For example, WinRAR when
  1146. /// run on a machine in Shanghai may encode filenames with the Big-5 Chinese
  1147. /// (950) code page. This behavior is contrary to the Zip specification, but
  1148. /// it occurs anyway.
  1149. /// </para>
  1150. ///
  1151. /// <para>
  1152. /// When using DotNetZip to write zip archives that will be read by one of
  1153. /// these other archivers, set this property to specify the code page to use
  1154. /// when encoding the <see cref="ZipEntry.FileName"/> and <see
  1155. /// cref="ZipEntry.Comment"/> for each <c>ZipEntry</c> in the zip file, for
  1156. /// values that cannot be encoded with the default codepage for zip files,
  1157. /// IBM437. This is why this property is "provisional". In all cases, IBM437
  1158. /// is used where possible, in other words, where no loss of data would
  1159. /// result. It is possible, therefore, to have a given entry with a
  1160. /// <c>Comment</c> encoded in IBM437 and a <c>FileName</c> encoded with the
  1161. /// specified "provisional" codepage.
  1162. /// </para>
  1163. ///
  1164. /// <para>
  1165. /// Be aware that a zip file created after you've explicitly set the <see
  1166. /// cref="ProvisionalAlternateEncoding" /> property to a value other than
  1167. /// IBM437 may not be compliant to the PKWare specification, and may not be
  1168. /// readable by compliant archivers. On the other hand, many (most?)
  1169. /// archivers are non-compliant and can read zip files created in arbitrary
  1170. /// code pages. The trick is to use or specify the proper codepage when
  1171. /// reading the zip.
  1172. /// </para>
  1173. ///
  1174. /// <para>
  1175. /// When creating a zip archive using this library, it is possible to change
  1176. /// the value of <see cref="ProvisionalAlternateEncoding" /> between each
  1177. /// entry you add, and between adding entries and the call to
  1178. /// <c>Save()</c>. Don't do this. It will likely result in a zipfile that is
  1179. /// not readable. For best interoperability, either leave <see
  1180. /// cref="ProvisionalAlternateEncoding" /> alone, or specify it only once,
  1181. /// before adding any entries to the <c>ZipFile</c> instance. There is one
  1182. /// exception to this recommendation, described later.
  1183. /// </para>
  1184. ///
  1185. /// <para>
  1186. /// When using an arbitrary, non-UTF8 code page for encoding, there is no
  1187. /// standard way for the creator application - whether DotNetZip, WinZip,
  1188. /// WinRar, or something else - to formally specify in the zip file which
  1189. /// codepage has been used for the entries. As a result, readers of zip files
  1190. /// are not able to inspect the zip file and determine the codepage that was
  1191. /// used for the entries contained within it. It is left to the application
  1192. /// or user to determine the necessary codepage when reading zip files encoded
  1193. /// this way. In other words, if you explicitly specify the codepage when you
  1194. /// create the zipfile, you must explicitly specify the same codepage when
  1195. /// reading the zipfile.
  1196. /// </para>
  1197. ///
  1198. /// <para>
  1199. /// The way you specify the code page to use when reading a zip file varies
  1200. /// depending on the tool or library you use to read the zip. In DotNetZip,
  1201. /// you use a ZipFile.Read() method that accepts an encoding parameter. It
  1202. /// isn't possible with Windows Explorer, as far as I know, to specify an
  1203. /// explicit codepage to use when reading a zip. If you use an incorrect
  1204. /// codepage when reading a zipfile, you will get entries with filenames that
  1205. /// are incorrect, and the incorrect filenames may even contain characters
  1206. /// that are not legal for use within filenames in Windows. Extracting entries
  1207. /// with illegal characters in the filenames will lead to exceptions. It's too
  1208. /// bad, but this is just the way things are with code pages in zip
  1209. /// files. Caveat Emptor.
  1210. /// </para>
  1211. ///
  1212. /// <para>
  1213. /// Example: Suppose you create a zipfile that contains entries with
  1214. /// filenames that have Danish characters. If you use <see
  1215. /// cref="ProvisionalAlternateEncoding" /> equal to "iso-8859-1" (cp 28591),
  1216. /// the filenames will be correctly encoded in the zip. But, to read that
  1217. /// zipfile correctly, you have to specify the same codepage at the time you
  1218. /// read it. If try to read that zip file with Windows Explorer or another
  1219. /// application that is not flexible with respect to the codepage used to
  1220. /// decode filenames in zipfiles, you will get a filename like "Inf°.txt".
  1221. /// </para>
  1222. ///
  1223. /// <para>
  1224. /// When using DotNetZip to read a zip archive, and the zip archive uses an
  1225. /// arbitrary code page, you must specify the encoding to use before or when
  1226. /// the <c>Zipfile</c> is READ. This means you must use a <c>ZipFile.Read()</c>
  1227. /// method that allows you to specify a System.Text.Encoding parameter. Setting
  1228. /// the ProvisionalAlternateEncoding property after your application has read in
  1229. /// the zip archive will not affect the entry names of entries that have already
  1230. /// been read in.
  1231. /// </para>
  1232. ///
  1233. /// <para>
  1234. /// And now, the exception to the rule described above. One strategy for
  1235. /// specifying the code page for a given zip file is to describe the code page
  1236. /// in a human-readable form in the Zip comment. For example, the comment may
  1237. /// read "Entries in this archive are encoded in the Big5 code page". For
  1238. /// maximum interoperability, the zip comment in this case should be encoded
  1239. /// in the default, IBM437 code page. In this case, the zip comment is
  1240. /// encoded using a different page than the filenames. To do this, Specify
  1241. /// <c>ProvisionalAlternateEncoding</c> to your desired region-specific code
  1242. /// page, once before adding any entries, and then reset
  1243. /// <c>ProvisionalAlternateEncoding</c> to IBM437 before setting the <see
  1244. /// cref="Comment"/> property and calling Save().
  1245. /// </para>
  1246. /// </remarks>
  1247. ///
  1248. /// <example>
  1249. /// This example shows how to read a zip file using the Big-5 Chinese code page
  1250. /// (950), and extract each entry in the zip file. For this code to work as
  1251. /// desired, the <c>Zipfile</c> must have been created using the big5 code page
  1252. /// (CP950). This is typical, for example, when using WinRar on a machine with
  1253. /// CP950 set as the default code page. In that case, the names of entries
  1254. /// within the Zip archive will be stored in that code page, and reading the zip
  1255. /// archive must be done using that code page. If the application did not use
  1256. /// the correct code page in <c>ZipFile.Read()</c>, then names of entries within the
  1257. /// zip archive would not be correctly retrieved.
  1258. /// <code>
  1259. /// using (var zip = ZipFile.Read(zipFileName, System.Text.Encoding.GetEncoding("big5")))
  1260. /// {
  1261. /// // retrieve and extract an entry using a name encoded with CP950
  1262. /// zip[MyDesiredEntry].Extract("unpack");
  1263. /// }
  1264. /// </code>
  1265. ///
  1266. /// <code lang="VB">
  1267. /// Using zip As ZipFile = ZipFile.Read(ZipToExtract, System.Text.Encoding.GetEncoding("big5"))
  1268. /// ' retrieve and extract an entry using a name encoded with CP950
  1269. /// zip(MyDesiredEntry).Extract("unpack")
  1270. /// End Using
  1271. /// </code>
  1272. /// </example>
  1273. ///
  1274. /// <seealso cref="Ionic.Zip.ZipFile.DefaultEncoding">DefaultEncoding</seealso>
  1275. [Obsolete("use AlternateEncoding instead.")]
  1276. public System.Text.Encoding ProvisionalAlternateEncoding
  1277. {
  1278. get
  1279. {
  1280. if (_alternateEncodingUsage == ZipOption.AsNecessary)
  1281. return _alternateEncoding;
  1282. return null;
  1283. }
  1284. set
  1285. {
  1286. _alternateEncoding = value;
  1287. _alternateEncodingUsage = ZipOption.AsNecessary;
  1288. }
  1289. }
  1290. /// <summary>
  1291. /// A Text Encoding to use when encoding the filenames and comments for
  1292. /// all the ZipEntry items, during a ZipFile.Save() operation.
  1293. /// </summary>
  1294. /// <remarks>
  1295. /// <para>
  1296. /// Whether the encoding specified here is used during the save depends
  1297. /// on <see cref="AlternateEncodingUsage"/>.
  1298. /// </para>
  1299. /// </remarks>
  1300. public System.Text.Encoding AlternateEncoding
  1301. {
  1302. get
  1303. {
  1304. return _alternateEncoding;
  1305. }
  1306. set
  1307. {
  1308. _alternateEncoding = value;
  1309. }
  1310. }
  1311. /// <summary>
  1312. /// A flag that tells if and when this instance should apply
  1313. /// AlternateEncoding to encode the filenames and comments associated to
  1314. /// of ZipEntry objects contained within this instance.
  1315. /// </summary>
  1316. public ZipOption AlternateEncodingUsage
  1317. {
  1318. get
  1319. {
  1320. return _alternateEncodingUsage;
  1321. }
  1322. set
  1323. {
  1324. _alternateEncodingUsage = value;
  1325. }
  1326. }
  1327. /// <summary>
  1328. /// Gets or sets the <c>TextWriter</c> to which status messages are delivered
  1329. /// for the instance.
  1330. /// </summary>
  1331. ///
  1332. /// <remarks>
  1333. /// If the TextWriter is set to a non-null value, then verbose output is sent
  1334. /// to the <c>TextWriter</c> during <c>Add</c><c>, Read</c><c>, Save</c> and
  1335. /// <c>Extract</c> operations. Typically, console applications might use
  1336. /// <c>Console.Out</c> and graphical or headless applications might use a
  1337. /// <c>System.IO.StringWriter</c>. The output of this is suitable for viewing
  1338. /// by humans.
  1339. /// </remarks>
  1340. ///
  1341. /// <example>
  1342. /// <para>
  1343. /// In this example, a console application instantiates a <c>ZipFile</c>, then
  1344. /// sets the <c>StatusMessageTextWriter</c> to <c>Console.Out</c>. At that
  1345. /// point, all verbose status messages for that <c>ZipFile</c> are sent to the
  1346. /// console.
  1347. /// </para>
  1348. ///
  1349. /// <code lang="C#">
  1350. /// using (ZipFile zip= ZipFile.Read(FilePath))
  1351. /// {
  1352. /// zip.StatusMessageTextWriter= System.Console.Out;
  1353. /// // messages are sent to the console during extraction
  1354. /// zip.ExtractAll();
  1355. /// }
  1356. /// </code>
  1357. ///
  1358. /// <code lang="VB">
  1359. /// Using zip As ZipFile = ZipFile.Read(FilePath)
  1360. /// zip.StatusMessageTextWriter= System.Console.Out
  1361. /// 'Status Messages will be sent to the console during extraction
  1362. /// zip.ExtractAll()
  1363. /// End Using
  1364. /// </code>
  1365. ///
  1366. /// <para>
  1367. /// In this example, a Windows Forms application instantiates a
  1368. /// <c>ZipFile</c>, then sets the <c>StatusMessageTextWriter</c> to a
  1369. /// <c>StringWriter</c>. At that point, all verbose status messages for that
  1370. /// <c>ZipFile</c> are sent to the <c>StringWriter</c>.
  1371. /// </para>
  1372. ///
  1373. /// <code lang="C#">
  1374. /// var sw = new System.IO.StringWriter();
  1375. /// using (ZipFile zip= ZipFile.Read(FilePath))
  1376. /// {
  1377. /// zip.StatusMessageTextWriter= sw;
  1378. /// zip.ExtractAll();
  1379. /// }
  1380. /// Console.WriteLine("{0}", sw.ToString());
  1381. /// </code>
  1382. ///
  1383. /// <code lang="VB">
  1384. /// Dim sw as New System.IO.StringWriter
  1385. /// Using zip As ZipFile = ZipFile.Read(FilePath)
  1386. /// zip.StatusMessageTextWriter= sw
  1387. /// zip.ExtractAll()
  1388. /// End Using
  1389. /// 'Status Messages are now available in sw
  1390. ///
  1391. /// </code>
  1392. /// </example>
  1393. public TextWriter StatusMessageTextWriter
  1394. {
  1395. get { return _StatusMessageTextWriter; }
  1396. set { _StatusMessageTextWriter = value; }
  1397. }
  1398. /// <summary>
  1399. /// Gets or sets the name for the folder to store the temporary file
  1400. /// this library writes when saving a zip archive.
  1401. /// </summary>
  1402. ///
  1403. /// <remarks>
  1404. /// <para>
  1405. /// This library will create a temporary file when saving a Zip archive to a
  1406. /// file. This file is written when calling one of the <c>Save()</c> methods
  1407. /// that does not save to a stream, or one of the <c>SaveSelfExtractor()</c>
  1408. /// methods.
  1409. /// </para>
  1410. ///
  1411. /// <para>
  1412. /// By default, the library will create the temporary file in the directory
  1413. /// specified for the file itself, via the <see cref="Name"/> property or via
  1414. /// the <see cref="ZipFile.Save(String)"/> method.
  1415. /// </para>
  1416. ///
  1417. /// <para>
  1418. /// Setting this property allows applications to override this default
  1419. /// behavior, so that the library will create the temporary file in the
  1420. /// specified folder. For example, to have the library create the temporary
  1421. /// file in the current working directory, regardless where the <c>ZipFile</c>
  1422. /// is saved, specfy ".". To revert to the default behavior, set this
  1423. /// property to <c>null</c> (<c>Nothing</c> in VB).
  1424. /// </para>
  1425. ///
  1426. /// <para>
  1427. /// When setting the property to a non-null value, the folder specified must
  1428. /// exist; if it does not an exception is thrown. The application should have
  1429. /// write and delete permissions on the folder. The permissions are not
  1430. /// explicitly checked ahead of time; if the application does not have the
  1431. /// appropriate rights, an exception will be thrown at the time <c>Save()</c>
  1432. /// is called.
  1433. /// </para>
  1434. ///
  1435. /// <para>
  1436. /// There is no temporary file created when reading a zip archive. When
  1437. /// saving to a Stream, there is no temporary file created. For example, if
  1438. /// the application is an ASP.NET application and calls <c>Save()</c>
  1439. /// specifying the <c>Response.OutputStream</c> as the output stream, there is
  1440. /// no temporary file created.
  1441. /// </para>
  1442. /// </remarks>
  1443. ///
  1444. /// <exception cref="System.IO.FileNotFoundException">
  1445. /// Thrown when setting the property if the directory does not exist.
  1446. /// </exception>
  1447. ///
  1448. public String TempFileFolder
  1449. {
  1450. get { return _TempFileFolder; }
  1451. set
  1452. {
  1453. _TempFileFolder = value;
  1454. if (value == null) return;
  1455. if (!Directory.Exists(value))
  1456. throw new FileNotFoundException(String.Format("That directory ({0}) does not exist.", value));
  1457. }
  1458. }
  1459. /// <summary>
  1460. /// Sets the password to be used on the <c>ZipFile</c> instance.
  1461. /// </summary>
  1462. ///
  1463. /// <remarks>
  1464. ///
  1465. /// <para>
  1466. /// When writing a zip archive, this password is applied to the entries, not
  1467. /// to the zip archive itself. It applies to any <c>ZipEntry</c> subsequently
  1468. /// added to the <c>ZipFile</c>, using one of the <c>AddFile</c>,
  1469. /// <c>AddDirectory</c>, <c>AddEntry</c>, or <c>AddItem</c> methods, etc.
  1470. /// When reading a zip archive, this property applies to any entry
  1471. /// subsequently extracted from the <c>ZipFile</c> using one of the Extract
  1472. /// methods on the <c>ZipFile</c> class.
  1473. /// </para>
  1474. ///
  1475. /// <para>
  1476. /// When writing a zip archive, keep this in mind: though the password is set
  1477. /// on the ZipFile object, according to the Zip spec, the "directory" of the
  1478. /// archive - in other words the list of entries or files contained in the archive - is
  1479. /// not encrypted with the password, or protected in any way. If you set the
  1480. /// Password property, the password actually applies to individual entries
  1481. /// that are added to the archive, subsequent to the setting of this property.
  1482. /// The list of filenames in the archive that is eventually created will
  1483. /// appear in clear text, but the contents of the individual files are
  1484. /// encrypted. This is how Zip encryption works.
  1485. /// </para>
  1486. ///
  1487. /// <para>
  1488. /// One simple way around this limitation is to simply double-wrap sensitive
  1489. /// filenames: Store the files in a zip file, and then store that zip file
  1490. /// within a second, "outer" zip file. If you apply a password to the outer
  1491. /// zip file, then readers will be able to see that the outer zip file
  1492. /// contains an inner zip file. But readers will not be able to read the
  1493. /// directory or file list of the inner zip file.
  1494. /// </para>
  1495. ///
  1496. /// <para>
  1497. /// If you set the password on the <c>ZipFile</c>, and then add a set of files
  1498. /// to the archive, then each entry is encrypted with that password. You may
  1499. /// also want to change the password between adding different entries. If you
  1500. /// set the password, add an entry, then set the password to <c>null</c>
  1501. /// (<c>Nothing</c> in VB), and add another entry, the first entry is
  1502. /// encrypted and the second is not. If you call <c>AddFile()</c>, then set
  1503. /// the <c>Password</c> property, then call <c>ZipFile.Save</c>, the file
  1504. /// added will not be password-protected, and no warning will be generated.
  1505. /// </para>
  1506. ///
  1507. /// <para>
  1508. /// When setting the Password, you may also want to explicitly set the <see
  1509. /// cref="Encryption"/> property, to specify how to encrypt the entries added
  1510. /// to the ZipFile. If you set the Password to a non-null value and do not
  1511. /// set <see cref="Encryption"/>, then PKZip 2.0 ("Weak") encryption is used.
  1512. /// This encryption is relatively weak but is very interoperable. If you set
  1513. /// the password to a <c>null</c> value (<c>Nothing</c> in VB), Encryption is
  1514. /// reset to None.
  1515. /// </para>
  1516. ///
  1517. /// <para>
  1518. /// All of the preceding applies to writing zip archives, in other words when
  1519. /// you use one of the Save methods. To use this property when reading or an
  1520. /// existing ZipFile, do the following: set the Password property on the
  1521. /// <c>ZipFile</c>, then call one of the Extract() overloads on the <see
  1522. /// cref="ZipEntry" />. In this case, the entry is extracted using the
  1523. /// <c>Password</c> that is specified on the <c>ZipFile</c> instance. If you
  1524. /// have not set the <c>Password</c> property, then the password is
  1525. /// <c>null</c>, and the entry is extracted with no password.
  1526. /// </para>
  1527. ///
  1528. /// <para>
  1529. /// If you set the Password property on the <c>ZipFile</c>, then call
  1530. /// <c>Extract()</c> an entry that has not been encrypted with a password, the
  1531. /// password is not used for that entry, and the <c>ZipEntry</c> is extracted
  1532. /// as normal. In other words, the password is used only if necessary.
  1533. /// </para>
  1534. ///
  1535. /// <para>
  1536. /// The <see cref="ZipEntry"/> class also has a <see
  1537. /// cref="ZipEntry.Password">Password</see> property. It takes precedence
  1538. /// over this property on the <c>ZipFile</c>. Typically, you would use the
  1539. /// per-entry Password when most entries in the zip archive use one password,
  1540. /// and a few entries use a different password. If all entries in the zip
  1541. /// file use the same password, then it is simpler to just set this property
  1542. /// on the <c>ZipFile</c> itself, whether creating a zip archive or extracting
  1543. /// a zip archive.
  1544. /// </para>
  1545. ///
  1546. /// </remarks>
  1547. ///
  1548. /// <example>
  1549. /// <para>
  1550. /// This example creates a zip file, using password protection for the
  1551. /// entries, and then extracts the entries from the zip file. When creating
  1552. /// the zip file, the Readme.txt file is not protected with a password, but
  1553. /// the other two are password-protected as they are saved. During extraction,
  1554. /// each file is extracted with the appropriate password.
  1555. /// </para>
  1556. /// <code>
  1557. /// // create a file with encryption
  1558. /// using (ZipFile zip = new ZipFile())
  1559. /// {
  1560. /// zip.AddFile("ReadMe.txt");
  1561. /// zip.Password= "!Secret1";
  1562. /// zip.AddFile("MapToTheSite-7440-N49th.png");
  1563. /// zip.AddFile("2008-Regional-Sales-Report.pdf");
  1564. /// zip.Save("EncryptedArchive.zip");
  1565. /// }
  1566. ///
  1567. /// // extract entries that use encryption
  1568. /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
  1569. /// {
  1570. /// zip.Password= "!Secret1";
  1571. /// zip.ExtractAll("extractDir");
  1572. /// }
  1573. ///
  1574. /// </code>
  1575. ///
  1576. /// <code lang="VB">
  1577. /// Using zip As New ZipFile
  1578. /// zip.AddFile("ReadMe.txt")
  1579. /// zip.Password = "123456!"
  1580. /// zip.AddFile("MapToTheSite-7440-N49th.png")
  1581. /// zip.Password= "!Secret1";
  1582. /// zip.AddFile("2008-Regional-Sales-Report.pdf")
  1583. /// zip.Save("EncryptedArchive.zip")
  1584. /// End Using
  1585. ///
  1586. ///
  1587. /// ' extract entries that use encryption
  1588. /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
  1589. /// zip.Password= "!Secret1"
  1590. /// zip.ExtractAll("extractDir")
  1591. /// End Using
  1592. ///
  1593. /// </code>
  1594. ///
  1595. /// </example>
  1596. ///
  1597. /// <seealso cref="Ionic.Zip.ZipFile.Encryption">ZipFile.Encryption</seealso>
  1598. /// <seealso cref="Ionic.Zip.ZipEntry.Password">ZipEntry.Password</seealso>
  1599. public String Password
  1600. {
  1601. set
  1602. {
  1603. _Password = value;
  1604. if (_Password == null)
  1605. {
  1606. Encryption = EncryptionAlgorithm.None;
  1607. }
  1608. else if (Encryption == EncryptionAlgorithm.None)
  1609. {
  1610. Encryption = EncryptionAlgorithm.PkzipWeak;
  1611. }
  1612. }
  1613. private get
  1614. {
  1615. return _Password;
  1616. }
  1617. }
  1618. /// <summary>
  1619. /// The action the library should take when extracting a file that already
  1620. /// exists.
  1621. /// </summary>
  1622. ///
  1623. /// <remarks>
  1624. /// <para>
  1625. /// This property affects the behavior of the Extract methods (one of the
  1626. /// <c>Extract()</c> or <c>ExtractWithPassword()</c> overloads), when
  1627. /// extraction would would overwrite an existing filesystem file. If you do
  1628. /// not set this property, the library throws an exception when extracting an
  1629. /// entry would overwrite an existing file.
  1630. /// </para>
  1631. ///
  1632. /// <para>
  1633. /// This property has no effect when extracting to a stream, or when the file
  1634. /// to be extracted does not already exist.
  1635. /// </para>
  1636. /// </remarks>
  1637. /// <seealso cref="Ionic.Zip.ZipEntry.ExtractExistingFile"/>
  1638. public ExtractExistingFileAction ExtractExistingFile
  1639. {
  1640. get;
  1641. set;
  1642. }
  1643. /// <summary>
  1644. /// The action the library should take when an error is encountered while
  1645. /// opening or reading files as they are saved into a zip archive.
  1646. /// </summary>
  1647. ///
  1648. /// <remarks>
  1649. /// <para>
  1650. /// Errors can occur as a file is being saved to the zip archive. For
  1651. /// example, the File.Open may fail, or a File.Read may fail, because of
  1652. /// lock conflicts or other reasons.
  1653. /// </para>
  1654. ///
  1655. /// <para>
  1656. /// The first problem might occur after having called AddDirectory() on a
  1657. /// directory that contains a Clipper .dbf file; the file is locked by
  1658. /// Clipper and cannot be opened for read by another process. An example of
  1659. /// the second problem might occur when trying to zip a .pst file that is in
  1660. /// use by Microsoft Outlook. Outlook locks a range on the file, which allows
  1661. /// other processes to open the file, but not read it in its entirety.
  1662. /// </para>
  1663. ///
  1664. /// <para>
  1665. /// This property tells DotNetZip what you would like to do in the case of
  1666. /// these errors. The primary options are: <c>ZipErrorAction.Throw</c> to
  1667. /// throw an exception (this is the default behavior if you don't set this
  1668. /// property); <c>ZipErrorAction.Skip</c> to Skip the file for which there
  1669. /// was an error and continue saving; <c>ZipErrorAction.Retry</c> to Retry
  1670. /// the entry that caused the problem; or
  1671. /// <c>ZipErrorAction.InvokeErrorEvent</c> to invoke an event handler.
  1672. /// </para>
  1673. ///
  1674. /// <para>
  1675. /// This property is implicitly set to <c>ZipErrorAction.InvokeErrorEvent</c>
  1676. /// if you add a handler to the <see cref="ZipError" /> event. If you set
  1677. /// this property to something other than
  1678. /// <c>ZipErrorAction.InvokeErrorEvent</c>, then the <c>ZipError</c>
  1679. /// event is implicitly cleared. What it means is you can set one or the
  1680. /// other (or neither), depending on what you want, but you never need to set
  1681. /// both.
  1682. /// </para>
  1683. ///
  1684. /// <para>
  1685. /// As with some other properties on the <c>ZipFile</c> class, like <see
  1686. /// cref="Password"/>, <see cref="Encryption"/>, and <see
  1687. /// cref="CompressionLevel"/>, setting this property on a <c>ZipFile</c>
  1688. /// instance will cause the specified <c>ZipErrorAction</c> to be used on all
  1689. /// <see cref="ZipEntry"/> items that are subsequently added to the
  1690. /// <c>ZipFile</c> instance. If you set this property after you have added
  1691. /// items to the <c>ZipFile</c>, but before you have called <c>Save()</c>,
  1692. /// those items will not use the specified error handling action.
  1693. /// </para>
  1694. ///
  1695. /// <para>
  1696. /// If you want to handle any errors that occur with any entry in the zip
  1697. /// file in the same way, then set this property once, before adding any
  1698. /// entries to the zip archive.
  1699. /// </para>
  1700. ///
  1701. /// <para>
  1702. /// If you set this property to <c>ZipErrorAction.Skip</c> and you'd like to
  1703. /// learn which files may have been skipped after a <c>Save()</c>, you can
  1704. /// set the <see cref="StatusMessageTextWriter" /> on the ZipFile before
  1705. /// calling <c>Save()</c>. A message will be emitted into that writer for
  1706. /// each skipped file, if any.
  1707. /// </para>
  1708. ///
  1709. /// </remarks>
  1710. ///
  1711. /// <example>
  1712. /// This example shows how to tell DotNetZip to skip any files for which an
  1713. /// error is generated during the Save().
  1714. /// <code lang="VB">
  1715. /// Public Sub SaveZipFile()
  1716. /// Dim SourceFolder As String = "fodder"
  1717. /// Dim DestFile As String = "eHandler.zip"
  1718. /// Dim sw as New StringWriter
  1719. /// Using zipArchive As ZipFile = New ZipFile
  1720. /// ' Tell DotNetZip to skip any files for which it encounters an error
  1721. /// zipArchive.ZipErrorAction = ZipErrorAction.Skip
  1722. /// zipArchive.StatusMessageTextWriter = sw
  1723. /// zipArchive.AddDirectory(SourceFolder)
  1724. /// zipArchive.Save(DestFile)
  1725. /// End Using
  1726. /// ' examine sw here to see any messages
  1727. /// End Sub
  1728. ///
  1729. /// </code>
  1730. /// </example>
  1731. ///
  1732. /// <seealso cref="Ionic.Zip.ZipEntry.ZipErrorAction"/>
  1733. /// <seealso cref="Ionic.Zip.ZipFile.ZipError"/>
  1734. public ZipErrorAction ZipErrorAction
  1735. {
  1736. get
  1737. {
  1738. if (ZipError != null)
  1739. _zipErrorAction = ZipErrorAction.InvokeErrorEvent;
  1740. return _zipErrorAction;
  1741. }
  1742. set
  1743. {
  1744. _zipErrorAction = value;
  1745. if (_zipErrorAction != ZipErrorAction.InvokeErrorEvent && ZipError != null)
  1746. ZipError = null;
  1747. }
  1748. }
  1749. /// <summary>
  1750. /// The Encryption to use for entries added to the <c>ZipFile</c>.
  1751. /// </summary>
  1752. ///
  1753. /// <remarks>
  1754. /// <para>
  1755. /// Set this when creating a zip archive, or when updating a zip archive. The
  1756. /// specified Encryption is applied to the entries subsequently added to the
  1757. /// <c>ZipFile</c> instance. Applications do not need to set the
  1758. /// <c>Encryption</c> property when reading or extracting a zip archive.
  1759. /// </para>
  1760. ///
  1761. /// <para>
  1762. /// If you set this to something other than EncryptionAlgorithm.None, you
  1763. /// will also need to set the <see cref="Password"/>.
  1764. /// </para>
  1765. ///
  1766. /// <para>
  1767. /// As with some other properties on the <c>ZipFile</c> class, like <see
  1768. /// cref="Password"/> and <see cref="CompressionLevel"/>, setting this
  1769. /// property on a <c>ZipFile</c> instance will cause the specified
  1770. /// <c>EncryptionAlgorithm</c> to be used on all <see cref="ZipEntry"/> items
  1771. /// that are subsequently added to the <c>ZipFile</c> instance. In other
  1772. /// words, if you set this property after you have added items to the
  1773. /// <c>ZipFile</c>, but before you have called <c>Save()</c>, those items will
  1774. /// not be encrypted or protected with a password in the resulting zip
  1775. /// archive. To get a zip archive with encrypted entries, set this property,
  1776. /// along with the <see cref="Password"/> property, before calling
  1777. /// <c>AddFile</c>, <c>AddItem</c>, or <c>AddDirectory</c> (etc.) on the
  1778. /// <c>ZipFile</c> instance.
  1779. /// </para>
  1780. ///
  1781. /// <para>
  1782. /// If you read a <c>ZipFile</c>, you can modify the <c>Encryption</c> on an
  1783. /// encrypted entry, only by setting the <c>Encryption</c> property on the
  1784. /// <c>ZipEntry</c> itself. Setting the <c>Encryption</c> property on the
  1785. /// <c>ZipFile</c>, once it has been created via a call to
  1786. /// <c>ZipFile.Read()</c>, does not affect entries that were previously read.
  1787. /// </para>
  1788. ///
  1789. /// <para>
  1790. /// For example, suppose you read a <c>ZipFile</c>, and there is an encrypted
  1791. /// entry. Setting the <c>Encryption</c> property on that <c>ZipFile</c> and
  1792. /// then calling <c>Save()</c> on the <c>ZipFile</c> does not update the
  1793. /// <c>Encryption</c> used for the entries in the archive. Neither is an
  1794. /// exception thrown. Instead, what happens during the <c>Save()</c> is that
  1795. /// all previously existing entries are copied through to the new zip archive,
  1796. /// with whatever encryption and password that was used when originally
  1797. /// creating the zip archive. Upon re-reading that archive, to extract
  1798. /// entries, applications should use the original password or passwords, if
  1799. /// any.
  1800. /// </para>
  1801. ///
  1802. /// <para>
  1803. /// Suppose an application reads a <c>ZipFile</c>, and there is an encrypted
  1804. /// entry. Setting the <c>Encryption</c> property on that <c>ZipFile</c> and
  1805. /// then adding new entries (via <c>AddFile()</c>, <c>AddEntry()</c>, etc)
  1806. /// and then calling <c>Save()</c> on the <c>ZipFile</c> does not update the
  1807. /// <c>Encryption</c> on any of the entries that had previously been in the
  1808. /// <c>ZipFile</c>. The <c>Encryption</c> property applies only to the
  1809. /// newly-added entries.
  1810. /// </para>
  1811. ///
  1812. /// </remarks>
  1813. ///
  1814. /// <example>
  1815. /// <para>
  1816. /// This example creates a zip archive that uses encryption, and then extracts
  1817. /// entries from the archive. When creating the zip archive, the ReadMe.txt
  1818. /// file is zipped without using a password or encryption. The other files
  1819. /// use encryption.
  1820. /// </para>
  1821. ///
  1822. /// <code>
  1823. /// // Create a zip archive with AES Encryption.
  1824. /// using (ZipFile zip = new ZipFile())
  1825. /// {
  1826. /// zip.AddFile("ReadMe.txt");
  1827. /// zip.Encryption= EncryptionAlgorithm.WinZipAes256;
  1828. /// zip.Password= "Top.Secret.No.Peeking!";
  1829. /// zip.AddFile("7440-N49th.png");
  1830. /// zip.AddFile("2008-Regional-Sales-Report.pdf");
  1831. /// zip.Save("EncryptedArchive.zip");
  1832. /// }
  1833. ///
  1834. /// // Extract a zip archive that uses AES Encryption.
  1835. /// // You do not need to specify the algorithm during extraction.
  1836. /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
  1837. /// {
  1838. /// zip.Password= "Top.Secret.No.Peeking!";
  1839. /// zip.ExtractAll("extractDirectory");
  1840. /// }
  1841. /// </code>
  1842. ///
  1843. /// <code lang="VB">
  1844. /// ' Create a zip that uses Encryption.
  1845. /// Using zip As New ZipFile()
  1846. /// zip.Encryption= EncryptionAlgorithm.WinZipAes256
  1847. /// zip.Password= "Top.Secret.No.Peeking!"
  1848. /// zip.AddFile("ReadMe.txt")
  1849. /// zip.AddFile("7440-N49th.png")
  1850. /// zip.AddFile("2008-Regional-Sales-Report.pdf")
  1851. /// zip.Save("EncryptedArchive.zip")
  1852. /// End Using
  1853. ///
  1854. /// ' Extract a zip archive that uses AES Encryption.
  1855. /// ' You do not need to specify the algorithm during extraction.
  1856. /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
  1857. /// zip.Password= "Top.Secret.No.Peeking!"
  1858. /// zip.ExtractAll("extractDirectory")
  1859. /// End Using
  1860. /// </code>
  1861. ///
  1862. /// </example>
  1863. ///
  1864. /// <seealso cref="Ionic.Zip.ZipFile.Password">ZipFile.Password</seealso>
  1865. /// <seealso cref="Ionic.Zip.ZipEntry.Encryption">ZipEntry.Encryption</seealso>
  1866. public EncryptionAlgorithm Encryption
  1867. {
  1868. get
  1869. {
  1870. return _Encryption;
  1871. }
  1872. set
  1873. {
  1874. if (value == EncryptionAlgorithm.Unsupported)
  1875. throw new InvalidOperationException("You may not set Encryption to that value.");
  1876. _Encryption = value;
  1877. }
  1878. }
  1879. /// <summary>
  1880. /// A callback that allows the application to specify the compression level
  1881. /// to use for entries subsequently added to the zip archive.
  1882. /// </summary>
  1883. ///
  1884. /// <remarks>
  1885. ///
  1886. /// <para>
  1887. /// With this callback, the DotNetZip library allows the application to
  1888. /// determine whether compression will be used, at the time of the
  1889. /// <c>Save</c>. This may be useful if the application wants to favor
  1890. /// speed over size, and wants to defer the decision until the time of
  1891. /// <c>Save</c>.
  1892. /// </para>
  1893. ///
  1894. /// <para>
  1895. /// Typically applications set the <see cref="CompressionLevel"/> property on
  1896. /// the <c>ZipFile</c> or on each <c>ZipEntry</c> to determine the level of
  1897. /// compression used. This is done at the time the entry is added to the
  1898. /// <c>ZipFile</c>. Setting the property to
  1899. /// <c>Ionic.Zlib.CompressionLevel.None</c> means no compression will be used.
  1900. /// </para>
  1901. ///
  1902. /// <para>
  1903. /// This callback allows the application to defer the decision on the
  1904. /// <c>CompressionLevel</c> to use, until the time of the call to
  1905. /// <c>ZipFile.Save()</c>. The callback is invoked once per <c>ZipEntry</c>,
  1906. /// at the time the data for the entry is being written out as part of a
  1907. /// <c>Save()</c> operation. The application can use whatever criteria it
  1908. /// likes in determining the level to return. For example, an application may
  1909. /// wish that no .mp3 files should be compressed, because they are already
  1910. /// compressed and the extra compression is not worth the CPU time incurred,
  1911. /// and so can return <c>None</c> for all .mp3 entries.
  1912. /// </para>
  1913. ///
  1914. /// <para>
  1915. /// The library determines whether compression will be attempted for an entry
  1916. /// this way: If the entry is a zero length file, or a directory, no
  1917. /// compression is used. Otherwise, if this callback is set, it is invoked
  1918. /// and the <c>CompressionLevel</c> is set to the return value. If this
  1919. /// callback has not been set, then the previously set value for
  1920. /// <c>CompressionLevel</c> is used.
  1921. /// </para>
  1922. ///
  1923. /// </remarks>
  1924. public SetCompressionCallback SetCompression
  1925. {
  1926. get;
  1927. set;
  1928. }
  1929. /// <summary>
  1930. /// The maximum size of an output segment, when saving a split Zip file.
  1931. /// </summary>
  1932. /// <remarks>
  1933. /// <para>
  1934. /// Set this to a non-zero value before calling <see cref="Save()"/> or <see
  1935. /// cref="Save(String)"/> to specify that the ZipFile should be saved as a
  1936. /// split archive, also sometimes called a spanned archive. Some also
  1937. /// call them multi-file archives.
  1938. /// </para>
  1939. ///
  1940. /// <para>
  1941. /// A split zip archive is saved in a set of discrete filesystem files,
  1942. /// rather than in a single file. This is handy when transmitting the
  1943. /// archive in email or some other mechanism that has a limit to the size of
  1944. /// each file. The first file in a split archive will be named
  1945. /// <c>basename.z01</c>, the second will be named <c>basename.z02</c>, and
  1946. /// so on. The final file is named <c>basename.zip</c>. According to the zip
  1947. /// specification from PKWare, the minimum value is 65536, for a 64k segment
  1948. /// size. The maximum number of segments allows in a split archive is 99.
  1949. /// </para>
  1950. ///
  1951. /// <para>
  1952. /// The value of this property determines the maximum size of a split
  1953. /// segment when writing a split archive. For example, suppose you have a
  1954. /// <c>ZipFile</c> that would save to a single file of 200k. If you set the
  1955. /// <c>MaxOutputSegmentSize</c> to 65536 before calling <c>Save()</c>, you
  1956. /// will get four distinct output files. On the other hand if you set this
  1957. /// property to 256k, then you will get a single-file archive for that
  1958. /// <c>ZipFile</c>.
  1959. /// </para>
  1960. ///
  1961. /// <para>
  1962. /// The size of each split output file will be as large as possible, up to
  1963. /// the maximum size set here. The zip specification requires that some data
  1964. /// fields in a zip archive may not span a split boundary, and an output
  1965. /// segment may be smaller than the maximum if necessary to avoid that
  1966. /// problem. Also, obviously the final segment of the archive may be smaller
  1967. /// than the maximum segment size. Segments will never be larger than the
  1968. /// value set with this property.
  1969. /// </para>
  1970. ///
  1971. /// <para>
  1972. /// You can save a split Zip file only when saving to a regular filesystem
  1973. /// file. It's not possible to save a split zip file as a self-extracting
  1974. /// archive, nor is it possible to save a split zip file to a stream. When
  1975. /// saving to a SFX or to a Stream, this property is ignored.
  1976. /// </para>
  1977. ///
  1978. /// <para>
  1979. /// About interoperability: Split or spanned zip files produced by DotNetZip
  1980. /// can be read by WinZip or PKZip, and vice-versa. Segmented zip files may
  1981. /// not be readable by other tools, if those other tools don't support zip
  1982. /// spanning or splitting. When in doubt, test. I don't believe Windows
  1983. /// Explorer can extract a split archive.
  1984. /// </para>
  1985. ///
  1986. /// <para>
  1987. /// This property has no effect when reading a split archive. You can read
  1988. /// a split archive in the normal way with DotNetZip.
  1989. /// </para>
  1990. ///
  1991. /// <para>
  1992. /// When saving a zip file, if you want a regular zip file rather than a
  1993. /// split zip file, don't set this property, or set it to Zero.
  1994. /// </para>
  1995. ///
  1996. /// <para>
  1997. /// If you read a split archive, with <see cref="ZipFile.Read(string)"/> and
  1998. /// then subsequently call <c>ZipFile.Save()</c>, unless you set this
  1999. /// property before calling <c>Save()</c>, you will get a normal,
  2000. /// single-file archive.
  2001. /// </para>
  2002. /// </remarks>
  2003. ///
  2004. /// <seealso cref="NumberOfSegmentsForMostRecentSave"/>
  2005. public Int32 MaxOutputSegmentSize
  2006. {
  2007. get
  2008. {
  2009. return _maxOutputSegmentSize;
  2010. }
  2011. set
  2012. {
  2013. if (value < 65536 && value != 0)
  2014. throw new ZipException("The minimum acceptable segment size is 65536.");
  2015. _maxOutputSegmentSize = value;
  2016. }
  2017. }
  2018. /// <summary>
  2019. /// Returns the number of segments used in the most recent Save() operation.
  2020. /// </summary>
  2021. /// <remarks>
  2022. /// <para>
  2023. /// This is normally zero, unless you have set the <see
  2024. /// cref="MaxOutputSegmentSize"/> property. If you have set <see
  2025. /// cref="MaxOutputSegmentSize"/>, and then you save a file, after the call to
  2026. /// Save() completes, you can read this value to learn the number of segments that
  2027. /// were created.
  2028. /// </para>
  2029. /// <para>
  2030. /// If you call Save("Archive.zip"), and it creates 5 segments, then you
  2031. /// will have filesystem files named Archive.z01, Archive.z02, Archive.z03,
  2032. /// Archive.z04, and Archive.zip, and the value of this property will be 5.
  2033. /// </para>
  2034. /// </remarks>
  2035. /// <seealso cref="MaxOutputSegmentSize"/>
  2036. public Int32 NumberOfSegmentsForMostRecentSave
  2037. {
  2038. get
  2039. {
  2040. return unchecked((Int32)_numberOfSegmentsForMostRecentSave + 1);
  2041. }
  2042. }
  2043. #if !NETCF
  2044. /// <summary>
  2045. /// The size threshold for an entry, above which a parallel deflate is used.
  2046. /// </summary>
  2047. ///
  2048. /// <remarks>
  2049. ///
  2050. /// <para>
  2051. /// DotNetZip will use multiple threads to compress any ZipEntry,
  2052. /// if the entry is larger than the given size. Zero means "always
  2053. /// use parallel deflate", while -1 means "never use parallel
  2054. /// deflate". The default value for this property is 512k. Aside
  2055. /// from the special values of 0 and 1, the minimum value is 65536.
  2056. /// </para>
  2057. ///
  2058. /// <para>
  2059. /// If the entry size cannot be known before compression, as with a
  2060. /// read-forward stream, then Parallel deflate will never be
  2061. /// performed, unless the value of this property is zero.
  2062. /// </para>
  2063. ///
  2064. /// <para>
  2065. /// A parallel deflate operations will speed up the compression of
  2066. /// large files, on computers with multiple CPUs or multiple CPU
  2067. /// cores. For files above 1mb, on a dual core or dual-cpu (2p)
  2068. /// machine, the time required to compress the file can be 70% of the
  2069. /// single-threaded deflate. For very large files on 4p machines the
  2070. /// compression can be done in 30% of the normal time. The downside
  2071. /// is that parallel deflate consumes extra memory during the deflate,
  2072. /// and the deflation is not as effective.
  2073. /// </para>
  2074. ///
  2075. /// <para>
  2076. /// Parallel deflate tends to yield slightly less compression when
  2077. /// compared to as single-threaded deflate; this is because the original
  2078. /// data stream is split into multiple independent buffers, each of which
  2079. /// is compressed in parallel. But because they are treated
  2080. /// independently, there is no opportunity to share compression
  2081. /// dictionaries. For that reason, a deflated stream may be slightly
  2082. /// larger when compressed using parallel deflate, as compared to a
  2083. /// traditional single-threaded deflate. Sometimes the increase over the
  2084. /// normal deflate is as much as 5% of the total compressed size. For
  2085. /// larger files it can be as small as 0.1%.
  2086. /// </para>
  2087. ///
  2088. /// <para>
  2089. /// Multi-threaded compression does not give as much an advantage when
  2090. /// using Encryption. This is primarily because encryption tends to slow
  2091. /// down the entire pipeline. Also, multi-threaded compression gives less
  2092. /// of an advantage when using lower compression levels, for example <see
  2093. /// cref="Ionic.Zlib.CompressionLevel.BestSpeed"/>. You may have to
  2094. /// perform some tests to determine the best approach for your situation.
  2095. /// </para>
  2096. ///
  2097. /// </remarks>
  2098. ///
  2099. /// <seealso cref="ParallelDeflateMaxBufferPairs"/>
  2100. ///
  2101. public long ParallelDeflateThreshold
  2102. {
  2103. set
  2104. {
  2105. if ((value != 0) && (value != -1) && (value < 64 * 1024))
  2106. throw new ArgumentOutOfRangeException("ParallelDeflateThreshold should be -1, 0, or > 65536");
  2107. _ParallelDeflateThreshold = value;
  2108. }
  2109. get
  2110. {
  2111. return _ParallelDeflateThreshold;
  2112. }
  2113. }
  2114. /// <summary>
  2115. /// The maximum number of buffer pairs to use when performing
  2116. /// parallel compression.
  2117. /// </summary>
  2118. ///
  2119. /// <remarks>
  2120. /// <para>
  2121. /// This property sets an upper limit on the number of memory
  2122. /// buffer pairs to create when performing parallel
  2123. /// compression. The implementation of the parallel
  2124. /// compression stream allocates multiple buffers to
  2125. /// facilitate parallel compression. As each buffer fills up,
  2126. /// the stream uses <see
  2127. /// cref="System.Threading.ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback)">
  2128. /// ThreadPool.QueueUserWorkItem()</see> to compress those
  2129. /// buffers in a background threadpool thread. After a buffer
  2130. /// is compressed, it is re-ordered and written to the output
  2131. /// stream.
  2132. /// </para>
  2133. ///
  2134. /// <para>
  2135. /// A higher number of buffer pairs enables a higher degree of
  2136. /// parallelism, which tends to increase the speed of compression on
  2137. /// multi-cpu computers. On the other hand, a higher number of buffer
  2138. /// pairs also implies a larger memory consumption, more active worker
  2139. /// threads, and a higher cpu utilization for any compression. This
  2140. /// property enables the application to limit its memory consumption and
  2141. /// CPU utilization behavior depending on requirements.
  2142. /// </para>
  2143. ///
  2144. /// <para>
  2145. /// For each compression "task" that occurs in parallel, there are 2
  2146. /// buffers allocated: one for input and one for output. This property
  2147. /// sets a limit for the number of pairs. The total amount of storage
  2148. /// space allocated for buffering will then be (N*S*2), where N is the
  2149. /// number of buffer pairs, S is the size of each buffer (<see
  2150. /// cref="BufferSize"/>). By default, DotNetZip allocates 4 buffer
  2151. /// pairs per CPU core, so if your machine has 4 cores, and you retain
  2152. /// the default buffer size of 128k, then the
  2153. /// ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer
  2154. /// memory in total, or 4mb, in blocks of 128kb. If you then set this
  2155. /// property to 8, then the number will be 8 * 2 * 128kb of buffer
  2156. /// memory, or 2mb.
  2157. /// </para>
  2158. ///
  2159. /// <para>
  2160. /// CPU utilization will also go up with additional buffers, because a
  2161. /// larger number of buffer pairs allows a larger number of background
  2162. /// threads to compress in parallel. If you find that parallel
  2163. /// compression is consuming too much memory or CPU, you can adjust this
  2164. /// value downward.
  2165. /// </para>
  2166. ///
  2167. /// <para>
  2168. /// The default value is 16. Different values may deliver better or
  2169. /// worse results, depending on your priorities and the dynamic
  2170. /// performance characteristics of your storage and compute resources.
  2171. /// </para>
  2172. ///
  2173. /// <para>
  2174. /// This property is not the number of buffer pairs to use; it is an
  2175. /// upper limit. An illustration: Suppose you have an application that
  2176. /// uses the default value of this property (which is 16), and it runs
  2177. /// on a machine with 2 CPU cores. In that case, DotNetZip will allocate
  2178. /// 4 buffer pairs per CPU core, for a total of 8 pairs. The upper
  2179. /// limit specified by this property has no effect.
  2180. /// </para>
  2181. ///
  2182. /// <para>
  2183. /// The application can set this value at any time
  2184. /// before calling <c>ZipFile.Save()</c>.
  2185. /// </para>
  2186. /// </remarks>
  2187. ///
  2188. /// <seealso cref="ParallelDeflateThreshold"/>
  2189. ///
  2190. public int ParallelDeflateMaxBufferPairs
  2191. {
  2192. get
  2193. {
  2194. return _maxBufferPairs;
  2195. }
  2196. set
  2197. {
  2198. if (value < 4)
  2199. throw new ArgumentOutOfRangeException("ParallelDeflateMaxBufferPairs",
  2200. "Value must be 4 or greater.");
  2201. _maxBufferPairs = value;
  2202. }
  2203. }
  2204. #endif
  2205. /// <summary>Provides a string representation of the instance.</summary>
  2206. /// <returns>a string representation of the instance.</returns>
  2207. public override String ToString()
  2208. {
  2209. return String.Format("ZipFile::{0}", Name);
  2210. }
  2211. /// <summary>
  2212. /// Returns the version number on the DotNetZip assembly.
  2213. /// </summary>
  2214. ///
  2215. /// <remarks>
  2216. /// <para>
  2217. /// This property is exposed as a convenience. Callers could also get the
  2218. /// version value by retrieving GetName().Version on the
  2219. /// System.Reflection.Assembly object pointing to the DotNetZip
  2220. /// assembly. But sometimes it is not clear which assembly is being loaded.
  2221. /// This property makes it clear.
  2222. /// </para>
  2223. /// <para>
  2224. /// This static property is primarily useful for diagnostic purposes.
  2225. /// </para>
  2226. /// </remarks>
  2227. public static System.Version LibraryVersion
  2228. {
  2229. get
  2230. {
  2231. return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
  2232. }
  2233. }
  2234. internal void NotifyEntryChanged()
  2235. {
  2236. _contentsChanged = true;
  2237. }
  2238. internal Stream StreamForDiskNumber(uint diskNumber)
  2239. {
  2240. if (diskNumber + 1 == this._diskNumberWithCd ||
  2241. (diskNumber == 0 && this._diskNumberWithCd == 0))
  2242. {
  2243. //return (this.ReadStream as FileStream);
  2244. return this.ReadStream;
  2245. }
  2246. return ZipSegmentedStream.ForReading(this._readName ?? this._name,
  2247. diskNumber, _diskNumberWithCd);
  2248. }
  2249. // called by ZipEntry in ZipEntry.Extract(), when there is no stream set for the
  2250. // ZipEntry.
  2251. internal void Reset(bool whileSaving)
  2252. {
  2253. if (_JustSaved)
  2254. {
  2255. // read in the just-saved zip archive
  2256. using (ZipFile x = new ZipFile())
  2257. {
  2258. if (File.Exists(this._readName ?? this._name))
  2259. {
  2260. // workitem 10735
  2261. x._readName = x._name = whileSaving
  2262. ? (this._readName ?? this._name)
  2263. : this._name;
  2264. }
  2265. else // if we just saved to a stream no file is available to read from
  2266. {
  2267. if (_readstream.CanSeek)
  2268. _readstream.Seek(0, SeekOrigin.Begin);
  2269. x._readstream = _readstream;
  2270. }
  2271. x.AlternateEncoding = this.AlternateEncoding;
  2272. x.AlternateEncodingUsage = this.AlternateEncodingUsage;
  2273. ReadIntoInstance(x);
  2274. // copy the contents of the entries.
  2275. // cannot just replace the entries - the app may be holding them
  2276. foreach (ZipEntry e1 in x)
  2277. {
  2278. foreach (ZipEntry e2 in this)
  2279. {
  2280. if (e1.FileName == e2.FileName)
  2281. {
  2282. if (!e2.IsChanged)
  2283. e2.CopyMetaData(e1);
  2284. break;
  2285. }
  2286. }
  2287. }
  2288. }
  2289. _JustSaved = false;
  2290. }
  2291. }
  2292. #endregion
  2293. #region Constructors
  2294. /// <summary>
  2295. /// Creates a new <c>ZipFile</c> instance, using the specified filename.
  2296. /// </summary>
  2297. ///
  2298. /// <remarks>
  2299. /// <para>
  2300. /// Applications can use this constructor to create a new ZipFile for writing,
  2301. /// or to slurp in an existing zip archive for read and update purposes.
  2302. /// </para>
  2303. ///
  2304. /// <para>
  2305. /// To create a new zip archive, an application can call this constructor,
  2306. /// passing the name of a file that does not exist. The name may be a fully
  2307. /// qualified path. Then the application can add directories or files to the
  2308. /// <c>ZipFile</c> via <c>AddDirectory()</c>, <c>AddFile()</c>, <c>AddItem()</c>
  2309. /// and then write the zip archive to the disk by calling <c>Save()</c>. The
  2310. /// zip file is not actually opened and written to the disk until the
  2311. /// application calls <c>ZipFile.Save()</c>. At that point the new zip file
  2312. /// with the given name is created.
  2313. /// </para>
  2314. ///
  2315. /// <para>
  2316. /// If you won't know the name of the <c>Zipfile</c> until the time you call
  2317. /// <c>ZipFile.Save()</c>, or if you plan to save to a stream (which has no
  2318. /// name), then you should use the no-argument constructor.
  2319. /// </para>
  2320. ///
  2321. /// <para>
  2322. /// The application can also call this constructor to read an existing zip
  2323. /// archive. passing the name of a valid zip file that does exist. But, it's
  2324. /// better form to use the static <see cref="ZipFile.Read(String)"/> method,
  2325. /// passing the name of the zip file, because using <c>ZipFile.Read()</c> in
  2326. /// your code communicates very clearly what you are doing. In either case,
  2327. /// the file is then read into the <c>ZipFile</c> instance. The app can then
  2328. /// enumerate the entries or can modify the zip file, for example adding
  2329. /// entries, removing entries, changing comments, and so on.
  2330. /// </para>
  2331. ///
  2332. /// <para>
  2333. /// One advantage to this parameterized constructor: it allows applications to
  2334. /// use the same code to add items to a zip archive, regardless of whether the
  2335. /// zip file exists.
  2336. /// </para>
  2337. ///
  2338. /// <para>
  2339. /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
  2340. /// not party on a single instance with multiple threads. You may have
  2341. /// multiple threads that each use a distinct <c>ZipFile</c> instance, or you
  2342. /// can synchronize multi-thread access to a single instance.
  2343. /// </para>
  2344. ///
  2345. /// <para>
  2346. /// By the way, since DotNetZip is so easy to use, don't you think <see
  2347. /// href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">you should
  2348. /// donate $5 or $10</see>?
  2349. /// </para>
  2350. ///
  2351. /// </remarks>
  2352. ///
  2353. /// <exception cref="Ionic.Zip.ZipException">
  2354. /// Thrown if name refers to an existing file that is not a valid zip file.
  2355. /// </exception>
  2356. ///
  2357. /// <example>
  2358. /// This example shows how to create a zipfile, and add a few files into it.
  2359. /// <code>
  2360. /// String ZipFileToCreate = "archive1.zip";
  2361. /// String DirectoryToZip = "c:\\reports";
  2362. /// using (ZipFile zip = new ZipFile())
  2363. /// {
  2364. /// // Store all files found in the top level directory, into the zip archive.
  2365. /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
  2366. /// zip.AddFiles(filenames, "files");
  2367. /// zip.Save(ZipFileToCreate);
  2368. /// }
  2369. /// </code>
  2370. ///
  2371. /// <code lang="VB">
  2372. /// Dim ZipFileToCreate As String = "archive1.zip"
  2373. /// Dim DirectoryToZip As String = "c:\reports"
  2374. /// Using zip As ZipFile = New ZipFile()
  2375. /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
  2376. /// zip.AddFiles(filenames, "files")
  2377. /// zip.Save(ZipFileToCreate)
  2378. /// End Using
  2379. /// </code>
  2380. /// </example>
  2381. ///
  2382. /// <param name="fileName">The filename to use for the new zip archive.</param>
  2383. ///
  2384. public ZipFile(string fileName)
  2385. {
  2386. if (DefaultEncoding == null)
  2387. {
  2388. _alternateEncoding = System.Text.Encoding.UTF8;
  2389. AlternateEncodingUsage = ZipOption.Always;
  2390. }
  2391. else
  2392. {
  2393. _alternateEncoding = DefaultEncoding;
  2394. }
  2395. try
  2396. {
  2397. _InitInstance(fileName, null);
  2398. }
  2399. catch (Exception e1)
  2400. {
  2401. throw new ZipException(String.Format("Could not read {0} as a zip file", fileName), e1);
  2402. }
  2403. }
  2404. /// <summary>
  2405. /// Creates a new <c>ZipFile</c> instance, using the specified name for the
  2406. /// filename, and the specified Encoding.
  2407. /// </summary>
  2408. ///
  2409. /// <remarks>
  2410. /// <para>
  2411. /// See the documentation on the <see cref="ZipFile(String)">ZipFile
  2412. /// constructor that accepts a single string argument</see> for basic
  2413. /// information on all the <c>ZipFile</c> constructors.
  2414. /// </para>
  2415. ///
  2416. /// <para>
  2417. /// The Encoding is used as the default alternate encoding for entries with
  2418. /// filenames or comments that cannot be encoded with the IBM437 code page.
  2419. /// This is equivalent to setting the <see
  2420. /// cref="ProvisionalAlternateEncoding"/> property on the <c>ZipFile</c>
  2421. /// instance after construction.
  2422. /// </para>
  2423. ///
  2424. /// <para>
  2425. /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
  2426. /// not party on a single instance with multiple threads. You may have
  2427. /// multiple threads that each use a distinct <c>ZipFile</c> instance, or you
  2428. /// can synchronize multi-thread access to a single instance.
  2429. /// </para>
  2430. ///
  2431. /// </remarks>
  2432. ///
  2433. /// <exception cref="Ionic.Zip.ZipException">
  2434. /// Thrown if name refers to an existing file that is not a valid zip file.
  2435. /// </exception>
  2436. ///
  2437. /// <param name="fileName">The filename to use for the new zip archive.</param>
  2438. /// <param name="encoding">The Encoding is used as the default alternate
  2439. /// encoding for entries with filenames or comments that cannot be encoded
  2440. /// with the IBM437 code page. </param>
  2441. public ZipFile(string fileName, System.Text.Encoding encoding)
  2442. {
  2443. try
  2444. {
  2445. AlternateEncoding = encoding;
  2446. AlternateEncodingUsage = ZipOption.Always;
  2447. _InitInstance(fileName, null);
  2448. }
  2449. catch (Exception e1)
  2450. {
  2451. throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
  2452. }
  2453. }
  2454. /// <summary>
  2455. /// Create a zip file, without specifying a target filename or stream to save to.
  2456. /// </summary>
  2457. ///
  2458. /// <remarks>
  2459. /// <para>
  2460. /// See the documentation on the <see cref="ZipFile(String)">ZipFile
  2461. /// constructor that accepts a single string argument</see> for basic
  2462. /// information on all the <c>ZipFile</c> constructors.
  2463. /// </para>
  2464. ///
  2465. /// <para>
  2466. /// After instantiating with this constructor and adding entries to the
  2467. /// archive, the application should call <see cref="ZipFile.Save(String)"/> or
  2468. /// <see cref="ZipFile.Save(System.IO.Stream)"/> to save to a file or a
  2469. /// stream, respectively. The application can also set the <see cref="Name"/>
  2470. /// property and then call the no-argument <see cref="Save()"/> method. (This
  2471. /// is the preferred approach for applications that use the library through
  2472. /// COM interop.) If you call the no-argument <see cref="Save()"/> method
  2473. /// without having set the <c>Name</c> of the <c>ZipFile</c>, either through
  2474. /// the parameterized constructor or through the explicit property , the
  2475. /// Save() will throw, because there is no place to save the file. </para>
  2476. ///
  2477. /// <para>
  2478. /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
  2479. /// have multiple threads that each use a distinct <c>ZipFile</c> instance, or
  2480. /// you can synchronize multi-thread access to a single instance. </para>
  2481. ///
  2482. /// </remarks>
  2483. ///
  2484. /// <example>
  2485. /// This example creates a Zip archive called Backup.zip, containing all the files
  2486. /// in the directory DirectoryToZip. Files within subdirectories are not zipped up.
  2487. /// <code>
  2488. /// using (ZipFile zip = new ZipFile())
  2489. /// {
  2490. /// // Store all files found in the top level directory, into the zip archive.
  2491. /// // note: this code does not recurse subdirectories!
  2492. /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
  2493. /// zip.AddFiles(filenames, "files");
  2494. /// zip.Save("Backup.zip");
  2495. /// }
  2496. /// </code>
  2497. ///
  2498. /// <code lang="VB">
  2499. /// Using zip As New ZipFile
  2500. /// ' Store all files found in the top level directory, into the zip archive.
  2501. /// ' note: this code does not recurse subdirectories!
  2502. /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
  2503. /// zip.AddFiles(filenames, "files")
  2504. /// zip.Save("Backup.zip")
  2505. /// End Using
  2506. /// </code>
  2507. /// </example>
  2508. public ZipFile()
  2509. {
  2510. if (DefaultEncoding == null)
  2511. {
  2512. _alternateEncoding = System.Text.Encoding.UTF8;
  2513. AlternateEncodingUsage = ZipOption.Always;
  2514. }
  2515. else
  2516. {
  2517. _alternateEncoding = DefaultEncoding;
  2518. }
  2519. _InitInstance(null, null);
  2520. }
  2521. /// <summary>
  2522. /// Create a zip file, specifying a text Encoding, but without specifying a
  2523. /// target filename or stream to save to.
  2524. /// </summary>
  2525. ///
  2526. /// <remarks>
  2527. /// <para>
  2528. /// See the documentation on the <see cref="ZipFile(String)">ZipFile
  2529. /// constructor that accepts a single string argument</see> for basic
  2530. /// information on all the <c>ZipFile</c> constructors.
  2531. /// </para>
  2532. ///
  2533. /// </remarks>
  2534. ///
  2535. /// <param name="encoding">
  2536. /// The Encoding is used as the default alternate encoding for entries with
  2537. /// filenames or comments that cannot be encoded with the IBM437 code page.
  2538. /// </param>
  2539. public ZipFile(System.Text.Encoding encoding)
  2540. {
  2541. AlternateEncoding = encoding;
  2542. AlternateEncodingUsage = ZipOption.Always;
  2543. _InitInstance(null, null);
  2544. }
  2545. /// <summary>
  2546. /// Creates a new <c>ZipFile</c> instance, using the specified name for the
  2547. /// filename, and the specified status message writer.
  2548. /// </summary>
  2549. ///
  2550. /// <remarks>
  2551. /// <para>
  2552. /// See the documentation on the <see cref="ZipFile(String)">ZipFile
  2553. /// constructor that accepts a single string argument</see> for basic
  2554. /// information on all the <c>ZipFile</c> constructors.
  2555. /// </para>
  2556. ///
  2557. /// <para>
  2558. /// This version of the constructor allows the caller to pass in a TextWriter,
  2559. /// to which verbose messages will be written during extraction or creation of
  2560. /// the zip archive. A console application may wish to pass
  2561. /// System.Console.Out to get messages on the Console. A graphical or headless
  2562. /// application may wish to capture the messages in a different
  2563. /// <c>TextWriter</c>, for example, a <c>StringWriter</c>, and then display
  2564. /// the messages in a TextBox, or generate an audit log of ZipFile operations.
  2565. /// </para>
  2566. ///
  2567. /// <para>
  2568. /// To encrypt the data for the files added to the <c>ZipFile</c> instance,
  2569. /// set the Password property after creating the <c>ZipFile</c> instance.
  2570. /// </para>
  2571. ///
  2572. /// <para>
  2573. /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
  2574. /// not party on a single instance with multiple threads. You may have
  2575. /// multiple threads that each use a distinct <c>ZipFile</c> instance, or you
  2576. /// can synchronize multi-thread access to a single instance.
  2577. /// </para>
  2578. ///
  2579. /// </remarks>
  2580. ///
  2581. /// <exception cref="Ionic.Zip.ZipException">
  2582. /// Thrown if name refers to an existing file that is not a valid zip file.
  2583. /// </exception>
  2584. ///
  2585. /// <example>
  2586. /// <code>
  2587. /// using (ZipFile zip = new ZipFile("Backup.zip", Console.Out))
  2588. /// {
  2589. /// // Store all files found in the top level directory, into the zip archive.
  2590. /// // note: this code does not recurse subdirectories!
  2591. /// // Status messages will be written to Console.Out
  2592. /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
  2593. /// zip.AddFiles(filenames);
  2594. /// zip.Save();
  2595. /// }
  2596. /// </code>
  2597. ///
  2598. /// <code lang="VB">
  2599. /// Using zip As New ZipFile("Backup.zip", Console.Out)
  2600. /// ' Store all files found in the top level directory, into the zip archive.
  2601. /// ' note: this code does not recurse subdirectories!
  2602. /// ' Status messages will be written to Console.Out
  2603. /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
  2604. /// zip.AddFiles(filenames)
  2605. /// zip.Save()
  2606. /// End Using
  2607. /// </code>
  2608. /// </example>
  2609. ///
  2610. /// <param name="fileName">The filename to use for the new zip archive.</param>
  2611. /// <param name="statusMessageWriter">A TextWriter to use for writing
  2612. /// verbose status messages.</param>
  2613. public ZipFile(string fileName, TextWriter statusMessageWriter)
  2614. {
  2615. if (DefaultEncoding == null)
  2616. {
  2617. _alternateEncoding = System.Text.Encoding.UTF8;
  2618. AlternateEncodingUsage = ZipOption.Always;
  2619. }
  2620. else
  2621. {
  2622. _alternateEncoding = DefaultEncoding;
  2623. }
  2624. try
  2625. {
  2626. _InitInstance(fileName, statusMessageWriter);
  2627. }
  2628. catch (Exception e1)
  2629. {
  2630. throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
  2631. }
  2632. }
  2633. /// <summary>
  2634. /// Creates a new <c>ZipFile</c> instance, using the specified name for the
  2635. /// filename, the specified status message writer, and the specified Encoding.
  2636. /// </summary>
  2637. ///
  2638. /// <remarks>
  2639. /// <para>
  2640. /// This constructor works like the <see cref="ZipFile(String)">ZipFile
  2641. /// constructor that accepts a single string argument.</see> See that
  2642. /// reference for detail on what this constructor does.
  2643. /// </para>
  2644. ///
  2645. /// <para>
  2646. /// This version of the constructor allows the caller to pass in a
  2647. /// <c>TextWriter</c>, and an Encoding. The <c>TextWriter</c> will collect
  2648. /// verbose messages that are generated by the library during extraction or
  2649. /// creation of the zip archive. A console application may wish to pass
  2650. /// <c>System.Console.Out</c> to get messages on the Console. A graphical or
  2651. /// headless application may wish to capture the messages in a different
  2652. /// <c>TextWriter</c>, for example, a <c>StringWriter</c>, and then display
  2653. /// the messages in a <c>TextBox</c>, or generate an audit log of
  2654. /// <c>ZipFile</c> operations.
  2655. /// </para>
  2656. ///
  2657. /// <para>
  2658. /// The <c>Encoding</c> is used as the default alternate encoding for entries
  2659. /// with filenames or comments that cannot be encoded with the IBM437 code
  2660. /// page. This is a equivalent to setting the <see
  2661. /// cref="ProvisionalAlternateEncoding"/> property on the <c>ZipFile</c>
  2662. /// instance after construction.
  2663. /// </para>
  2664. ///
  2665. /// <para>
  2666. /// To encrypt the data for the files added to the <c>ZipFile</c> instance,
  2667. /// set the <c>Password</c> property after creating the <c>ZipFile</c>
  2668. /// instance.
  2669. /// </para>
  2670. ///
  2671. /// <para>
  2672. /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
  2673. /// not party on a single instance with multiple threads. You may have
  2674. /// multiple threads that each use a distinct <c>ZipFile</c> instance, or you
  2675. /// can synchronize multi-thread access to a single instance.
  2676. /// </para>
  2677. ///
  2678. /// </remarks>
  2679. ///
  2680. /// <exception cref="Ionic.Zip.ZipException">
  2681. /// Thrown if <c>fileName</c> refers to an existing file that is not a valid zip file.
  2682. /// </exception>
  2683. ///
  2684. /// <param name="fileName">The filename to use for the new zip archive.</param>
  2685. /// <param name="statusMessageWriter">A TextWriter to use for writing verbose
  2686. /// status messages.</param>
  2687. /// <param name="encoding">
  2688. /// The Encoding is used as the default alternate encoding for entries with
  2689. /// filenames or comments that cannot be encoded with the IBM437 code page.
  2690. /// </param>
  2691. public ZipFile(string fileName, TextWriter statusMessageWriter,
  2692. System.Text.Encoding encoding)
  2693. {
  2694. try
  2695. {
  2696. AlternateEncoding = encoding;
  2697. AlternateEncodingUsage = ZipOption.Always;
  2698. _InitInstance(fileName, statusMessageWriter);
  2699. }
  2700. catch (Exception e1)
  2701. {
  2702. throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
  2703. }
  2704. }
  2705. /// <summary>
  2706. /// Initialize a <c>ZipFile</c> instance by reading in a zip file.
  2707. /// </summary>
  2708. ///
  2709. /// <remarks>
  2710. ///
  2711. /// <para>
  2712. /// This method is primarily useful from COM Automation environments, when
  2713. /// reading or extracting zip files. In COM, it is not possible to invoke
  2714. /// parameterized constructors for a class. A COM Automation application can
  2715. /// update a zip file by using the <see cref="ZipFile()">default (no argument)
  2716. /// constructor</see>, then calling <c>Initialize()</c> to read the contents
  2717. /// of an on-disk zip archive into the <c>ZipFile</c> instance.
  2718. /// </para>
  2719. ///
  2720. /// <para>
  2721. /// .NET applications are encouraged to use the <c>ZipFile.Read()</c> methods
  2722. /// for better clarity.
  2723. /// </para>
  2724. ///
  2725. /// </remarks>
  2726. /// <param name="fileName">the name of the existing zip file to read in.</param>
  2727. public void Initialize(string fileName)
  2728. {
  2729. try
  2730. {
  2731. _InitInstance(fileName, null);
  2732. }
  2733. catch (Exception e1)
  2734. {
  2735. throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
  2736. }
  2737. }
  2738. private void _InitInstance(string zipFileName, TextWriter statusMessageWriter)
  2739. {
  2740. // create a new zipfile
  2741. _name = zipFileName;
  2742. _StatusMessageTextWriter = statusMessageWriter;
  2743. _contentsChanged = true;
  2744. AddDirectoryWillTraverseReparsePoints = true; // workitem 8617
  2745. CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
  2746. #if !NETCF
  2747. ParallelDeflateThreshold = 512 * 1024;
  2748. #endif
  2749. // workitem 7685, 9868
  2750. _entries = new Dictionary<string, ZipEntry>(StringComparer.Ordinal);
  2751. _entriesInsensitive = new Dictionary<string, ZipEntry>(StringComparer.OrdinalIgnoreCase);
  2752. if (File.Exists(_name))
  2753. {
  2754. if (FullScan)
  2755. ReadIntoInstance_Orig(this);
  2756. else
  2757. ReadIntoInstance(this);
  2758. this._fileAlreadyExists = true;
  2759. }
  2760. return;
  2761. }
  2762. #endregion
  2763. #region Indexers and Collections
  2764. private List<ZipEntry> ZipEntriesAsList
  2765. {
  2766. get
  2767. {
  2768. if (_zipEntriesAsList == null)
  2769. _zipEntriesAsList = new List<ZipEntry>(_entries.Values);
  2770. return _zipEntriesAsList;
  2771. }
  2772. }
  2773. /// <summary>
  2774. /// This is an integer indexer into the Zip archive.
  2775. /// </summary>
  2776. ///
  2777. /// <remarks>
  2778. /// <para>
  2779. /// This property is read-only.
  2780. /// </para>
  2781. ///
  2782. /// <para>
  2783. /// Internally, the <c>ZipEntry</c> instances that belong to the
  2784. /// <c>ZipFile</c> are stored in a Dictionary. When you use this
  2785. /// indexer the first time, it creates a read-only
  2786. /// <c>List&lt;ZipEntry&gt;</c> from the Dictionary.Values Collection.
  2787. /// If at any time you modify the set of entries in the <c>ZipFile</c>,
  2788. /// either by adding an entry, removing an entry, or renaming an
  2789. /// entry, a new List will be created, and the numeric indexes for the
  2790. /// remaining entries may be different.
  2791. /// </para>
  2792. ///
  2793. /// <para>
  2794. /// This means you cannot rename any ZipEntry from
  2795. /// inside an enumeration of the zip file.
  2796. /// </para>
  2797. ///
  2798. /// <param name="ix">
  2799. /// The index value.
  2800. /// </param>
  2801. ///
  2802. /// </remarks>
  2803. ///
  2804. /// <returns>
  2805. /// The <c>ZipEntry</c> within the Zip archive at the specified index. If the
  2806. /// entry does not exist in the archive, this indexer throws.
  2807. /// </returns>
  2808. ///
  2809. public ZipEntry this[int ix]
  2810. {
  2811. // workitem 6402
  2812. get
  2813. {
  2814. return ZipEntriesAsList[ix];
  2815. }
  2816. }
  2817. /// <summary>
  2818. /// This is a name-based indexer into the Zip archive.
  2819. /// </summary>
  2820. ///
  2821. /// <remarks>
  2822. /// <para>
  2823. /// This property is read-only.
  2824. /// </para>
  2825. ///
  2826. /// <para>
  2827. /// The <see cref="CaseSensitiveRetrieval"/> property on the <c>ZipFile</c>
  2828. /// determines whether retrieval via this indexer is done via case-sensitive
  2829. /// comparisons. By default, retrieval is not case sensitive. This makes
  2830. /// sense on Windows, in which filesystems are not case sensitive.
  2831. /// </para>
  2832. ///
  2833. /// <para>
  2834. /// Regardless of case-sensitivity, it is not always the case that
  2835. /// <c>this[value].FileName == value</c>. In other words, the <c>FileName</c>
  2836. /// property of the <c>ZipEntry</c> retrieved with this indexer, may or may
  2837. /// not be equal to the index value.
  2838. /// </para>
  2839. ///
  2840. /// <para>
  2841. /// This is because DotNetZip performs a normalization of filenames passed to
  2842. /// this indexer, before attempting to retrieve the item. That normalization
  2843. /// includes: removal of a volume letter and colon, swapping backward slashes
  2844. /// for forward slashes. So, <c>zip["dir1\\entry1.txt"].FileName ==
  2845. /// "dir1/entry.txt"</c>.
  2846. /// </para>
  2847. ///
  2848. /// <para>
  2849. /// Directory entries in the zip file may be retrieved via this indexer only
  2850. /// with names that have a trailing slash. DotNetZip automatically appends a
  2851. /// trailing slash to the names of any directory entries added to a zip.
  2852. /// </para>
  2853. ///
  2854. /// </remarks>
  2855. ///
  2856. /// <example>
  2857. /// This example extracts only the entries in a zip file that are .txt files.
  2858. /// <code>
  2859. /// using (ZipFile zip = ZipFile.Read("PackedDocuments.zip"))
  2860. /// {
  2861. /// foreach (string s1 in zip.EntryFilenames)
  2862. /// {
  2863. /// if (s1.EndsWith(".txt"))
  2864. /// zip[s1].Extract("textfiles");
  2865. /// }
  2866. /// }
  2867. /// </code>
  2868. /// <code lang="VB">
  2869. /// Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip")
  2870. /// Dim s1 As String
  2871. /// For Each s1 In zip.EntryFilenames
  2872. /// If s1.EndsWith(".txt") Then
  2873. /// zip(s1).Extract("textfiles")
  2874. /// End If
  2875. /// Next
  2876. /// End Using
  2877. /// </code>
  2878. /// </example>
  2879. /// <seealso cref="Ionic.Zip.ZipFile.RemoveEntry(string)"/>
  2880. ///
  2881. /// <exception cref="System.ArgumentException">
  2882. /// Thrown if the caller attempts to assign a non-null value to the indexer.
  2883. /// </exception>
  2884. ///
  2885. /// <param name="fileName">
  2886. /// The name of the file, including any directory path, to retrieve from the
  2887. /// zip. The filename match is not case-sensitive by default; you can use the
  2888. /// <see cref="CaseSensitiveRetrieval"/> property to change this behavior. The
  2889. /// pathname can use forward-slashes or backward slashes.
  2890. /// </param>
  2891. ///
  2892. /// <returns>
  2893. /// The <c>ZipEntry</c> within the Zip archive, given by the specified
  2894. /// filename. If the named entry does not exist in the archive, this indexer
  2895. /// returns <c>null</c> (<c>Nothing</c> in VB).
  2896. /// </returns>
  2897. ///
  2898. public ZipEntry this[String fileName]
  2899. {
  2900. get
  2901. {
  2902. var entries = RetrievalEntries;
  2903. var key = SharedUtilities.NormalizePathForUseInZipFile(fileName);
  2904. if (entries.ContainsKey(key))
  2905. return entries[key];
  2906. // workitem 11056
  2907. key = key.Replace("/", "\\");
  2908. if (entries.ContainsKey(key))
  2909. return entries[key];
  2910. return null;
  2911. #if MESSY
  2912. foreach (ZipEntry e in _entries.Values)
  2913. {
  2914. if (this.CaseSensitiveRetrieval)
  2915. {
  2916. // check for the file match with a case-sensitive comparison.
  2917. if (e.FileName == fileName) return e;
  2918. // also check for equivalence
  2919. if (fileName.Replace("\\", "/") == e.FileName) return e;
  2920. if (e.FileName.Replace("\\", "/") == fileName) return e;
  2921. // check for a difference only in trailing slash
  2922. if (e.FileName.EndsWith("/"))
  2923. {
  2924. var fileNameNoSlash = e.FileName.Trim("/".ToCharArray());
  2925. if (fileNameNoSlash == fileName) return e;
  2926. // also check for equivalence
  2927. if (fileName.Replace("\\", "/") == fileNameNoSlash) return e;
  2928. if (fileNameNoSlash.Replace("\\", "/") == fileName) return e;
  2929. }
  2930. }
  2931. else
  2932. {
  2933. // check for the file match in a case-insensitive manner.
  2934. if (String.Compare(e.FileName, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
  2935. // also check for equivalence
  2936. if (String.Compare(fileName.Replace("\\", "/"), e.FileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
  2937. if (String.Compare(e.FileName.Replace("\\", "/"), fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
  2938. // check for a difference only in trailing slash
  2939. if (e.FileName.EndsWith("/"))
  2940. {
  2941. var fileNameNoSlash = e.FileName.Trim("/".ToCharArray());
  2942. if (String.Compare(fileNameNoSlash, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
  2943. // also check for equivalence
  2944. if (String.Compare(fileName.Replace("\\", "/"), fileNameNoSlash, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
  2945. if (String.Compare(fileNameNoSlash.Replace("\\", "/"), fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
  2946. }
  2947. }
  2948. }
  2949. return null;
  2950. #endif
  2951. }
  2952. }
  2953. /// <summary>
  2954. /// The list of filenames for the entries contained within the zip archive.
  2955. /// </summary>
  2956. ///
  2957. /// <remarks>
  2958. /// According to the ZIP specification, the names of the entries use forward
  2959. /// slashes in pathnames. If you are scanning through the list, you may have
  2960. /// to swap forward slashes for backslashes.
  2961. /// </remarks>
  2962. ///
  2963. /// <seealso cref="Ionic.Zip.ZipFile.this[string]"/>
  2964. ///
  2965. /// <example>
  2966. /// This example shows one way to test if a filename is already contained
  2967. /// within a zip archive.
  2968. /// <code>
  2969. /// String zipFileToRead= "PackedDocuments.zip";
  2970. /// string candidate = "DatedMaterial.xps";
  2971. /// using (ZipFile zip = new ZipFile(zipFileToRead))
  2972. /// {
  2973. /// if (zip.EntryFilenames.Contains(candidate))
  2974. /// Console.WriteLine("The file '{0}' exists in the zip archive '{1}'",
  2975. /// candidate,
  2976. /// zipFileName);
  2977. /// else
  2978. /// Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'",
  2979. /// candidate,
  2980. /// zipFileName);
  2981. /// Console.WriteLine();
  2982. /// }
  2983. /// </code>
  2984. /// <code lang="VB">
  2985. /// Dim zipFileToRead As String = "PackedDocuments.zip"
  2986. /// Dim candidate As String = "DatedMaterial.xps"
  2987. /// Using zip As ZipFile.Read(ZipFileToRead)
  2988. /// If zip.EntryFilenames.Contains(candidate) Then
  2989. /// Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", _
  2990. /// candidate, _
  2991. /// zipFileName)
  2992. /// Else
  2993. /// Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", _
  2994. /// candidate, _
  2995. /// zipFileName)
  2996. /// End If
  2997. /// Console.WriteLine
  2998. /// End Using
  2999. /// </code>
  3000. /// </example>
  3001. ///
  3002. /// <returns>
  3003. /// The list of strings for the filenames contained within the Zip archive.
  3004. /// </returns>
  3005. ///
  3006. public System.Collections.Generic.ICollection<String> EntryFileNames
  3007. {
  3008. get
  3009. {
  3010. return _entries.Keys;
  3011. }
  3012. }
  3013. /// <summary>
  3014. /// Returns the readonly collection of entries in the Zip archive.
  3015. /// </summary>
  3016. ///
  3017. /// <remarks>
  3018. ///
  3019. /// <para>
  3020. /// If there are no entries in the current <c>ZipFile</c>, the value returned is a
  3021. /// non-null zero-element collection. If there are entries in the zip file,
  3022. /// the elements are returned in no particular order.
  3023. /// </para>
  3024. /// <para>
  3025. /// This is the implied enumerator on the <c>ZipFile</c> class. If you use a
  3026. /// <c>ZipFile</c> instance in a context that expects an enumerator, you will
  3027. /// get this collection.
  3028. /// </para>
  3029. /// </remarks>
  3030. /// <seealso cref="EntriesSorted"/>
  3031. public System.Collections.Generic.ICollection<ZipEntry> Entries
  3032. {
  3033. get
  3034. {
  3035. return _entries.Values;
  3036. }
  3037. }
  3038. /// <summary>
  3039. /// Returns a readonly collection of entries in the Zip archive, sorted by FileName.
  3040. /// </summary>
  3041. ///
  3042. /// <remarks>
  3043. /// If there are no entries in the current <c>ZipFile</c>, the value returned
  3044. /// is a non-null zero-element collection. If there are entries in the zip
  3045. /// file, the elements are returned sorted by the name of the entry.
  3046. /// </remarks>
  3047. ///
  3048. /// <example>
  3049. ///
  3050. /// This example fills a Windows Forms ListView with the entries in a zip file.
  3051. ///
  3052. /// <code lang="C#">
  3053. /// using (ZipFile zip = ZipFile.Read(zipFile))
  3054. /// {
  3055. /// foreach (ZipEntry entry in zip.EntriesSorted)
  3056. /// {
  3057. /// ListViewItem item = new ListViewItem(n.ToString());
  3058. /// n++;
  3059. /// string[] subitems = new string[] {
  3060. /// entry.FileName.Replace("/","\\"),
  3061. /// entry.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
  3062. /// entry.UncompressedSize.ToString(),
  3063. /// String.Format("{0,5:F0}%", entry.CompressionRatio),
  3064. /// entry.CompressedSize.ToString(),
  3065. /// (entry.UsesEncryption) ? "Y" : "N",
  3066. /// String.Format("{0:X8}", entry.Crc)};
  3067. ///
  3068. /// foreach (String s in subitems)
  3069. /// {
  3070. /// ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem();
  3071. /// subitem.Text = s;
  3072. /// item.SubItems.Add(subitem);
  3073. /// }
  3074. ///
  3075. /// this.listView1.Items.Add(item);
  3076. /// }
  3077. /// }
  3078. /// </code>
  3079. /// </example>
  3080. ///
  3081. /// <seealso cref="Entries"/>
  3082. public System.Collections.Generic.ICollection<ZipEntry> EntriesSorted
  3083. {
  3084. get
  3085. {
  3086. var coll = new System.Collections.Generic.List<ZipEntry>();
  3087. foreach (var e in this.Entries)
  3088. {
  3089. coll.Add(e);
  3090. }
  3091. StringComparison sc = (CaseSensitiveRetrieval) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
  3092. coll.Sort((x, y) => { return String.Compare(x.FileName, y.FileName, sc); });
  3093. return coll.AsReadOnly();
  3094. }
  3095. }
  3096. /// <summary>
  3097. /// Returns the number of entries in the Zip archive.
  3098. /// </summary>
  3099. public int Count
  3100. {
  3101. get
  3102. {
  3103. return _entries.Count;
  3104. }
  3105. }
  3106. /// <summary>
  3107. /// Removes the given <c>ZipEntry</c> from the zip archive.
  3108. /// </summary>
  3109. ///
  3110. /// <remarks>
  3111. /// <para>
  3112. /// After calling <c>RemoveEntry</c>, the application must call <c>Save</c> to
  3113. /// make the changes permanent.
  3114. /// </para>
  3115. /// </remarks>
  3116. ///
  3117. /// <exception cref="System.ArgumentException">
  3118. /// Thrown if the specified <c>ZipEntry</c> does not exist in the <c>ZipFile</c>.
  3119. /// </exception>
  3120. ///
  3121. /// <example>
  3122. /// In this example, all entries in the zip archive dating from before
  3123. /// December 31st, 2007, are removed from the archive. This is actually much
  3124. /// easier if you use the RemoveSelectedEntries method. But I needed an
  3125. /// example for RemoveEntry, so here it is.
  3126. /// <code>
  3127. /// String ZipFileToRead = "ArchiveToModify.zip";
  3128. /// System.DateTime Threshold = new System.DateTime(2007,12,31);
  3129. /// using (ZipFile zip = ZipFile.Read(ZipFileToRead))
  3130. /// {
  3131. /// var EntriesToRemove = new System.Collections.Generic.List&lt;ZipEntry&gt;();
  3132. /// foreach (ZipEntry e in zip)
  3133. /// {
  3134. /// if (e.LastModified &lt; Threshold)
  3135. /// {
  3136. /// // We cannot remove the entry from the list, within the context of
  3137. /// // an enumeration of said list.
  3138. /// // So we add the doomed entry to a list to be removed later.
  3139. /// EntriesToRemove.Add(e);
  3140. /// }
  3141. /// }
  3142. ///
  3143. /// // actually remove the doomed entries.
  3144. /// foreach (ZipEntry zombie in EntriesToRemove)
  3145. /// zip.RemoveEntry(zombie);
  3146. ///
  3147. /// zip.Comment= String.Format("This zip archive was updated at {0}.",
  3148. /// System.DateTime.Now.ToString("G"));
  3149. ///
  3150. /// // save with a different name
  3151. /// zip.Save("Archive-Updated.zip");
  3152. /// }
  3153. /// </code>
  3154. ///
  3155. /// <code lang="VB">
  3156. /// Dim ZipFileToRead As String = "ArchiveToModify.zip"
  3157. /// Dim Threshold As New DateTime(2007, 12, 31)
  3158. /// Using zip As ZipFile = ZipFile.Read(ZipFileToRead)
  3159. /// Dim EntriesToRemove As New System.Collections.Generic.List(Of ZipEntry)
  3160. /// Dim e As ZipEntry
  3161. /// For Each e In zip
  3162. /// If (e.LastModified &lt; Threshold) Then
  3163. /// ' We cannot remove the entry from the list, within the context of
  3164. /// ' an enumeration of said list.
  3165. /// ' So we add the doomed entry to a list to be removed later.
  3166. /// EntriesToRemove.Add(e)
  3167. /// End If
  3168. /// Next
  3169. ///
  3170. /// ' actually remove the doomed entries.
  3171. /// Dim zombie As ZipEntry
  3172. /// For Each zombie In EntriesToRemove
  3173. /// zip.RemoveEntry(zombie)
  3174. /// Next
  3175. /// zip.Comment = String.Format("This zip archive was updated at {0}.", DateTime.Now.ToString("G"))
  3176. /// 'save as a different name
  3177. /// zip.Save("Archive-Updated.zip")
  3178. /// End Using
  3179. /// </code>
  3180. /// </example>
  3181. ///
  3182. /// <param name="entry">
  3183. /// The <c>ZipEntry</c> to remove from the zip.
  3184. /// </param>
  3185. ///
  3186. /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(string)"/>
  3187. ///
  3188. public void RemoveEntry(ZipEntry entry)
  3189. {
  3190. //if (!_entries.Values.Contains(entry))
  3191. // throw new ArgumentException("The entry you specified does not exist in the zip archive.");
  3192. if (entry == null)
  3193. throw new ArgumentNullException("entry");
  3194. var path = SharedUtilities.NormalizePathForUseInZipFile(entry.FileName);
  3195. _entries.Remove(path);
  3196. if (!AnyCaseInsensitiveMatches(path))
  3197. _entriesInsensitive.Remove(path);
  3198. _zipEntriesAsList = null;
  3199. #if NOTNEEDED
  3200. if (_direntries != null)
  3201. {
  3202. bool FoundAndRemovedDirEntry = false;
  3203. foreach (ZipDirEntry de1 in _direntries)
  3204. {
  3205. if (entry.FileName == de1.FileName)
  3206. {
  3207. _direntries.Remove(de1);
  3208. FoundAndRemovedDirEntry = true;
  3209. break;
  3210. }
  3211. }
  3212. if (!FoundAndRemovedDirEntry)
  3213. throw new BadStateException("The entry to be removed was not found in the directory.");
  3214. }
  3215. #endif
  3216. _contentsChanged = true;
  3217. }
  3218. private bool AnyCaseInsensitiveMatches(string path)
  3219. {
  3220. // this has to search _entries rather than _caseInsensitiveEntries because it's used to determine whether to update the latter
  3221. foreach (var entry in _entries.Values)
  3222. {
  3223. if (String.Equals(entry.FileName, path, StringComparison.OrdinalIgnoreCase))
  3224. return true;
  3225. }
  3226. return false;
  3227. }
  3228. /// <summary>
  3229. /// Removes the <c>ZipEntry</c> with the given filename from the zip archive.
  3230. /// </summary>
  3231. ///
  3232. /// <remarks>
  3233. /// <para>
  3234. /// After calling <c>RemoveEntry</c>, the application must call <c>Save</c> to
  3235. /// make the changes permanent.
  3236. /// </para>
  3237. ///
  3238. /// </remarks>
  3239. ///
  3240. /// <exception cref="System.InvalidOperationException">
  3241. /// Thrown if the <c>ZipFile</c> is not updatable.
  3242. /// </exception>
  3243. ///
  3244. /// <exception cref="System.ArgumentException">
  3245. /// Thrown if a <c>ZipEntry</c> with the specified filename does not exist in
  3246. /// the <c>ZipFile</c>.
  3247. /// </exception>
  3248. ///
  3249. /// <example>
  3250. ///
  3251. /// This example shows one way to remove an entry with a given filename from
  3252. /// an existing zip archive.
  3253. ///
  3254. /// <code>
  3255. /// String zipFileToRead= "PackedDocuments.zip";
  3256. /// string candidate = "DatedMaterial.xps";
  3257. /// using (ZipFile zip = ZipFile.Read(zipFileToRead))
  3258. /// {
  3259. /// if (zip.EntryFilenames.Contains(candidate))
  3260. /// {
  3261. /// zip.RemoveEntry(candidate);
  3262. /// zip.Comment= String.Format("The file '{0}' has been removed from this archive.",
  3263. /// Candidate);
  3264. /// zip.Save();
  3265. /// }
  3266. /// }
  3267. /// </code>
  3268. /// <code lang="VB">
  3269. /// Dim zipFileToRead As String = "PackedDocuments.zip"
  3270. /// Dim candidate As String = "DatedMaterial.xps"
  3271. /// Using zip As ZipFile = ZipFile.Read(zipFileToRead)
  3272. /// If zip.EntryFilenames.Contains(candidate) Then
  3273. /// zip.RemoveEntry(candidate)
  3274. /// zip.Comment = String.Format("The file '{0}' has been removed from this archive.", Candidate)
  3275. /// zip.Save
  3276. /// End If
  3277. /// End Using
  3278. /// </code>
  3279. /// </example>
  3280. ///
  3281. /// <param name="fileName">
  3282. /// The name of the file, including any directory path, to remove from the zip.
  3283. /// The filename match is not case-sensitive by default; you can use the
  3284. /// <c>CaseSensitiveRetrieval</c> property to change this behavior. The
  3285. /// pathname can use forward-slashes or backward slashes.
  3286. /// </param>
  3287. ///
  3288. public void RemoveEntry(String fileName)
  3289. {
  3290. string modifiedName = ZipEntry.NameInArchive(fileName, null);
  3291. ZipEntry e = this[modifiedName];
  3292. if (e == null)
  3293. throw new ArgumentException("The entry you specified was not found in the zip archive.");
  3294. RemoveEntry(e);
  3295. }
  3296. #endregion
  3297. #region Destructors and Disposers
  3298. // /// <summary>
  3299. // /// This is the class Destructor, which gets called implicitly when the instance
  3300. // /// is destroyed. Because the <c>ZipFile</c> type implements IDisposable, this
  3301. // /// method calls Dispose(false).
  3302. // /// </summary>
  3303. // ~ZipFile()
  3304. // {
  3305. // // call Dispose with false. Since we're in the
  3306. // // destructor call, the managed resources will be
  3307. // // disposed of anyways.
  3308. // Dispose(false);
  3309. // }
  3310. /// <summary>
  3311. /// Closes the read and write streams associated
  3312. /// to the <c>ZipFile</c>, if necessary.
  3313. /// </summary>
  3314. ///
  3315. /// <remarks>
  3316. /// The Dispose() method is generally employed implicitly, via a <c>using(..) {..}</c>
  3317. /// statement. (<c>Using...End Using</c> in VB) If you do not employ a using
  3318. /// statement, insure that your application calls Dispose() explicitly. For
  3319. /// example, in a Powershell application, or an application that uses the COM
  3320. /// interop interface, you must call Dispose() explicitly.
  3321. /// </remarks>
  3322. ///
  3323. /// <example>
  3324. /// This example extracts an entry selected by name, from the Zip file to the
  3325. /// Console.
  3326. /// <code>
  3327. /// using (ZipFile zip = ZipFile.Read(zipfile))
  3328. /// {
  3329. /// foreach (ZipEntry e in zip)
  3330. /// {
  3331. /// if (WantThisEntry(e.FileName))
  3332. /// zip.Extract(e.FileName, Console.OpenStandardOutput());
  3333. /// }
  3334. /// } // Dispose() is called implicitly here.
  3335. /// </code>
  3336. ///
  3337. /// <code lang="VB">
  3338. /// Using zip As ZipFile = ZipFile.Read(zipfile)
  3339. /// Dim e As ZipEntry
  3340. /// For Each e In zip
  3341. /// If WantThisEntry(e.FileName) Then
  3342. /// zip.Extract(e.FileName, Console.OpenStandardOutput())
  3343. /// End If
  3344. /// Next
  3345. /// End Using ' Dispose is implicity called here
  3346. /// </code>
  3347. /// </example>
  3348. public void Dispose()
  3349. {
  3350. // dispose of the managed and unmanaged resources
  3351. Dispose(true);
  3352. // tell the GC that the Finalize process no longer needs
  3353. // to be run for this object.
  3354. GC.SuppressFinalize(this);
  3355. }
  3356. /// <summary>
  3357. /// Disposes any managed resources, if the flag is set, then marks the
  3358. /// instance disposed. This method is typically not called explicitly from
  3359. /// application code.
  3360. /// </summary>
  3361. ///
  3362. /// <remarks>
  3363. /// Applications should call <see cref="Dispose()">the no-arg Dispose method</see>.
  3364. /// </remarks>
  3365. ///
  3366. /// <param name="disposeManagedResources">
  3367. /// indicates whether the method should dispose streams or not.
  3368. /// </param>
  3369. protected virtual void Dispose(bool disposeManagedResources)
  3370. {
  3371. if (!this._disposed)
  3372. {
  3373. if (disposeManagedResources)
  3374. {
  3375. // dispose managed resources
  3376. if (_ReadStreamIsOurs)
  3377. {
  3378. if (_readstream != null)
  3379. {
  3380. // workitem 7704
  3381. #if NETCF
  3382. _readstream.Close();
  3383. #else
  3384. _readstream.Dispose();
  3385. #endif
  3386. _readstream = null;
  3387. }
  3388. }
  3389. // only dispose the writestream if there is a backing file
  3390. if ((_temporaryFileName != null) && (_name != null))
  3391. if (_writestream != null)
  3392. {
  3393. // workitem 7704
  3394. #if NETCF
  3395. _writestream.Close();
  3396. #else
  3397. _writestream.Dispose();
  3398. #endif
  3399. _writestream = null;
  3400. }
  3401. #if !NETCF
  3402. // workitem 10030
  3403. if (this.ParallelDeflater != null)
  3404. {
  3405. this.ParallelDeflater.Dispose();
  3406. this.ParallelDeflater = null;
  3407. }
  3408. #endif
  3409. }
  3410. this._disposed = true;
  3411. }
  3412. }
  3413. #endregion
  3414. #region private properties
  3415. internal Stream ReadStream
  3416. {
  3417. get
  3418. {
  3419. if (_readstream == null)
  3420. {
  3421. if (_readName != null || _name !=null)
  3422. {
  3423. _readstream = File.Open(_readName ?? _name,
  3424. FileMode.Open,
  3425. FileAccess.Read,
  3426. FileShare.Read | FileShare.Write);
  3427. _ReadStreamIsOurs = true;
  3428. }
  3429. }
  3430. return _readstream;
  3431. }
  3432. }
  3433. private Stream WriteStream
  3434. {
  3435. // workitem 9763
  3436. get
  3437. {
  3438. if (_writestream != null) return _writestream;
  3439. if (_name == null) return _writestream;
  3440. if (_maxOutputSegmentSize != 0)
  3441. {
  3442. _writestream = ZipSegmentedStream.ForWriting(this._name, _maxOutputSegmentSize);
  3443. return _writestream;
  3444. }
  3445. SharedUtilities.CreateAndOpenUniqueTempFile(TempFileFolder ?? Path.GetDirectoryName(_name),
  3446. out _writestream,
  3447. out _temporaryFileName);
  3448. return _writestream;
  3449. }
  3450. set
  3451. {
  3452. if (value != null)
  3453. throw new ZipException("Cannot set the stream to a non-null value.");
  3454. _writestream = null;
  3455. }
  3456. }
  3457. #endregion
  3458. #region private fields
  3459. private TextWriter _StatusMessageTextWriter;
  3460. private bool _CaseSensitiveRetrieval;
  3461. private bool _IgnoreDuplicateFiles;
  3462. private Stream _readstream;
  3463. private Stream _writestream;
  3464. private UInt16 _versionMadeBy;
  3465. private UInt16 _versionNeededToExtract;
  3466. private UInt32 _diskNumberWithCd;
  3467. private Int32 _maxOutputSegmentSize;
  3468. private UInt32 _numberOfSegmentsForMostRecentSave;
  3469. private ZipErrorAction _zipErrorAction;
  3470. private bool _disposed;
  3471. //private System.Collections.Generic.List<ZipEntry> _entries;
  3472. private System.Collections.Generic.Dictionary<String, ZipEntry> _entries;
  3473. private System.Collections.Generic.Dictionary<String, ZipEntry> _entriesInsensitive;
  3474. private List<ZipEntry> _zipEntriesAsList;
  3475. private string _name;
  3476. private string _readName;
  3477. private string _Comment;
  3478. internal string _Password;
  3479. private bool _emitNtfsTimes = true;
  3480. private bool _emitUnixTimes;
  3481. private Ionic.Zlib.CompressionStrategy _Strategy = Ionic.Zlib.CompressionStrategy.Default;
  3482. private Ionic.Zip.CompressionMethod _compressionMethod = Ionic.Zip.CompressionMethod.Deflate;
  3483. private bool _fileAlreadyExists;
  3484. private string _temporaryFileName;
  3485. private bool _contentsChanged;
  3486. private bool _hasBeenSaved;
  3487. private String _TempFileFolder;
  3488. private bool _ReadStreamIsOurs = true;
  3489. private object LOCK = new object();
  3490. private bool _saveOperationCanceled;
  3491. private bool _extractOperationCanceled;
  3492. private bool _addOperationCanceled;
  3493. private EncryptionAlgorithm _Encryption;
  3494. private bool _JustSaved;
  3495. private long _locEndOfCDS = -1;
  3496. private uint _OffsetOfCentralDirectory;
  3497. private Int64 _OffsetOfCentralDirectory64;
  3498. private Nullable<bool> _OutputUsesZip64;
  3499. internal bool _inExtractAll;
  3500. private System.Text.Encoding _alternateEncoding = null;
  3501. private ZipOption _alternateEncodingUsage = ZipOption.Never;
  3502. private int _BufferSize = BufferSizeDefault;
  3503. #if !NETCF
  3504. internal Ionic.Zlib.ParallelDeflateOutputStream ParallelDeflater;
  3505. private long _ParallelDeflateThreshold;
  3506. private int _maxBufferPairs = 16;
  3507. #endif
  3508. internal Zip64Option _zip64 = Zip64Option.Default;
  3509. #pragma warning disable 649
  3510. private bool _SavingSfx;
  3511. #pragma warning restore 649
  3512. /// <summary>
  3513. /// Default size of the buffer used for IO.
  3514. /// </summary>
  3515. public static readonly int BufferSizeDefault = 32768;
  3516. #endregion
  3517. }
  3518. /// <summary>
  3519. /// Options for using ZIP64 extensions when saving zip archives.
  3520. /// </summary>
  3521. ///
  3522. /// <remarks>
  3523. ///
  3524. /// <para>
  3525. /// Designed many years ago, the <see
  3526. /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">original zip
  3527. /// specification from PKWARE</see> allowed for 32-bit quantities for the
  3528. /// compressed and uncompressed sizes of zip entries, as well as a 32-bit quantity
  3529. /// for specifying the length of the zip archive itself, and a maximum of 65535
  3530. /// entries. These limits are now regularly exceeded in many backup and archival
  3531. /// scenarios. Recently, PKWare added extensions to the original zip spec, called
  3532. /// "ZIP64 extensions", to raise those limitations. This property governs whether
  3533. /// DotNetZip will use those extensions when writing zip archives. The use of
  3534. /// these extensions is optional and explicit in DotNetZip because, despite the
  3535. /// status of ZIP64 as a bona fide standard, many other zip tools and libraries do
  3536. /// not support ZIP64, and therefore a zip file with ZIP64 extensions may be
  3537. /// unreadable by some of those other tools.
  3538. /// </para>
  3539. ///
  3540. /// <para>
  3541. /// Set this property to <see cref="Zip64Option.Always"/> to always use ZIP64
  3542. /// extensions when saving, regardless of whether your zip archive needs it.
  3543. /// Suppose you add 5 files, each under 100k, to a ZipFile. If you specify Always
  3544. /// for this flag, you will get a ZIP64 archive, though the archive does not need
  3545. /// to use ZIP64 because none of the original zip limits had been exceeded.
  3546. /// </para>
  3547. ///
  3548. /// <para>
  3549. /// Set this property to <see cref="Zip64Option.Never"/> to tell the DotNetZip
  3550. /// library to never use ZIP64 extensions. This is useful for maximum
  3551. /// compatibility and interoperability, at the expense of the capability of
  3552. /// handling large files or large archives. NB: Windows Explorer in Windows XP
  3553. /// and Windows Vista cannot currently extract files from a zip64 archive, so if
  3554. /// you want to guarantee that a zip archive produced by this library will work in
  3555. /// Windows Explorer, use <c>Never</c>. If you set this property to <see
  3556. /// cref="Zip64Option.Never"/>, and your application creates a zip that would
  3557. /// exceed one of the Zip limits, the library will throw an exception while saving
  3558. /// the zip file.
  3559. /// </para>
  3560. ///
  3561. /// <para>
  3562. /// Set this property to <see cref="Zip64Option.AsNecessary"/> to tell the
  3563. /// DotNetZip library to use the ZIP64 extensions when required by the
  3564. /// entry. After the file is compressed, the original and compressed sizes are
  3565. /// checked, and if they exceed the limits described above, then zip64 can be
  3566. /// used. That is the general idea, but there is an additional wrinkle when saving
  3567. /// to a non-seekable device, like the ASP.NET <c>Response.OutputStream</c>, or
  3568. /// <c>Console.Out</c>. When using non-seekable streams for output, the entry
  3569. /// header - which indicates whether zip64 is in use - is emitted before it is
  3570. /// known if zip64 is necessary. It is only after all entries have been saved
  3571. /// that it can be known if ZIP64 will be required. On seekable output streams,
  3572. /// after saving all entries, the library can seek backward and re-emit the zip
  3573. /// file header to be consistent with the actual ZIP64 requirement. But using a
  3574. /// non-seekable output stream, the library cannot seek backward, so the header
  3575. /// can never be changed. In other words, the archive's use of ZIP64 extensions is
  3576. /// not alterable after the header is emitted. Therefore, when saving to
  3577. /// non-seekable streams, using <see cref="Zip64Option.AsNecessary"/> is the same
  3578. /// as using <see cref="Zip64Option.Always"/>: it will always produce a zip
  3579. /// archive that uses ZIP64 extensions.
  3580. /// </para>
  3581. ///
  3582. /// </remarks>
  3583. public enum Zip64Option
  3584. {
  3585. /// <summary>
  3586. /// The default behavior, which is "Never".
  3587. /// (For COM clients, this is a 0 (zero).)
  3588. /// </summary>
  3589. Default = 0,
  3590. /// <summary>
  3591. /// Do not use ZIP64 extensions when writing zip archives.
  3592. /// (For COM clients, this is a 0 (zero).)
  3593. /// </summary>
  3594. Never = 0,
  3595. /// <summary>
  3596. /// Use ZIP64 extensions when writing zip archives, as necessary.
  3597. /// For example, when a single entry exceeds 0xFFFFFFFF in size, or when the archive as a whole
  3598. /// exceeds 0xFFFFFFFF in size, or when there are more than 65535 entries in an archive.
  3599. /// (For COM clients, this is a 1.)
  3600. /// </summary>
  3601. AsNecessary = 1,
  3602. /// <summary>
  3603. /// Always use ZIP64 extensions when writing zip archives, even when unnecessary.
  3604. /// (For COM clients, this is a 2.)
  3605. /// </summary>
  3606. Always
  3607. }
  3608. /// <summary>
  3609. /// An enum representing the values on a three-way toggle switch
  3610. /// for various options in the library. This might be used to
  3611. /// specify whether to employ a particular text encoding, or to use
  3612. /// ZIP64 extensions, or some other option.
  3613. /// </summary>
  3614. public enum ZipOption
  3615. {
  3616. /// <summary>
  3617. /// The default behavior. This is the same as "Never".
  3618. /// (For COM clients, this is a 0 (zero).)
  3619. /// </summary>
  3620. Default = 0,
  3621. /// <summary>
  3622. /// Never use the associated option.
  3623. /// (For COM clients, this is a 0 (zero).)
  3624. /// </summary>
  3625. Never = 0,
  3626. /// <summary>
  3627. /// Use the associated behavior "as necessary."
  3628. /// (For COM clients, this is a 1.)
  3629. /// </summary>
  3630. AsNecessary = 1,
  3631. /// <summary>
  3632. /// Use the associated behavior Always, whether necessary or not.
  3633. /// (For COM clients, this is a 2.)
  3634. /// </summary>
  3635. Always
  3636. }
  3637. enum AddOrUpdateAction
  3638. {
  3639. AddOnly = 0,
  3640. AddOrUpdate
  3641. }
  3642. }
  3643. // ==================================================================
  3644. //
  3645. // Information on the ZIP format:
  3646. //
  3647. // From
  3648. // http://www.pkware.com/documents/casestudies/APPNOTE.TXT
  3649. //
  3650. // Overall .ZIP file format:
  3651. //
  3652. // [local file header 1]
  3653. // [file data 1]
  3654. // [data descriptor 1] ** sometimes
  3655. // .
  3656. // .
  3657. // .
  3658. // [local file header n]
  3659. // [file data n]
  3660. // [data descriptor n] ** sometimes
  3661. // [archive decryption header]
  3662. // [archive extra data record]
  3663. // [central directory]
  3664. // [zip64 end of central directory record]
  3665. // [zip64 end of central directory locator]
  3666. // [end of central directory record]
  3667. //
  3668. // Local File Header format:
  3669. // local file header signature ... 4 bytes (0x04034b50)
  3670. // version needed to extract ..... 2 bytes
  3671. // general purpose bit field ..... 2 bytes
  3672. // compression method ............ 2 bytes
  3673. // last mod file time ............ 2 bytes
  3674. // last mod file date............. 2 bytes
  3675. // crc-32 ........................ 4 bytes
  3676. // compressed size................ 4 bytes
  3677. // uncompressed size.............. 4 bytes
  3678. // file name length............... 2 bytes
  3679. // extra field length ............ 2 bytes
  3680. // file name varies
  3681. // extra field varies
  3682. //
  3683. //
  3684. // Data descriptor: (used only when bit 3 of the general purpose bitfield is set)
  3685. // (although, I have found zip files where bit 3 is not set, yet this descriptor is present!)
  3686. // local file header signature 4 bytes (0x08074b50) ** sometimes!!! Not always
  3687. // crc-32 4 bytes
  3688. // compressed size 4 bytes
  3689. // uncompressed size 4 bytes
  3690. //
  3691. //
  3692. // Central directory structure:
  3693. //
  3694. // [file header 1]
  3695. // .
  3696. // .
  3697. // .
  3698. // [file header n]
  3699. // [digital signature]
  3700. //
  3701. //
  3702. // File header: (This is a ZipDirEntry)
  3703. // central file header signature 4 bytes (0x02014b50)
  3704. // version made by 2 bytes
  3705. // version needed to extract 2 bytes
  3706. // general purpose bit flag 2 bytes
  3707. // compression method 2 bytes
  3708. // last mod file time 2 bytes
  3709. // last mod file date 2 bytes
  3710. // crc-32 4 bytes
  3711. // compressed size 4 bytes
  3712. // uncompressed size 4 bytes
  3713. // file name length 2 bytes
  3714. // extra field length 2 bytes
  3715. // file comment length 2 bytes
  3716. // disk number start 2 bytes
  3717. // internal file attributes ** 2 bytes
  3718. // external file attributes *** 4 bytes
  3719. // relative offset of local header 4 bytes
  3720. // file name (variable size)
  3721. // extra field (variable size)
  3722. // file comment (variable size)
  3723. //
  3724. // ** The internal file attributes, near as I can tell,
  3725. // uses 0x01 for a file and a 0x00 for a directory.
  3726. //
  3727. // ***The external file attributes follows the MS-DOS file attribute byte, described here:
  3728. // at http://support.microsoft.com/kb/q125019/
  3729. // 0x0010 => directory
  3730. // 0x0020 => file
  3731. //
  3732. //
  3733. // End of central directory record:
  3734. //
  3735. // end of central dir signature 4 bytes (0x06054b50)
  3736. // number of this disk 2 bytes
  3737. // number of the disk with the
  3738. // start of the central directory 2 bytes
  3739. // total number of entries in the
  3740. // central directory on this disk 2 bytes
  3741. // total number of entries in
  3742. // the central directory 2 bytes
  3743. // size of the central directory 4 bytes
  3744. // offset of start of central
  3745. // directory with respect to
  3746. // the starting disk number 4 bytes
  3747. // .ZIP file comment length 2 bytes
  3748. // .ZIP file comment (variable size)
  3749. //
  3750. // date and time are packed values, as MSDOS did them
  3751. // time: bits 0-4 : seconds (divided by 2)
  3752. // 5-10: minute
  3753. // 11-15: hour
  3754. // date bits 0-4 : day
  3755. // 5-8: month
  3756. // 9-15 year (since 1980)
  3757. //
  3758. // see http://msdn.microsoft.com/en-us/library/ms724274(VS.85).aspx