12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965 |
- // ZipFile.cs
- //
- // Copyright (c) 2006-2010 Dino Chiesa
- // All rights reserved.
- //
- // This module is part of DotNetZip, a zipfile class library.
- // The class library reads and writes zip files, according to the format
- // described by PKware, at:
- // http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
- //
- //
- // There are other Zip class libraries available.
- //
- // - it is possible to read and write zip files within .NET via the J# runtime.
- // But some people don't like to install the extra DLL, which is no longer
- // supported by MS. And also, the J# libraries don't support advanced zip
- // features, like ZIP64, spanned archives, or AES encryption.
- //
- // - There are third-party GPL and LGPL libraries available. Some people don't
- // like the license, and some of them don't support all the ZIP features, like AES.
- //
- // - Finally, there are commercial tools (From ComponentOne, XCeed, etc). But
- // some people don't want to incur the cost.
- //
- // This alternative implementation is **not** GPL licensed. It is free of cost, and
- // does not require J#. It does require .NET 2.0. It balances a good set of
- // features, with ease of use and speed of performance.
- //
- // This code is released under the Microsoft Public License .
- // See the License.txt for details.
- //
- //
- // NB: This implementation originally relied on the
- // System.IO.Compression.DeflateStream base class in the .NET Framework
- // v2.0 base class library, but now includes a managed-code port of Zlib.
- //
- // Thu, 08 Oct 2009 17:04
- //
- using System;
- using System.IO;
- using System.Collections.Generic;
- using Interop = System.Runtime.InteropServices;
- namespace Ionic.Zip
- {
- /// <summary>
- /// The ZipFile type represents a zip archive file.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This is the main type in the DotNetZip class library. This class reads and
- /// writes zip files, as defined in the <see
- /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">specification
- /// for zip files described by PKWare</see>. The compression for this
- /// implementation is provided by a managed-code version of Zlib, included with
- /// DotNetZip in the classes in the Ionic.Zlib namespace.
- /// </para>
- ///
- /// <para>
- /// This class provides a general purpose zip file capability. Use it to read,
- /// create, or update zip files. When you want to create zip files using a
- /// <c>Stream</c> type to write the zip file, you may want to consider the <see
- /// cref="ZipOutputStream"/> class.
- /// </para>
- ///
- /// <para>
- /// Both the <c>ZipOutputStream</c> class and the <c>ZipFile</c> class can
- /// be used to create zip files. Both of them support many of the common zip
- /// features, including Unicode, different compression methods and levels,
- /// and ZIP64. They provide very similar performance when creating zip
- /// files.
- /// </para>
- ///
- /// <para>
- /// The <c>ZipFile</c> class is generally easier to use than
- /// <c>ZipOutputStream</c> and should be considered a higher-level interface. For
- /// example, when creating a zip file via calls to the <c>PutNextEntry()</c> and
- /// <c>Write()</c> methods on the <c>ZipOutputStream</c> class, the caller is
- /// responsible for opening the file, reading the bytes from the file, writing
- /// those bytes into the <c>ZipOutputStream</c>, setting the attributes on the
- /// <c>ZipEntry</c>, and setting the created, last modified, and last accessed
- /// timestamps on the zip entry. All of these things are done automatically by a
- /// call to <see cref="ZipFile.AddFile(string,string)">ZipFile.AddFile()</see>.
- /// For this reason, the <c>ZipOutputStream</c> is generally recommended for use
- /// only when your application emits arbitrary data, not necessarily data from a
- /// filesystem file, directly into a zip file, and does so using a <c>Stream</c>
- /// metaphor.
- /// </para>
- ///
- /// <para>
- /// Aside from the differences in programming model, there are other
- /// differences in capability between the two classes.
- /// </para>
- ///
- /// <list type="bullet">
- /// <item>
- /// <c>ZipFile</c> can be used to read and extract zip files, in addition to
- /// creating zip files. <c>ZipOutputStream</c> cannot read zip files. If you want
- /// to use a stream to read zip files, check out the <see cref="ZipInputStream"/> class.
- /// </item>
- ///
- /// <item>
- /// <c>ZipOutputStream</c> does not support the creation of segmented or spanned
- /// zip files.
- /// </item>
- ///
- /// <item>
- /// <c>ZipOutputStream</c> cannot produce a self-extracting archive.
- /// </item>
- /// </list>
- ///
- /// <para>
- /// Be aware that the <c>ZipFile</c> class implements the <see
- /// cref="System.IDisposable"/> interface. In order for <c>ZipFile</c> to
- /// produce a valid zip file, you use use it within a using clause (<c>Using</c>
- /// in VB), or call the <c>Dispose()</c> method explicitly. See the examples
- /// for how to employ a using clause.
- /// </para>
- ///
- /// </remarks>
- [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00005")]
- [Interop.ComVisible(true)]
- #if !NETCF
- [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)]
- #endif
- public partial class ZipFile :
- System.Collections.IEnumerable,
- System.Collections.Generic.IEnumerable<ZipEntry>,
- IDisposable
- {
- #region public properties
- /// <summary>
- /// Indicates whether to perform a full scan of the zip file when reading it.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// You almost never want to use this property.
- /// </para>
- ///
- /// <para>
- /// When reading a zip file, if this flag is <c>true</c> (<c>True</c> in
- /// VB), the entire zip archive will be scanned and searched for entries.
- /// For large archives, this can take a very, long time. The much more
- /// efficient default behavior is to read the zip directory, which is
- /// stored at the end of the zip file. But, in some cases the directory is
- /// corrupted and you need to perform a full scan of the zip file to
- /// determine the contents of the zip file. This property lets you do
- /// that, when necessary.
- /// </para>
- ///
- /// <para>
- /// This flag is effective only when calling <see
- /// cref="Initialize(string)"/>. Normally you would read a ZipFile with the
- /// static <see cref="ZipFile.Read(String)">ZipFile.Read</see>
- /// method. But you can't set the <c>FullScan</c> property on the
- /// <c>ZipFile</c> instance when you use a static factory method like
- /// <c>ZipFile.Read</c>.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- ///
- /// This example shows how to read a zip file using the full scan approach,
- /// and then save it, thereby producing a corrected zip file.
- ///
- /// <code lang="C#">
- /// using (var zip = new ZipFile())
- /// {
- /// zip.FullScan = true;
- /// zip.Initialize(zipFileName);
- /// zip.Save(newName);
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As New ZipFile
- /// zip.FullScan = True
- /// zip.Initialize(zipFileName)
- /// zip.Save(newName)
- /// End Using
- /// </code>
- /// </example>
- ///
- public bool FullScan
- {
- get;
- set;
- }
- /// <summary>
- /// Whether to sort the ZipEntries before saving the file.
- /// </summary>
- ///
- /// <remarks>
- /// The default is false. If you have a large number of zip entries, the sort
- /// alone can consume significant time.
- /// </remarks>
- ///
- /// <example>
- /// <code lang="C#">
- /// using (var zip = new ZipFile())
- /// {
- /// zip.AddFiles(filesToAdd);
- /// zip.SortEntriesBeforeSaving = true;
- /// zip.Save(name);
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As New ZipFile
- /// zip.AddFiles(filesToAdd)
- /// zip.SortEntriesBeforeSaving = True
- /// zip.Save(name)
- /// End Using
- /// </code>
- /// </example>
- ///
- public bool SortEntriesBeforeSaving
- {
- get;
- set;
- }
- /// <summary>
- /// Indicates whether NTFS Reparse Points, like junctions, should be
- /// traversed during calls to <c>AddDirectory()</c>.
- /// </summary>
- ///
- /// <remarks>
- /// By default, calls to AddDirectory() will traverse NTFS reparse
- /// points, like mounted volumes, and directory junctions. An example
- /// of a junction is the "My Music" directory in Windows Vista. In some
- /// cases you may not want DotNetZip to traverse those directories. In
- /// that case, set this property to false.
- /// </remarks>
- ///
- /// <example>
- /// <code lang="C#">
- /// using (var zip = new ZipFile())
- /// {
- /// zip.AddDirectoryWillTraverseReparsePoints = false;
- /// zip.AddDirectory(dirToZip,"fodder");
- /// zip.Save(zipFileToCreate);
- /// }
- /// </code>
- /// </example>
- public bool AddDirectoryWillTraverseReparsePoints { get; set; }
- /// <summary>
- /// Size of the IO buffer used while saving.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// First, let me say that you really don't need to bother with this. It is
- /// here to allow for optimizations that you probably won't make! It will work
- /// fine if you don't set or get this property at all. Ok?
- /// </para>
- ///
- /// <para>
- /// Now that we have <em>that</em> out of the way, the fine print: This
- /// property affects the size of the buffer that is used for I/O for each
- /// entry contained in the zip file. When a file is read in to be compressed,
- /// it uses a buffer given by the size here. When you update a zip file, the
- /// data for unmodified entries is copied from the first zip file to the
- /// other, through a buffer given by the size here.
- /// </para>
- ///
- /// <para>
- /// Changing the buffer size affects a few things: first, for larger buffer
- /// sizes, the memory used by the <c>ZipFile</c>, obviously, will be larger
- /// during I/O operations. This may make operations faster for very much
- /// larger files. Last, for any given entry, when you use a larger buffer
- /// there will be fewer progress events during I/O operations, because there's
- /// one progress event generated for each time the buffer is filled and then
- /// emptied.
- /// </para>
- ///
- /// <para>
- /// The default buffer size is 8k. Increasing the buffer size may speed
- /// things up as you compress larger files. But there are no hard-and-fast
- /// rules here, eh? You won't know til you test it. And there will be a
- /// limit where ever larger buffers actually slow things down. So as I said
- /// in the beginning, it's probably best if you don't set or get this property
- /// at all.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// This example shows how you might set a large buffer size for efficiency when
- /// dealing with zip entries that are larger than 1gb.
- /// <code lang="C#">
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// zip.SaveProgress += this.zip1_SaveProgress;
- /// zip.AddDirectory(directoryToZip, "");
- /// zip.UseZip64WhenSaving = Zip64Option.Always;
- /// zip.BufferSize = 65536*8; // 65536 * 8 = 512k
- /// zip.Save(ZipFileToCreate);
- /// }
- /// </code>
- /// </example>
- public int BufferSize
- {
- get { return _BufferSize; }
- set { _BufferSize = value; }
- }
- /// <summary>
- /// Size of the work buffer to use for the ZLIB codec during compression.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// When doing ZLIB or Deflate compression, the library fills a buffer,
- /// then passes it to the compressor for compression. Then the library
- /// reads out the compressed bytes. This happens repeatedly until there
- /// is no more uncompressed data to compress. This property sets the
- /// size of the buffer that will be used for chunk-wise compression. In
- /// order for the setting to take effect, your application needs to set
- /// this property before calling one of the <c>ZipFile.Save()</c>
- /// overloads.
- /// </para>
- /// <para>
- /// Setting this affects the performance and memory efficiency of
- /// compression and decompression. For larger files, setting this to a
- /// larger size may improve compression performance, but the exact
- /// numbers vary depending on available memory, the size of the streams
- /// you are compressing, and a bunch of other variables. I don't have
- /// good firm recommendations on how to set it. You'll have to test it
- /// yourself. Or just leave it alone and accept the default.
- /// </para>
- /// </remarks>
- public int CodecBufferSize
- {
- get;
- set;
- }
- /// <summary>
- /// Indicates whether extracted files should keep their paths as
- /// stored in the zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This property affects Extraction. It is not used when creating zip
- /// archives.
- /// </para>
- ///
- /// <para>
- /// With this property set to <c>false</c>, the default, extracting entries
- /// from a zip file will create files in the filesystem that have the full
- /// path associated to the entry within the zip file. With this property set
- /// to <c>true</c>, extracting entries from the zip file results in files
- /// with no path: the folders are "flattened."
- /// </para>
- ///
- /// <para>
- /// An example: suppose the zip file contains entries /directory1/file1.txt and
- /// /directory2/file2.txt. With <c>FlattenFoldersOnExtract</c> set to false,
- /// the files created will be \directory1\file1.txt and \directory2\file2.txt.
- /// With the property set to true, the files created are file1.txt and file2.txt.
- /// </para>
- ///
- /// </remarks>
- public bool FlattenFoldersOnExtract
- {
- get;
- set;
- }
- /// <summary>
- /// The compression strategy to use for all entries.
- /// </summary>
- ///
- /// <remarks>
- /// Set the Strategy used by the ZLIB-compatible compressor, when
- /// compressing entries using the DEFLATE method. Different compression
- /// strategies work better on different sorts of data. The strategy
- /// parameter can affect the compression ratio and the speed of
- /// compression but not the correctness of the compresssion. For more
- /// information see <see
- /// cref="Ionic.Zlib.CompressionStrategy">Ionic.Zlib.CompressionStrategy</see>.
- /// </remarks>
- public Ionic.Zlib.CompressionStrategy Strategy
- {
- get { return _Strategy; }
- set { _Strategy = value; }
- }
- /// <summary>
- /// The name of the <c>ZipFile</c>, on disk.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// When the <c>ZipFile</c> instance was created by reading an archive using
- /// one of the <c>ZipFile.Read</c> methods, this property represents the name
- /// of the zip file that was read. When the <c>ZipFile</c> instance was
- /// created by using the no-argument constructor, this value is <c>null</c>
- /// (<c>Nothing</c> in VB).
- /// </para>
- ///
- /// <para>
- /// If you use the no-argument constructor, and you then explicitly set this
- /// property, when you call <see cref="ZipFile.Save()"/>, this name will
- /// specify the name of the zip file created. Doing so is equivalent to
- /// calling <see cref="ZipFile.Save(String)"/>. When instantiating a
- /// <c>ZipFile</c> by reading from a stream or byte array, the <c>Name</c>
- /// property remains <c>null</c>. When saving to a stream, the <c>Name</c>
- /// property is implicitly set to <c>null</c>.
- /// </para>
- /// </remarks>
- public string Name
- {
- get { return _name; }
- set { _name = value; }
- }
- /// <summary>
- /// Sets the compression level to be used for entries subsequently added to
- /// the zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// Varying the compression level used on entries can affect the
- /// size-vs-speed tradeoff when compression and decompressing data streams
- /// or files.
- /// </para>
- ///
- /// <para>
- /// As with some other properties on the <c>ZipFile</c> class, like <see
- /// cref="Password"/>, <see cref="Encryption"/>, and <see
- /// cref="ZipErrorAction"/>, setting this property on a <c>ZipFile</c>
- /// instance will cause the specified <c>CompressionLevel</c> to be used on all
- /// <see cref="ZipEntry"/> items that are subsequently added to the
- /// <c>ZipFile</c> instance. If you set this property after you have added
- /// items to the <c>ZipFile</c>, but before you have called <c>Save()</c>,
- /// those items will not use the specified compression level.
- /// </para>
- ///
- /// <para>
- /// If you do not set this property, the default compression level is used,
- /// which normally gives a good balance of compression efficiency and
- /// compression speed. In some tests, using <c>BestCompression</c> can
- /// double the time it takes to compress, while delivering just a small
- /// increase in compression efficiency. This behavior will vary with the
- /// type of data you compress. If you are in doubt, just leave this setting
- /// alone, and accept the default.
- /// </para>
- /// </remarks>
- public Ionic.Zlib.CompressionLevel CompressionLevel
- {
- get;
- set;
- }
- /// <summary>
- /// The compression method for the zipfile.
- /// </summary>
- /// <remarks>
- /// <para>
- /// By default, the compression method is <c>CompressionMethod.Deflate.</c>
- /// </para>
- /// </remarks>
- /// <seealso cref="Ionic.Zip.CompressionMethod" />
- public Ionic.Zip.CompressionMethod CompressionMethod
- {
- get
- {
- return _compressionMethod;
- }
- set
- {
- _compressionMethod = value;
- }
- }
- /// <summary>
- /// A comment attached to the zip archive.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// This property is read/write. It allows the application to specify a
- /// comment for the <c>ZipFile</c>, or read the comment for the
- /// <c>ZipFile</c>. After setting this property, changes are only made
- /// permanent when you call a <c>Save()</c> method.
- /// </para>
- ///
- /// <para>
- /// According to <see
- /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
- /// zip specification</see>, the comment is not encrypted, even if there is a
- /// password set on the zip file.
- /// </para>
- ///
- /// <para>
- /// The specification does not describe how to indicate the encoding used
- /// on a comment string. Many "compliant" zip tools and libraries use
- /// IBM437 as the code page for comments; DotNetZip, too, follows that
- /// practice. On the other hand, there are situations where you want a
- /// Comment to be encoded with something else, for example using code page
- /// 950 "Big-5 Chinese". To fill that need, DotNetZip will encode the
- /// comment following the same procedure it follows for encoding
- /// filenames: (a) if <see cref="AlternateEncodingUsage"/> is
- /// <c>Never</c>, it uses the default encoding (IBM437). (b) if <see
- /// cref="AlternateEncodingUsage"/> is <c>Always</c>, it always uses the
- /// alternate encoding (<see cref="AlternateEncoding"/>). (c) if <see
- /// cref="AlternateEncodingUsage"/> is <c>AsNecessary</c>, it uses the
- /// alternate encoding only if the default encoding is not sufficient for
- /// encoding the comment - in other words if decoding the result does not
- /// produce the original string. This decision is taken at the time of
- /// the call to <c>ZipFile.Save()</c>.
- /// </para>
- ///
- /// <para>
- /// When creating a zip archive using this library, it is possible to change
- /// the value of <see cref="AlternateEncoding" /> between each
- /// entry you add, and between adding entries and the call to
- /// <c>Save()</c>. Don't do this. It will likely result in a zip file that is
- /// not readable by any tool or application. For best interoperability, leave
- /// <see cref="AlternateEncoding"/> alone, or specify it only
- /// once, before adding any entries to the <c>ZipFile</c> instance.
- /// </para>
- ///
- /// </remarks>
- public string Comment
- {
- get { return _Comment; }
- set
- {
- _Comment = value;
- _contentsChanged = true;
- }
- }
- /// <summary>
- /// Specifies whether the Creation, Access, and Modified times for entries
- /// added to the zip file will be emitted in “Windows format”
- /// when the zip archive is saved.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// An application creating a zip archive can use this flag to explicitly
- /// specify that the file times for the entries should or should not be stored
- /// in the zip archive in the format used by Windows. By default this flag is
- /// <c>true</c>, meaning the Windows-format times are stored in the zip
- /// archive.
- /// </para>
- ///
- /// <para>
- /// When adding an entry from a file or directory, the Creation (<see
- /// cref="ZipEntry.CreationTime"/>), Access (<see
- /// cref="ZipEntry.AccessedTime"/>), and Modified (<see
- /// cref="ZipEntry.ModifiedTime"/>) times for the given entry are
- /// automatically set from the filesystem values. When adding an entry from a
- /// stream or string, all three values are implicitly set to
- /// <c>DateTime.Now</c>. Applications can also explicitly set those times by
- /// calling <see cref="ZipEntry.SetEntryTimes(DateTime, DateTime,
- /// DateTime)"/>.
- /// </para>
- ///
- /// <para>
- /// <see
- /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
- /// zip specification</see> describes multiple ways to format these times in a
- /// zip file. One is the format Windows applications normally use: 100ns ticks
- /// since January 1, 1601 UTC. The other is a format Unix applications typically
- /// use: seconds since January 1, 1970 UTC. Each format can be stored in an
- /// "extra field" in the zip entry when saving the zip archive. The former
- /// uses an extra field with a Header Id of 0x000A, while the latter uses a
- /// header ID of 0x5455, although you probably don't need to know that.
- /// </para>
- ///
- /// <para>
- /// Not all tools and libraries can interpret these fields. Windows
- /// compressed folders is one that can read the Windows Format timestamps,
- /// while I believe <see href="http://www.info-zip.org/">the Infozip
- /// tools</see> can read the Unix format timestamps. Some tools and libraries
- /// may be able to read only one or the other. DotNetZip can read or write
- /// times in either or both formats.
- /// </para>
- ///
- /// <para>
- /// The times stored are taken from <see cref="ZipEntry.ModifiedTime"/>, <see
- /// cref="ZipEntry.AccessedTime"/>, and <see cref="ZipEntry.CreationTime"/>.
- /// </para>
- ///
- /// <para>
- /// The value set here applies to all entries subsequently added to the
- /// <c>ZipFile</c>.
- /// </para>
- ///
- /// <para>
- /// This property is not mutually exclusive of the <see
- /// cref="EmitTimesInUnixFormatWhenSaving" /> property. It is possible and
- /// legal and valid to produce a zip file that contains timestamps encoded in
- /// the Unix format as well as in the Windows format, in addition to the <see
- /// cref="ZipEntry.LastModified">LastModified</see> time attached to each
- /// entry in the archive, a time that is always stored in "DOS format". And,
- /// notwithstanding the names PKWare uses for these time formats, any of them
- /// can be read and written by any computer, on any operating system. But,
- /// there are no guarantees that a program running on Mac or Linux will
- /// gracefully handle a zip file with "Windows" formatted times, or that an
- /// application that does not use DotNetZip but runs on Windows will be able to
- /// handle file times in Unix format.
- /// </para>
- ///
- /// <para>
- /// When in doubt, test. Sorry, I haven't got a complete list of tools and
- /// which sort of timestamps they can use and will tolerate. If you get any
- /// good information and would like to pass it on, please do so and I will
- /// include that information in this documentation.
- /// </para>
- /// </remarks>
- ///
- /// <example>
- /// This example shows how to save a zip file that contains file timestamps
- /// in a format normally used by Unix.
- /// <code lang="C#">
- /// using (var zip = new ZipFile())
- /// {
- /// // produce a zip file the Mac will like
- /// zip.EmitTimesInWindowsFormatWhenSaving = false;
- /// zip.EmitTimesInUnixFormatWhenSaving = true;
- /// zip.AddDirectory(directoryToZip, "files");
- /// zip.Save(outputFile);
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As New ZipFile
- /// '' produce a zip file the Mac will like
- /// zip.EmitTimesInWindowsFormatWhenSaving = False
- /// zip.EmitTimesInUnixFormatWhenSaving = True
- /// zip.AddDirectory(directoryToZip, "files")
- /// zip.Save(outputFile)
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <seealso cref="ZipEntry.EmitTimesInWindowsFormatWhenSaving" />
- /// <seealso cref="EmitTimesInUnixFormatWhenSaving" />
- public bool EmitTimesInWindowsFormatWhenSaving
- {
- get
- {
- return _emitNtfsTimes;
- }
- set
- {
- _emitNtfsTimes = value;
- }
- }
- /// <summary>
- /// Specifies whether the Creation, Access, and Modified times
- /// for entries added to the zip file will be emitted in "Unix(tm)
- /// format" when the zip archive is saved.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// An application creating a zip archive can use this flag to explicitly
- /// specify that the file times for the entries should or should not be stored
- /// in the zip archive in the format used by Unix. By default this flag is
- /// <c>false</c>, meaning the Unix-format times are not stored in the zip
- /// archive.
- /// </para>
- ///
- /// <para>
- /// When adding an entry from a file or directory, the Creation (<see
- /// cref="ZipEntry.CreationTime"/>), Access (<see
- /// cref="ZipEntry.AccessedTime"/>), and Modified (<see
- /// cref="ZipEntry.ModifiedTime"/>) times for the given entry are
- /// automatically set from the filesystem values. When adding an entry from a
- /// stream or string, all three values are implicitly set to DateTime.Now.
- /// Applications can also explicitly set those times by calling <see
- /// cref="ZipEntry.SetEntryTimes(DateTime, DateTime, DateTime)"/>.
- /// </para>
- ///
- /// <para>
- /// <see
- /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
- /// zip specification</see> describes multiple ways to format these times in a
- /// zip file. One is the format Windows applications normally use: 100ns ticks
- /// since January 1, 1601 UTC. The other is a format Unix applications
- /// typically use: seconds since January 1, 1970 UTC. Each format can be
- /// stored in an "extra field" in the zip entry when saving the zip
- /// archive. The former uses an extra field with a Header Id of 0x000A, while
- /// the latter uses a header ID of 0x5455, although you probably don't need to
- /// know that.
- /// </para>
- ///
- /// <para>
- /// Not all tools and libraries can interpret these fields. Windows
- /// compressed folders is one that can read the Windows Format timestamps,
- /// while I believe the <see href="http://www.info-zip.org/">Infozip</see>
- /// tools can read the Unix format timestamps. Some tools and libraries may be
- /// able to read only one or the other. DotNetZip can read or write times in
- /// either or both formats.
- /// </para>
- ///
- /// <para>
- /// The times stored are taken from <see cref="ZipEntry.ModifiedTime"/>, <see
- /// cref="ZipEntry.AccessedTime"/>, and <see cref="ZipEntry.CreationTime"/>.
- /// </para>
- ///
- /// <para>
- /// This property is not mutually exclusive of the <see
- /// cref="EmitTimesInWindowsFormatWhenSaving" /> property. It is possible and
- /// legal and valid to produce a zip file that contains timestamps encoded in
- /// the Unix format as well as in the Windows format, in addition to the <see
- /// cref="ZipEntry.LastModified">LastModified</see> time attached to each
- /// entry in the zip archive, a time that is always stored in "DOS
- /// format". And, notwithstanding the names PKWare uses for these time
- /// formats, any of them can be read and written by any computer, on any
- /// operating system. But, there are no guarantees that a program running on
- /// Mac or Linux will gracefully handle a zip file with "Windows" formatted
- /// times, or that an application that does not use DotNetZip but runs on
- /// Windows will be able to handle file times in Unix format.
- /// </para>
- ///
- /// <para>
- /// When in doubt, test. Sorry, I haven't got a complete list of tools and
- /// which sort of timestamps they can use and will tolerate. If you get any
- /// good information and would like to pass it on, please do so and I will
- /// include that information in this documentation.
- /// </para>
- /// </remarks>
- ///
- /// <seealso cref="ZipEntry.EmitTimesInUnixFormatWhenSaving" />
- /// <seealso cref="EmitTimesInWindowsFormatWhenSaving" />
- public bool EmitTimesInUnixFormatWhenSaving
- {
- get
- {
- return _emitUnixTimes;
- }
- set
- {
- _emitUnixTimes = value;
- }
- }
- /// <summary>
- /// Indicates whether verbose output is sent to the <see
- /// cref="StatusMessageTextWriter"/> during <c>AddXxx()</c> and
- /// <c>ReadXxx()</c> operations.
- /// </summary>
- ///
- /// <remarks>
- /// This is a <em>synthetic</em> property. It returns true if the <see
- /// cref="StatusMessageTextWriter"/> is non-null.
- /// </remarks>
- internal bool Verbose
- {
- get { return (_StatusMessageTextWriter != null); }
- }
- /// <summary>
- /// Returns true if an entry by the given name exists in the ZipFile.
- /// </summary>
- ///
- /// <param name='name'>the name of the entry to find</param>
- /// <returns>true if an entry with the given name exists; otherwise false.
- /// </returns>
- public bool ContainsEntry(string name)
- {
- // workitem 12534
- return RetrievalEntries.ContainsKey(SharedUtilities.NormalizePathForUseInZipFile(name));
- }
- /// <summary>
- /// Indicates whether to perform case-sensitive matching on the filename when
- /// retrieving entries in the zipfile via the string-based indexer.
- /// </summary>
- ///
- /// <remarks>
- /// The default value is <c>false</c>, which means don't do case-sensitive
- /// matching. In other words, retrieving zip["ReadMe.Txt"] is the same as
- /// zip["readme.txt"]. It really makes sense to set this to <c>true</c> only
- /// if you are not running on Windows, which has case-insensitive
- /// filenames. But since this library is not built for non-Windows platforms,
- /// in most cases you should just leave this property alone.
- /// </remarks>
- public bool CaseSensitiveRetrieval
- {
- get
- {
- return _CaseSensitiveRetrieval;
- }
- set
- {
- _CaseSensitiveRetrieval = value;
- }
- }
- private Dictionary<string, ZipEntry> RetrievalEntries
- {
- get { return CaseSensitiveRetrieval ? _entries : _entriesInsensitive; }
- }
- /// <summary>
- /// Indicates whether to ignore duplicate files (report only the first entry)
- /// when loading a zipfile.
- /// </summary>
- ///
- /// <remarks>
- /// The default value is <c>false</c>, which will try to make all files
- /// available (duplicates will have a "copy" suffix appended to their name).
- /// Setting this to <c>true</c> prior to using <c>Initialize</c> to read a
- /// zipfile will prevent this and instead just ignore the duplicates.
- /// </remarks>
- public bool IgnoreDuplicateFiles
- {
- get { return _IgnoreDuplicateFiles; }
- set { _IgnoreDuplicateFiles = value; }
- }
- /// <summary>
- /// Indicates whether to encode entry filenames and entry comments using Unicode
- /// (UTF-8).
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">The
- /// PKWare zip specification</see> provides for encoding file names and file
- /// comments in either the IBM437 code page, or in UTF-8. This flag selects
- /// the encoding according to that specification. By default, this flag is
- /// false, and filenames and comments are encoded into the zip file in the
- /// IBM437 codepage. Setting this flag to true will specify that filenames
- /// and comments that cannot be encoded with IBM437 will be encoded with
- /// UTF-8.
- /// </para>
- ///
- /// <para>
- /// Zip files created with strict adherence to the PKWare specification with
- /// respect to UTF-8 encoding can contain entries with filenames containing
- /// any combination of Unicode characters, including the full range of
- /// characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other
- /// alphabets. However, because at this time, the UTF-8 portion of the PKWare
- /// specification is not broadly supported by other zip libraries and
- /// utilities, such zip files may not be readable by your favorite zip tool or
- /// archiver. In other words, interoperability will decrease if you set this
- /// flag to true.
- /// </para>
- ///
- /// <para>
- /// In particular, Zip files created with strict adherence to the PKWare
- /// specification with respect to UTF-8 encoding will not work well with
- /// Explorer in Windows XP or Windows Vista, because Windows compressed
- /// folders, as far as I know, do not support UTF-8 in zip files. Vista can
- /// read the zip files, but shows the filenames incorrectly. Unpacking from
- /// Windows Vista Explorer will result in filenames that have rubbish
- /// characters in place of the high-order UTF-8 bytes.
- /// </para>
- ///
- /// <para>
- /// Also, zip files that use UTF-8 encoding will not work well with Java
- /// applications that use the java.util.zip classes, as of v5.0 of the Java
- /// runtime. The Java runtime does not correctly implement the PKWare
- /// specification in this regard.
- /// </para>
- ///
- /// <para>
- /// As a result, we have the unfortunate situation that "correct" behavior by
- /// the DotNetZip library with regard to Unicode encoding of filenames during
- /// zip creation will result in zip files that are readable by strictly
- /// compliant and current tools (for example the most recent release of the
- /// commercial WinZip tool); but these zip files will not be readable by
- /// various other tools or libraries, including Windows Explorer.
- /// </para>
- ///
- /// <para>
- /// The DotNetZip library can read and write zip files with UTF8-encoded
- /// entries, according to the PKware spec. If you use DotNetZip for both
- /// creating and reading the zip file, and you use UTF-8, there will be no
- /// loss of information in the filenames. For example, using a self-extractor
- /// created by this library will allow you to unpack files correctly with no
- /// loss of information in the filenames.
- /// </para>
- ///
- /// <para>
- /// If you do not set this flag, it will remain false. If this flag is false,
- /// your <c>ZipFile</c> will encode all filenames and comments using the
- /// IBM437 codepage. This can cause "loss of information" on some filenames,
- /// but the resulting zipfile will be more interoperable with other
- /// utilities. As an example of the loss of information, diacritics can be
- /// lost. The o-tilde character will be down-coded to plain o. The c with a
- /// cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c.
- /// Likewise, the O-stroke character (Unicode 248), used in Danish and
- /// Norwegian, will be down-coded to plain o. Chinese characters cannot be
- /// represented in codepage IBM437; when using the default encoding, Chinese
- /// characters in filenames will be represented as ?. These are all examples
- /// of "information loss".
- /// </para>
- ///
- /// <para>
- /// The loss of information associated to the use of the IBM437 encoding is
- /// inconvenient, and can also lead to runtime errors. For example, using
- /// IBM437, any sequence of 4 Chinese characters will be encoded as ????. If
- /// your application creates a <c>ZipFile</c>, then adds two files, each with
- /// names of four Chinese characters each, this will result in a duplicate
- /// filename exception. In the case where you add a single file with a name
- /// containing four Chinese characters, calling Extract() on the entry that
- /// has question marks in the filename will result in an exception, because
- /// the question mark is not legal for use within filenames on Windows. These
- /// are just a few examples of the problems associated to loss of information.
- /// </para>
- ///
- /// <para>
- /// This flag is independent of the encoding of the content within the entries
- /// in the zip file. Think of the zip file as a container - it supports an
- /// encoding. Within the container are other "containers" - the file entries
- /// themselves. The encoding within those entries is independent of the
- /// encoding of the zip archive container for those entries.
- /// </para>
- ///
- /// <para>
- /// Rather than specify the encoding in a binary fashion using this flag, an
- /// application can specify an arbitrary encoding via the <see
- /// cref="ProvisionalAlternateEncoding"/> property. Setting the encoding
- /// explicitly when creating zip archives will result in non-compliant zip
- /// files that, curiously, are fairly interoperable. The challenge is, the
- /// PKWare specification does not provide for a way to specify that an entry
- /// in a zip archive uses a code page that is neither IBM437 nor UTF-8.
- /// Therefore if you set the encoding explicitly when creating a zip archive,
- /// you must take care upon reading the zip archive to use the same code page.
- /// If you get it wrong, the behavior is undefined and may result in incorrect
- /// filenames, exceptions, stomach upset, hair loss, and acne.
- /// </para>
- /// </remarks>
- /// <seealso cref="ProvisionalAlternateEncoding"/>
- [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.")]
- public bool UseUnicodeAsNecessary
- {
- get
- {
- return (_alternateEncoding == System.Text.Encoding.GetEncoding("UTF-8")) &&
- (_alternateEncodingUsage == ZipOption.AsNecessary);
- }
- set
- {
- if (value)
- {
- _alternateEncoding = System.Text.Encoding.GetEncoding("UTF-8");
- _alternateEncodingUsage = ZipOption.AsNecessary;
- }
- else
- {
- _alternateEncoding = Ionic.Zip.ZipFile.DefaultEncoding;
- _alternateEncodingUsage = ZipOption.Never;
- }
- }
- }
- /// <summary>
- /// Specify whether to use ZIP64 extensions when saving a zip archive.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// When creating a zip file, the default value for the property is <see
- /// cref="Zip64Option.Never"/>. <see cref="Zip64Option.AsNecessary"/> is
- /// safest, in the sense that you will not get an Exception if a pre-ZIP64
- /// limit is exceeded.
- /// </para>
- ///
- /// <para>
- /// You may set the property at any time before calling Save().
- /// </para>
- ///
- /// <para>
- /// When reading a zip file via the <c>Zipfile.Read()</c> method, DotNetZip
- /// will properly read ZIP64-endowed zip archives, regardless of the value of
- /// this property. DotNetZip will always read ZIP64 archives. This property
- /// governs only whether DotNetZip will write them. Therefore, when updating
- /// archives, be careful about setting this property after reading an archive
- /// that may use ZIP64 extensions.
- /// </para>
- ///
- /// <para>
- /// An interesting question is, if you have set this property to
- /// <c>AsNecessary</c>, and then successfully saved, does the resulting
- /// archive use ZIP64 extensions or not? To learn this, check the <see
- /// cref="OutputUsedZip64"/> property, after calling <c>Save()</c>.
- /// </para>
- ///
- /// <para>
- /// Have you thought about
- /// <see href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">donating</see>?
- /// </para>
- ///
- /// </remarks>
- /// <seealso cref="RequiresZip64"/>
- public Zip64Option UseZip64WhenSaving
- {
- get
- {
- return _zip64;
- }
- set
- {
- _zip64 = value;
- }
- }
- /// <summary>
- /// Indicates whether the archive requires ZIP64 extensions.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// This property is <c>null</c> (or <c>Nothing</c> in VB) if the archive has
- /// not been saved, and there are fewer than 65334 <c>ZipEntry</c> items
- /// contained in the archive.
- /// </para>
- ///
- /// <para>
- /// The <c>Value</c> is true if any of the following four conditions holds:
- /// the uncompressed size of any entry is larger than 0xFFFFFFFF; the
- /// compressed size of any entry is larger than 0xFFFFFFFF; the relative
- /// offset of any entry within the zip archive is larger than 0xFFFFFFFF; or
- /// there are more than 65534 entries in the archive. (0xFFFFFFFF =
- /// 4,294,967,295). The result may not be known until a <c>Save()</c> is attempted
- /// on the zip archive. The Value of this <see cref="System.Nullable"/>
- /// property may be set only AFTER one of the Save() methods has been called.
- /// </para>
- ///
- /// <para>
- /// If none of the four conditions holds, and the archive has been saved, then
- /// the <c>Value</c> is false.
- /// </para>
- ///
- /// <para>
- /// A <c>Value</c> of false does not indicate that the zip archive, as saved,
- /// does not use ZIP64. It merely indicates that ZIP64 is not required. An
- /// archive may use ZIP64 even when not required if the <see
- /// cref="ZipFile.UseZip64WhenSaving"/> property is set to <see
- /// cref="Zip64Option.Always"/>, or if the <see
- /// cref="ZipFile.UseZip64WhenSaving"/> property is set to <see
- /// cref="Zip64Option.AsNecessary"/> and the output stream was not
- /// seekable. Use the <see cref="OutputUsedZip64"/> property to determine if
- /// the most recent <c>Save()</c> method resulted in an archive that utilized
- /// the ZIP64 extensions.
- /// </para>
- ///
- /// </remarks>
- /// <seealso cref="UseZip64WhenSaving"/>
- /// <seealso cref="OutputUsedZip64"/>
- public Nullable<bool> RequiresZip64
- {
- get
- {
- if (_entries.Count > 65534)
- return new Nullable<bool>(true);
- // If the <c>ZipFile</c> has not been saved or if the contents have changed, then
- // it is not known if ZIP64 is required.
- if (!_hasBeenSaved || _contentsChanged) return null;
- // Whether ZIP64 is required is knowable.
- foreach (ZipEntry e in _entries.Values)
- {
- if (e.RequiresZip64.Value) return new Nullable<bool>(true);
- }
- return new Nullable<bool>(false);
- }
- }
- /// <summary>
- /// Indicates whether the most recent <c>Save()</c> operation used ZIP64 extensions.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// The use of ZIP64 extensions within an archive is not always necessary, and
- /// for interoperability concerns, it may be desired to NOT use ZIP64 if
- /// possible. The <see cref="ZipFile.UseZip64WhenSaving"/> property can be
- /// set to use ZIP64 extensions only when necessary. In those cases,
- /// Sometimes applications want to know whether a Save() actually used ZIP64
- /// extensions. Applications can query this read-only property to learn
- /// whether ZIP64 has been used in a just-saved <c>ZipFile</c>.
- /// </para>
- ///
- /// <para>
- /// The value is <c>null</c> (or <c>Nothing</c> in VB) if the archive has not
- /// been saved.
- /// </para>
- ///
- /// <para>
- /// Non-null values (<c>HasValue</c> is true) indicate whether ZIP64
- /// extensions were used during the most recent <c>Save()</c> operation. The
- /// ZIP64 extensions may have been used as required by any particular entry
- /// because of its uncompressed or compressed size, or because the archive is
- /// larger than 4294967295 bytes, or because there are more than 65534 entries
- /// in the archive, or because the <c>UseZip64WhenSaving</c> property was set
- /// to <see cref="Zip64Option.Always"/>, or because the
- /// <c>UseZip64WhenSaving</c> property was set to <see
- /// cref="Zip64Option.AsNecessary"/> and the output stream was not seekable.
- /// The value of this property does not indicate the reason the ZIP64
- /// extensions were used.
- /// </para>
- ///
- /// </remarks>
- /// <seealso cref="UseZip64WhenSaving"/>
- /// <seealso cref="RequiresZip64"/>
- public Nullable<bool> OutputUsedZip64
- {
- get
- {
- return _OutputUsesZip64;
- }
- }
- /// <summary>
- /// Indicates whether the most recent <c>Read()</c> operation read a zip file that uses
- /// ZIP64 extensions.
- /// </summary>
- ///
- /// <remarks>
- /// This property will return null (Nothing in VB) if you've added an entry after reading
- /// the zip file.
- /// </remarks>
- public Nullable<bool> InputUsesZip64
- {
- get
- {
- if (_entries.Count > 65534)
- return true;
- foreach (ZipEntry e in this)
- {
- // if any entry was added after reading the zip file, then the result is null
- if (e.Source != ZipEntrySource.ZipFile) return null;
- // if any entry read from the zip used zip64, then the result is true
- if (e._InputUsesZip64) return true;
- }
- return false;
- }
- }
- /// <summary>
- /// The text encoding to use when writing new entries to the <c>ZipFile</c>,
- /// for those entries that cannot be encoded with the default (IBM437)
- /// encoding; or, the text encoding that was used when reading the entries
- /// from the <c>ZipFile</c>.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// In <see href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">its
- /// zip specification</see>, PKWare describes two options for encoding
- /// filenames and comments: using IBM437 or UTF-8. But, some archiving tools
- /// or libraries do not follow the specification, and instead encode
- /// characters using the system default code page. For example, WinRAR when
- /// run on a machine in Shanghai may encode filenames with the Big-5 Chinese
- /// (950) code page. This behavior is contrary to the Zip specification, but
- /// it occurs anyway.
- /// </para>
- ///
- /// <para>
- /// When using DotNetZip to write zip archives that will be read by one of
- /// these other archivers, set this property to specify the code page to use
- /// when encoding the <see cref="ZipEntry.FileName"/> and <see
- /// cref="ZipEntry.Comment"/> for each <c>ZipEntry</c> in the zip file, for
- /// values that cannot be encoded with the default codepage for zip files,
- /// IBM437. This is why this property is "provisional". In all cases, IBM437
- /// is used where possible, in other words, where no loss of data would
- /// result. It is possible, therefore, to have a given entry with a
- /// <c>Comment</c> encoded in IBM437 and a <c>FileName</c> encoded with the
- /// specified "provisional" codepage.
- /// </para>
- ///
- /// <para>
- /// Be aware that a zip file created after you've explicitly set the <see
- /// cref="ProvisionalAlternateEncoding" /> property to a value other than
- /// IBM437 may not be compliant to the PKWare specification, and may not be
- /// readable by compliant archivers. On the other hand, many (most?)
- /// archivers are non-compliant and can read zip files created in arbitrary
- /// code pages. The trick is to use or specify the proper codepage when
- /// reading the zip.
- /// </para>
- ///
- /// <para>
- /// When creating a zip archive using this library, it is possible to change
- /// the value of <see cref="ProvisionalAlternateEncoding" /> between each
- /// entry you add, and between adding entries and the call to
- /// <c>Save()</c>. Don't do this. It will likely result in a zipfile that is
- /// not readable. For best interoperability, either leave <see
- /// cref="ProvisionalAlternateEncoding" /> alone, or specify it only once,
- /// before adding any entries to the <c>ZipFile</c> instance. There is one
- /// exception to this recommendation, described later.
- /// </para>
- ///
- /// <para>
- /// When using an arbitrary, non-UTF8 code page for encoding, there is no
- /// standard way for the creator application - whether DotNetZip, WinZip,
- /// WinRar, or something else - to formally specify in the zip file which
- /// codepage has been used for the entries. As a result, readers of zip files
- /// are not able to inspect the zip file and determine the codepage that was
- /// used for the entries contained within it. It is left to the application
- /// or user to determine the necessary codepage when reading zip files encoded
- /// this way. In other words, if you explicitly specify the codepage when you
- /// create the zipfile, you must explicitly specify the same codepage when
- /// reading the zipfile.
- /// </para>
- ///
- /// <para>
- /// The way you specify the code page to use when reading a zip file varies
- /// depending on the tool or library you use to read the zip. In DotNetZip,
- /// you use a ZipFile.Read() method that accepts an encoding parameter. It
- /// isn't possible with Windows Explorer, as far as I know, to specify an
- /// explicit codepage to use when reading a zip. If you use an incorrect
- /// codepage when reading a zipfile, you will get entries with filenames that
- /// are incorrect, and the incorrect filenames may even contain characters
- /// that are not legal for use within filenames in Windows. Extracting entries
- /// with illegal characters in the filenames will lead to exceptions. It's too
- /// bad, but this is just the way things are with code pages in zip
- /// files. Caveat Emptor.
- /// </para>
- ///
- /// <para>
- /// Example: Suppose you create a zipfile that contains entries with
- /// filenames that have Danish characters. If you use <see
- /// cref="ProvisionalAlternateEncoding" /> equal to "iso-8859-1" (cp 28591),
- /// the filenames will be correctly encoded in the zip. But, to read that
- /// zipfile correctly, you have to specify the same codepage at the time you
- /// read it. If try to read that zip file with Windows Explorer or another
- /// application that is not flexible with respect to the codepage used to
- /// decode filenames in zipfiles, you will get a filename like "Inf°.txt".
- /// </para>
- ///
- /// <para>
- /// When using DotNetZip to read a zip archive, and the zip archive uses an
- /// arbitrary code page, you must specify the encoding to use before or when
- /// the <c>Zipfile</c> is READ. This means you must use a <c>ZipFile.Read()</c>
- /// method that allows you to specify a System.Text.Encoding parameter. Setting
- /// the ProvisionalAlternateEncoding property after your application has read in
- /// the zip archive will not affect the entry names of entries that have already
- /// been read in.
- /// </para>
- ///
- /// <para>
- /// And now, the exception to the rule described above. One strategy for
- /// specifying the code page for a given zip file is to describe the code page
- /// in a human-readable form in the Zip comment. For example, the comment may
- /// read "Entries in this archive are encoded in the Big5 code page". For
- /// maximum interoperability, the zip comment in this case should be encoded
- /// in the default, IBM437 code page. In this case, the zip comment is
- /// encoded using a different page than the filenames. To do this, Specify
- /// <c>ProvisionalAlternateEncoding</c> to your desired region-specific code
- /// page, once before adding any entries, and then reset
- /// <c>ProvisionalAlternateEncoding</c> to IBM437 before setting the <see
- /// cref="Comment"/> property and calling Save().
- /// </para>
- /// </remarks>
- ///
- /// <example>
- /// This example shows how to read a zip file using the Big-5 Chinese code page
- /// (950), and extract each entry in the zip file. For this code to work as
- /// desired, the <c>Zipfile</c> must have been created using the big5 code page
- /// (CP950). This is typical, for example, when using WinRar on a machine with
- /// CP950 set as the default code page. In that case, the names of entries
- /// within the Zip archive will be stored in that code page, and reading the zip
- /// archive must be done using that code page. If the application did not use
- /// the correct code page in <c>ZipFile.Read()</c>, then names of entries within the
- /// zip archive would not be correctly retrieved.
- /// <code>
- /// using (var zip = ZipFile.Read(zipFileName, System.Text.Encoding.GetEncoding("big5")))
- /// {
- /// // retrieve and extract an entry using a name encoded with CP950
- /// zip[MyDesiredEntry].Extract("unpack");
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As ZipFile = ZipFile.Read(ZipToExtract, System.Text.Encoding.GetEncoding("big5"))
- /// ' retrieve and extract an entry using a name encoded with CP950
- /// zip(MyDesiredEntry).Extract("unpack")
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.DefaultEncoding">DefaultEncoding</seealso>
- [Obsolete("use AlternateEncoding instead.")]
- public System.Text.Encoding ProvisionalAlternateEncoding
- {
- get
- {
- if (_alternateEncodingUsage == ZipOption.AsNecessary)
- return _alternateEncoding;
- return null;
- }
- set
- {
- _alternateEncoding = value;
- _alternateEncodingUsage = ZipOption.AsNecessary;
- }
- }
- /// <summary>
- /// A Text Encoding to use when encoding the filenames and comments for
- /// all the ZipEntry items, during a ZipFile.Save() operation.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Whether the encoding specified here is used during the save depends
- /// on <see cref="AlternateEncodingUsage"/>.
- /// </para>
- /// </remarks>
- public System.Text.Encoding AlternateEncoding
- {
- get
- {
- return _alternateEncoding;
- }
- set
- {
- _alternateEncoding = value;
- }
- }
- /// <summary>
- /// A flag that tells if and when this instance should apply
- /// AlternateEncoding to encode the filenames and comments associated to
- /// of ZipEntry objects contained within this instance.
- /// </summary>
- public ZipOption AlternateEncodingUsage
- {
- get
- {
- return _alternateEncodingUsage;
- }
- set
- {
- _alternateEncodingUsage = value;
- }
- }
-
- /// <summary>
- /// Gets or sets the <c>TextWriter</c> to which status messages are delivered
- /// for the instance.
- /// </summary>
- ///
- /// <remarks>
- /// If the TextWriter is set to a non-null value, then verbose output is sent
- /// to the <c>TextWriter</c> during <c>Add</c><c>, Read</c><c>, Save</c> and
- /// <c>Extract</c> operations. Typically, console applications might use
- /// <c>Console.Out</c> and graphical or headless applications might use a
- /// <c>System.IO.StringWriter</c>. The output of this is suitable for viewing
- /// by humans.
- /// </remarks>
- ///
- /// <example>
- /// <para>
- /// In this example, a console application instantiates a <c>ZipFile</c>, then
- /// sets the <c>StatusMessageTextWriter</c> to <c>Console.Out</c>. At that
- /// point, all verbose status messages for that <c>ZipFile</c> are sent to the
- /// console.
- /// </para>
- ///
- /// <code lang="C#">
- /// using (ZipFile zip= ZipFile.Read(FilePath))
- /// {
- /// zip.StatusMessageTextWriter= System.Console.Out;
- /// // messages are sent to the console during extraction
- /// zip.ExtractAll();
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As ZipFile = ZipFile.Read(FilePath)
- /// zip.StatusMessageTextWriter= System.Console.Out
- /// 'Status Messages will be sent to the console during extraction
- /// zip.ExtractAll()
- /// End Using
- /// </code>
- ///
- /// <para>
- /// In this example, a Windows Forms application instantiates a
- /// <c>ZipFile</c>, then sets the <c>StatusMessageTextWriter</c> to a
- /// <c>StringWriter</c>. At that point, all verbose status messages for that
- /// <c>ZipFile</c> are sent to the <c>StringWriter</c>.
- /// </para>
- ///
- /// <code lang="C#">
- /// var sw = new System.IO.StringWriter();
- /// using (ZipFile zip= ZipFile.Read(FilePath))
- /// {
- /// zip.StatusMessageTextWriter= sw;
- /// zip.ExtractAll();
- /// }
- /// Console.WriteLine("{0}", sw.ToString());
- /// </code>
- ///
- /// <code lang="VB">
- /// Dim sw as New System.IO.StringWriter
- /// Using zip As ZipFile = ZipFile.Read(FilePath)
- /// zip.StatusMessageTextWriter= sw
- /// zip.ExtractAll()
- /// End Using
- /// 'Status Messages are now available in sw
- ///
- /// </code>
- /// </example>
- public TextWriter StatusMessageTextWriter
- {
- get { return _StatusMessageTextWriter; }
- set { _StatusMessageTextWriter = value; }
- }
- /// <summary>
- /// Gets or sets the name for the folder to store the temporary file
- /// this library writes when saving a zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This library will create a temporary file when saving a Zip archive to a
- /// file. This file is written when calling one of the <c>Save()</c> methods
- /// that does not save to a stream, or one of the <c>SaveSelfExtractor()</c>
- /// methods.
- /// </para>
- ///
- /// <para>
- /// By default, the library will create the temporary file in the directory
- /// specified for the file itself, via the <see cref="Name"/> property or via
- /// the <see cref="ZipFile.Save(String)"/> method.
- /// </para>
- ///
- /// <para>
- /// Setting this property allows applications to override this default
- /// behavior, so that the library will create the temporary file in the
- /// specified folder. For example, to have the library create the temporary
- /// file in the current working directory, regardless where the <c>ZipFile</c>
- /// is saved, specfy ".". To revert to the default behavior, set this
- /// property to <c>null</c> (<c>Nothing</c> in VB).
- /// </para>
- ///
- /// <para>
- /// When setting the property to a non-null value, the folder specified must
- /// exist; if it does not an exception is thrown. The application should have
- /// write and delete permissions on the folder. The permissions are not
- /// explicitly checked ahead of time; if the application does not have the
- /// appropriate rights, an exception will be thrown at the time <c>Save()</c>
- /// is called.
- /// </para>
- ///
- /// <para>
- /// There is no temporary file created when reading a zip archive. When
- /// saving to a Stream, there is no temporary file created. For example, if
- /// the application is an ASP.NET application and calls <c>Save()</c>
- /// specifying the <c>Response.OutputStream</c> as the output stream, there is
- /// no temporary file created.
- /// </para>
- /// </remarks>
- ///
- /// <exception cref="System.IO.FileNotFoundException">
- /// Thrown when setting the property if the directory does not exist.
- /// </exception>
- ///
- public String TempFileFolder
- {
- get { return _TempFileFolder; }
- set
- {
- _TempFileFolder = value;
- if (value == null) return;
- if (!Directory.Exists(value))
- throw new FileNotFoundException(String.Format("That directory ({0}) does not exist.", value));
- }
- }
- /// <summary>
- /// Sets the password to be used on the <c>ZipFile</c> instance.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// When writing a zip archive, this password is applied to the entries, not
- /// to the zip archive itself. It applies to any <c>ZipEntry</c> subsequently
- /// added to the <c>ZipFile</c>, using one of the <c>AddFile</c>,
- /// <c>AddDirectory</c>, <c>AddEntry</c>, or <c>AddItem</c> methods, etc.
- /// When reading a zip archive, this property applies to any entry
- /// subsequently extracted from the <c>ZipFile</c> using one of the Extract
- /// methods on the <c>ZipFile</c> class.
- /// </para>
- ///
- /// <para>
- /// When writing a zip archive, keep this in mind: though the password is set
- /// on the ZipFile object, according to the Zip spec, the "directory" of the
- /// archive - in other words the list of entries or files contained in the archive - is
- /// not encrypted with the password, or protected in any way. If you set the
- /// Password property, the password actually applies to individual entries
- /// that are added to the archive, subsequent to the setting of this property.
- /// The list of filenames in the archive that is eventually created will
- /// appear in clear text, but the contents of the individual files are
- /// encrypted. This is how Zip encryption works.
- /// </para>
- ///
- /// <para>
- /// One simple way around this limitation is to simply double-wrap sensitive
- /// filenames: Store the files in a zip file, and then store that zip file
- /// within a second, "outer" zip file. If you apply a password to the outer
- /// zip file, then readers will be able to see that the outer zip file
- /// contains an inner zip file. But readers will not be able to read the
- /// directory or file list of the inner zip file.
- /// </para>
- ///
- /// <para>
- /// If you set the password on the <c>ZipFile</c>, and then add a set of files
- /// to the archive, then each entry is encrypted with that password. You may
- /// also want to change the password between adding different entries. If you
- /// set the password, add an entry, then set the password to <c>null</c>
- /// (<c>Nothing</c> in VB), and add another entry, the first entry is
- /// encrypted and the second is not. If you call <c>AddFile()</c>, then set
- /// the <c>Password</c> property, then call <c>ZipFile.Save</c>, the file
- /// added will not be password-protected, and no warning will be generated.
- /// </para>
- ///
- /// <para>
- /// When setting the Password, you may also want to explicitly set the <see
- /// cref="Encryption"/> property, to specify how to encrypt the entries added
- /// to the ZipFile. If you set the Password to a non-null value and do not
- /// set <see cref="Encryption"/>, then PKZip 2.0 ("Weak") encryption is used.
- /// This encryption is relatively weak but is very interoperable. If you set
- /// the password to a <c>null</c> value (<c>Nothing</c> in VB), Encryption is
- /// reset to None.
- /// </para>
- ///
- /// <para>
- /// All of the preceding applies to writing zip archives, in other words when
- /// you use one of the Save methods. To use this property when reading or an
- /// existing ZipFile, do the following: set the Password property on the
- /// <c>ZipFile</c>, then call one of the Extract() overloads on the <see
- /// cref="ZipEntry" />. In this case, the entry is extracted using the
- /// <c>Password</c> that is specified on the <c>ZipFile</c> instance. If you
- /// have not set the <c>Password</c> property, then the password is
- /// <c>null</c>, and the entry is extracted with no password.
- /// </para>
- ///
- /// <para>
- /// If you set the Password property on the <c>ZipFile</c>, then call
- /// <c>Extract()</c> an entry that has not been encrypted with a password, the
- /// password is not used for that entry, and the <c>ZipEntry</c> is extracted
- /// as normal. In other words, the password is used only if necessary.
- /// </para>
- ///
- /// <para>
- /// The <see cref="ZipEntry"/> class also has a <see
- /// cref="ZipEntry.Password">Password</see> property. It takes precedence
- /// over this property on the <c>ZipFile</c>. Typically, you would use the
- /// per-entry Password when most entries in the zip archive use one password,
- /// and a few entries use a different password. If all entries in the zip
- /// file use the same password, then it is simpler to just set this property
- /// on the <c>ZipFile</c> itself, whether creating a zip archive or extracting
- /// a zip archive.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// <para>
- /// This example creates a zip file, using password protection for the
- /// entries, and then extracts the entries from the zip file. When creating
- /// the zip file, the Readme.txt file is not protected with a password, but
- /// the other two are password-protected as they are saved. During extraction,
- /// each file is extracted with the appropriate password.
- /// </para>
- /// <code>
- /// // create a file with encryption
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// zip.AddFile("ReadMe.txt");
- /// zip.Password= "!Secret1";
- /// zip.AddFile("MapToTheSite-7440-N49th.png");
- /// zip.AddFile("2008-Regional-Sales-Report.pdf");
- /// zip.Save("EncryptedArchive.zip");
- /// }
- ///
- /// // extract entries that use encryption
- /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
- /// {
- /// zip.Password= "!Secret1";
- /// zip.ExtractAll("extractDir");
- /// }
- ///
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As New ZipFile
- /// zip.AddFile("ReadMe.txt")
- /// zip.Password = "123456!"
- /// zip.AddFile("MapToTheSite-7440-N49th.png")
- /// zip.Password= "!Secret1";
- /// zip.AddFile("2008-Regional-Sales-Report.pdf")
- /// zip.Save("EncryptedArchive.zip")
- /// End Using
- ///
- ///
- /// ' extract entries that use encryption
- /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
- /// zip.Password= "!Secret1"
- /// zip.ExtractAll("extractDir")
- /// End Using
- ///
- /// </code>
- ///
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.Encryption">ZipFile.Encryption</seealso>
- /// <seealso cref="Ionic.Zip.ZipEntry.Password">ZipEntry.Password</seealso>
- public String Password
- {
- set
- {
- _Password = value;
- if (_Password == null)
- {
- Encryption = EncryptionAlgorithm.None;
- }
- else if (Encryption == EncryptionAlgorithm.None)
- {
- Encryption = EncryptionAlgorithm.PkzipWeak;
- }
- }
- private get
- {
- return _Password;
- }
- }
- /// <summary>
- /// The action the library should take when extracting a file that already
- /// exists.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This property affects the behavior of the Extract methods (one of the
- /// <c>Extract()</c> or <c>ExtractWithPassword()</c> overloads), when
- /// extraction would would overwrite an existing filesystem file. If you do
- /// not set this property, the library throws an exception when extracting an
- /// entry would overwrite an existing file.
- /// </para>
- ///
- /// <para>
- /// This property has no effect when extracting to a stream, or when the file
- /// to be extracted does not already exist.
- /// </para>
- /// </remarks>
- /// <seealso cref="Ionic.Zip.ZipEntry.ExtractExistingFile"/>
- public ExtractExistingFileAction ExtractExistingFile
- {
- get;
- set;
- }
- /// <summary>
- /// The action the library should take when an error is encountered while
- /// opening or reading files as they are saved into a zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// Errors can occur as a file is being saved to the zip archive. For
- /// example, the File.Open may fail, or a File.Read may fail, because of
- /// lock conflicts or other reasons.
- /// </para>
- ///
- /// <para>
- /// The first problem might occur after having called AddDirectory() on a
- /// directory that contains a Clipper .dbf file; the file is locked by
- /// Clipper and cannot be opened for read by another process. An example of
- /// the second problem might occur when trying to zip a .pst file that is in
- /// use by Microsoft Outlook. Outlook locks a range on the file, which allows
- /// other processes to open the file, but not read it in its entirety.
- /// </para>
- ///
- /// <para>
- /// This property tells DotNetZip what you would like to do in the case of
- /// these errors. The primary options are: <c>ZipErrorAction.Throw</c> to
- /// throw an exception (this is the default behavior if you don't set this
- /// property); <c>ZipErrorAction.Skip</c> to Skip the file for which there
- /// was an error and continue saving; <c>ZipErrorAction.Retry</c> to Retry
- /// the entry that caused the problem; or
- /// <c>ZipErrorAction.InvokeErrorEvent</c> to invoke an event handler.
- /// </para>
- ///
- /// <para>
- /// This property is implicitly set to <c>ZipErrorAction.InvokeErrorEvent</c>
- /// if you add a handler to the <see cref="ZipError" /> event. If you set
- /// this property to something other than
- /// <c>ZipErrorAction.InvokeErrorEvent</c>, then the <c>ZipError</c>
- /// event is implicitly cleared. What it means is you can set one or the
- /// other (or neither), depending on what you want, but you never need to set
- /// both.
- /// </para>
- ///
- /// <para>
- /// As with some other properties on the <c>ZipFile</c> class, like <see
- /// cref="Password"/>, <see cref="Encryption"/>, and <see
- /// cref="CompressionLevel"/>, setting this property on a <c>ZipFile</c>
- /// instance will cause the specified <c>ZipErrorAction</c> to be used on all
- /// <see cref="ZipEntry"/> items that are subsequently added to the
- /// <c>ZipFile</c> instance. If you set this property after you have added
- /// items to the <c>ZipFile</c>, but before you have called <c>Save()</c>,
- /// those items will not use the specified error handling action.
- /// </para>
- ///
- /// <para>
- /// If you want to handle any errors that occur with any entry in the zip
- /// file in the same way, then set this property once, before adding any
- /// entries to the zip archive.
- /// </para>
- ///
- /// <para>
- /// If you set this property to <c>ZipErrorAction.Skip</c> and you'd like to
- /// learn which files may have been skipped after a <c>Save()</c>, you can
- /// set the <see cref="StatusMessageTextWriter" /> on the ZipFile before
- /// calling <c>Save()</c>. A message will be emitted into that writer for
- /// each skipped file, if any.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// This example shows how to tell DotNetZip to skip any files for which an
- /// error is generated during the Save().
- /// <code lang="VB">
- /// Public Sub SaveZipFile()
- /// Dim SourceFolder As String = "fodder"
- /// Dim DestFile As String = "eHandler.zip"
- /// Dim sw as New StringWriter
- /// Using zipArchive As ZipFile = New ZipFile
- /// ' Tell DotNetZip to skip any files for which it encounters an error
- /// zipArchive.ZipErrorAction = ZipErrorAction.Skip
- /// zipArchive.StatusMessageTextWriter = sw
- /// zipArchive.AddDirectory(SourceFolder)
- /// zipArchive.Save(DestFile)
- /// End Using
- /// ' examine sw here to see any messages
- /// End Sub
- ///
- /// </code>
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipEntry.ZipErrorAction"/>
- /// <seealso cref="Ionic.Zip.ZipFile.ZipError"/>
- public ZipErrorAction ZipErrorAction
- {
- get
- {
- if (ZipError != null)
- _zipErrorAction = ZipErrorAction.InvokeErrorEvent;
- return _zipErrorAction;
- }
- set
- {
- _zipErrorAction = value;
- if (_zipErrorAction != ZipErrorAction.InvokeErrorEvent && ZipError != null)
- ZipError = null;
- }
- }
- /// <summary>
- /// The Encryption to use for entries added to the <c>ZipFile</c>.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// Set this when creating a zip archive, or when updating a zip archive. The
- /// specified Encryption is applied to the entries subsequently added to the
- /// <c>ZipFile</c> instance. Applications do not need to set the
- /// <c>Encryption</c> property when reading or extracting a zip archive.
- /// </para>
- ///
- /// <para>
- /// If you set this to something other than EncryptionAlgorithm.None, you
- /// will also need to set the <see cref="Password"/>.
- /// </para>
- ///
- /// <para>
- /// As with some other properties on the <c>ZipFile</c> class, like <see
- /// cref="Password"/> and <see cref="CompressionLevel"/>, setting this
- /// property on a <c>ZipFile</c> instance will cause the specified
- /// <c>EncryptionAlgorithm</c> to be used on all <see cref="ZipEntry"/> items
- /// that are subsequently added to the <c>ZipFile</c> instance. In other
- /// words, if you set this property after you have added items to the
- /// <c>ZipFile</c>, but before you have called <c>Save()</c>, those items will
- /// not be encrypted or protected with a password in the resulting zip
- /// archive. To get a zip archive with encrypted entries, set this property,
- /// along with the <see cref="Password"/> property, before calling
- /// <c>AddFile</c>, <c>AddItem</c>, or <c>AddDirectory</c> (etc.) on the
- /// <c>ZipFile</c> instance.
- /// </para>
- ///
- /// <para>
- /// If you read a <c>ZipFile</c>, you can modify the <c>Encryption</c> on an
- /// encrypted entry, only by setting the <c>Encryption</c> property on the
- /// <c>ZipEntry</c> itself. Setting the <c>Encryption</c> property on the
- /// <c>ZipFile</c>, once it has been created via a call to
- /// <c>ZipFile.Read()</c>, does not affect entries that were previously read.
- /// </para>
- ///
- /// <para>
- /// For example, suppose you read a <c>ZipFile</c>, and there is an encrypted
- /// entry. Setting the <c>Encryption</c> property on that <c>ZipFile</c> and
- /// then calling <c>Save()</c> on the <c>ZipFile</c> does not update the
- /// <c>Encryption</c> used for the entries in the archive. Neither is an
- /// exception thrown. Instead, what happens during the <c>Save()</c> is that
- /// all previously existing entries are copied through to the new zip archive,
- /// with whatever encryption and password that was used when originally
- /// creating the zip archive. Upon re-reading that archive, to extract
- /// entries, applications should use the original password or passwords, if
- /// any.
- /// </para>
- ///
- /// <para>
- /// Suppose an application reads a <c>ZipFile</c>, and there is an encrypted
- /// entry. Setting the <c>Encryption</c> property on that <c>ZipFile</c> and
- /// then adding new entries (via <c>AddFile()</c>, <c>AddEntry()</c>, etc)
- /// and then calling <c>Save()</c> on the <c>ZipFile</c> does not update the
- /// <c>Encryption</c> on any of the entries that had previously been in the
- /// <c>ZipFile</c>. The <c>Encryption</c> property applies only to the
- /// newly-added entries.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// <para>
- /// This example creates a zip archive that uses encryption, and then extracts
- /// entries from the archive. When creating the zip archive, the ReadMe.txt
- /// file is zipped without using a password or encryption. The other files
- /// use encryption.
- /// </para>
- ///
- /// <code>
- /// // Create a zip archive with AES Encryption.
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// zip.AddFile("ReadMe.txt");
- /// zip.Encryption= EncryptionAlgorithm.WinZipAes256;
- /// zip.Password= "Top.Secret.No.Peeking!";
- /// zip.AddFile("7440-N49th.png");
- /// zip.AddFile("2008-Regional-Sales-Report.pdf");
- /// zip.Save("EncryptedArchive.zip");
- /// }
- ///
- /// // Extract a zip archive that uses AES Encryption.
- /// // You do not need to specify the algorithm during extraction.
- /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip"))
- /// {
- /// zip.Password= "Top.Secret.No.Peeking!";
- /// zip.ExtractAll("extractDirectory");
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// ' Create a zip that uses Encryption.
- /// Using zip As New ZipFile()
- /// zip.Encryption= EncryptionAlgorithm.WinZipAes256
- /// zip.Password= "Top.Secret.No.Peeking!"
- /// zip.AddFile("ReadMe.txt")
- /// zip.AddFile("7440-N49th.png")
- /// zip.AddFile("2008-Regional-Sales-Report.pdf")
- /// zip.Save("EncryptedArchive.zip")
- /// End Using
- ///
- /// ' Extract a zip archive that uses AES Encryption.
- /// ' You do not need to specify the algorithm during extraction.
- /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip"))
- /// zip.Password= "Top.Secret.No.Peeking!"
- /// zip.ExtractAll("extractDirectory")
- /// End Using
- /// </code>
- ///
- /// </example>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.Password">ZipFile.Password</seealso>
- /// <seealso cref="Ionic.Zip.ZipEntry.Encryption">ZipEntry.Encryption</seealso>
- public EncryptionAlgorithm Encryption
- {
- get
- {
- return _Encryption;
- }
- set
- {
- if (value == EncryptionAlgorithm.Unsupported)
- throw new InvalidOperationException("You may not set Encryption to that value.");
- _Encryption = value;
- }
- }
- /// <summary>
- /// A callback that allows the application to specify the compression level
- /// to use for entries subsequently added to the zip archive.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// With this callback, the DotNetZip library allows the application to
- /// determine whether compression will be used, at the time of the
- /// <c>Save</c>. This may be useful if the application wants to favor
- /// speed over size, and wants to defer the decision until the time of
- /// <c>Save</c>.
- /// </para>
- ///
- /// <para>
- /// Typically applications set the <see cref="CompressionLevel"/> property on
- /// the <c>ZipFile</c> or on each <c>ZipEntry</c> to determine the level of
- /// compression used. This is done at the time the entry is added to the
- /// <c>ZipFile</c>. Setting the property to
- /// <c>Ionic.Zlib.CompressionLevel.None</c> means no compression will be used.
- /// </para>
- ///
- /// <para>
- /// This callback allows the application to defer the decision on the
- /// <c>CompressionLevel</c> to use, until the time of the call to
- /// <c>ZipFile.Save()</c>. The callback is invoked once per <c>ZipEntry</c>,
- /// at the time the data for the entry is being written out as part of a
- /// <c>Save()</c> operation. The application can use whatever criteria it
- /// likes in determining the level to return. For example, an application may
- /// wish that no .mp3 files should be compressed, because they are already
- /// compressed and the extra compression is not worth the CPU time incurred,
- /// and so can return <c>None</c> for all .mp3 entries.
- /// </para>
- ///
- /// <para>
- /// The library determines whether compression will be attempted for an entry
- /// this way: If the entry is a zero length file, or a directory, no
- /// compression is used. Otherwise, if this callback is set, it is invoked
- /// and the <c>CompressionLevel</c> is set to the return value. If this
- /// callback has not been set, then the previously set value for
- /// <c>CompressionLevel</c> is used.
- /// </para>
- ///
- /// </remarks>
- public SetCompressionCallback SetCompression
- {
- get;
- set;
- }
- /// <summary>
- /// The maximum size of an output segment, when saving a split Zip file.
- /// </summary>
- /// <remarks>
- /// <para>
- /// Set this to a non-zero value before calling <see cref="Save()"/> or <see
- /// cref="Save(String)"/> to specify that the ZipFile should be saved as a
- /// split archive, also sometimes called a spanned archive. Some also
- /// call them multi-file archives.
- /// </para>
- ///
- /// <para>
- /// A split zip archive is saved in a set of discrete filesystem files,
- /// rather than in a single file. This is handy when transmitting the
- /// archive in email or some other mechanism that has a limit to the size of
- /// each file. The first file in a split archive will be named
- /// <c>basename.z01</c>, the second will be named <c>basename.z02</c>, and
- /// so on. The final file is named <c>basename.zip</c>. According to the zip
- /// specification from PKWare, the minimum value is 65536, for a 64k segment
- /// size. The maximum number of segments allows in a split archive is 99.
- /// </para>
- ///
- /// <para>
- /// The value of this property determines the maximum size of a split
- /// segment when writing a split archive. For example, suppose you have a
- /// <c>ZipFile</c> that would save to a single file of 200k. If you set the
- /// <c>MaxOutputSegmentSize</c> to 65536 before calling <c>Save()</c>, you
- /// will get four distinct output files. On the other hand if you set this
- /// property to 256k, then you will get a single-file archive for that
- /// <c>ZipFile</c>.
- /// </para>
- ///
- /// <para>
- /// The size of each split output file will be as large as possible, up to
- /// the maximum size set here. The zip specification requires that some data
- /// fields in a zip archive may not span a split boundary, and an output
- /// segment may be smaller than the maximum if necessary to avoid that
- /// problem. Also, obviously the final segment of the archive may be smaller
- /// than the maximum segment size. Segments will never be larger than the
- /// value set with this property.
- /// </para>
- ///
- /// <para>
- /// You can save a split Zip file only when saving to a regular filesystem
- /// file. It's not possible to save a split zip file as a self-extracting
- /// archive, nor is it possible to save a split zip file to a stream. When
- /// saving to a SFX or to a Stream, this property is ignored.
- /// </para>
- ///
- /// <para>
- /// About interoperability: Split or spanned zip files produced by DotNetZip
- /// can be read by WinZip or PKZip, and vice-versa. Segmented zip files may
- /// not be readable by other tools, if those other tools don't support zip
- /// spanning or splitting. When in doubt, test. I don't believe Windows
- /// Explorer can extract a split archive.
- /// </para>
- ///
- /// <para>
- /// This property has no effect when reading a split archive. You can read
- /// a split archive in the normal way with DotNetZip.
- /// </para>
- ///
- /// <para>
- /// When saving a zip file, if you want a regular zip file rather than a
- /// split zip file, don't set this property, or set it to Zero.
- /// </para>
- ///
- /// <para>
- /// If you read a split archive, with <see cref="ZipFile.Read(string)"/> and
- /// then subsequently call <c>ZipFile.Save()</c>, unless you set this
- /// property before calling <c>Save()</c>, you will get a normal,
- /// single-file archive.
- /// </para>
- /// </remarks>
- ///
- /// <seealso cref="NumberOfSegmentsForMostRecentSave"/>
- public Int32 MaxOutputSegmentSize
- {
- get
- {
- return _maxOutputSegmentSize;
- }
- set
- {
- if (value < 65536 && value != 0)
- throw new ZipException("The minimum acceptable segment size is 65536.");
- _maxOutputSegmentSize = value;
- }
- }
- /// <summary>
- /// Returns the number of segments used in the most recent Save() operation.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is normally zero, unless you have set the <see
- /// cref="MaxOutputSegmentSize"/> property. If you have set <see
- /// cref="MaxOutputSegmentSize"/>, and then you save a file, after the call to
- /// Save() completes, you can read this value to learn the number of segments that
- /// were created.
- /// </para>
- /// <para>
- /// If you call Save("Archive.zip"), and it creates 5 segments, then you
- /// will have filesystem files named Archive.z01, Archive.z02, Archive.z03,
- /// Archive.z04, and Archive.zip, and the value of this property will be 5.
- /// </para>
- /// </remarks>
- /// <seealso cref="MaxOutputSegmentSize"/>
- public Int32 NumberOfSegmentsForMostRecentSave
- {
- get
- {
- return unchecked((Int32)_numberOfSegmentsForMostRecentSave + 1);
- }
- }
- #if !NETCF
- /// <summary>
- /// The size threshold for an entry, above which a parallel deflate is used.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// DotNetZip will use multiple threads to compress any ZipEntry,
- /// if the entry is larger than the given size. Zero means "always
- /// use parallel deflate", while -1 means "never use parallel
- /// deflate". The default value for this property is 512k. Aside
- /// from the special values of 0 and 1, the minimum value is 65536.
- /// </para>
- ///
- /// <para>
- /// If the entry size cannot be known before compression, as with a
- /// read-forward stream, then Parallel deflate will never be
- /// performed, unless the value of this property is zero.
- /// </para>
- ///
- /// <para>
- /// A parallel deflate operations will speed up the compression of
- /// large files, on computers with multiple CPUs or multiple CPU
- /// cores. For files above 1mb, on a dual core or dual-cpu (2p)
- /// machine, the time required to compress the file can be 70% of the
- /// single-threaded deflate. For very large files on 4p machines the
- /// compression can be done in 30% of the normal time. The downside
- /// is that parallel deflate consumes extra memory during the deflate,
- /// and the deflation is not as effective.
- /// </para>
- ///
- /// <para>
- /// Parallel deflate tends to yield slightly less compression when
- /// compared to as single-threaded deflate; this is because the original
- /// data stream is split into multiple independent buffers, each of which
- /// is compressed in parallel. But because they are treated
- /// independently, there is no opportunity to share compression
- /// dictionaries. For that reason, a deflated stream may be slightly
- /// larger when compressed using parallel deflate, as compared to a
- /// traditional single-threaded deflate. Sometimes the increase over the
- /// normal deflate is as much as 5% of the total compressed size. For
- /// larger files it can be as small as 0.1%.
- /// </para>
- ///
- /// <para>
- /// Multi-threaded compression does not give as much an advantage when
- /// using Encryption. This is primarily because encryption tends to slow
- /// down the entire pipeline. Also, multi-threaded compression gives less
- /// of an advantage when using lower compression levels, for example <see
- /// cref="Ionic.Zlib.CompressionLevel.BestSpeed"/>. You may have to
- /// perform some tests to determine the best approach for your situation.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <seealso cref="ParallelDeflateMaxBufferPairs"/>
- ///
- public long ParallelDeflateThreshold
- {
- set
- {
- if ((value != 0) && (value != -1) && (value < 64 * 1024))
- throw new ArgumentOutOfRangeException("ParallelDeflateThreshold should be -1, 0, or > 65536");
- _ParallelDeflateThreshold = value;
- }
- get
- {
- return _ParallelDeflateThreshold;
- }
- }
- /// <summary>
- /// The maximum number of buffer pairs to use when performing
- /// parallel compression.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This property sets an upper limit on the number of memory
- /// buffer pairs to create when performing parallel
- /// compression. The implementation of the parallel
- /// compression stream allocates multiple buffers to
- /// facilitate parallel compression. As each buffer fills up,
- /// the stream uses <see
- /// cref="System.Threading.ThreadPool.QueueUserWorkItem(System.Threading.WaitCallback)">
- /// ThreadPool.QueueUserWorkItem()</see> to compress those
- /// buffers in a background threadpool thread. After a buffer
- /// is compressed, it is re-ordered and written to the output
- /// stream.
- /// </para>
- ///
- /// <para>
- /// A higher number of buffer pairs enables a higher degree of
- /// parallelism, which tends to increase the speed of compression on
- /// multi-cpu computers. On the other hand, a higher number of buffer
- /// pairs also implies a larger memory consumption, more active worker
- /// threads, and a higher cpu utilization for any compression. This
- /// property enables the application to limit its memory consumption and
- /// CPU utilization behavior depending on requirements.
- /// </para>
- ///
- /// <para>
- /// For each compression "task" that occurs in parallel, there are 2
- /// buffers allocated: one for input and one for output. This property
- /// sets a limit for the number of pairs. The total amount of storage
- /// space allocated for buffering will then be (N*S*2), where N is the
- /// number of buffer pairs, S is the size of each buffer (<see
- /// cref="BufferSize"/>). By default, DotNetZip allocates 4 buffer
- /// pairs per CPU core, so if your machine has 4 cores, and you retain
- /// the default buffer size of 128k, then the
- /// ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer
- /// memory in total, or 4mb, in blocks of 128kb. If you then set this
- /// property to 8, then the number will be 8 * 2 * 128kb of buffer
- /// memory, or 2mb.
- /// </para>
- ///
- /// <para>
- /// CPU utilization will also go up with additional buffers, because a
- /// larger number of buffer pairs allows a larger number of background
- /// threads to compress in parallel. If you find that parallel
- /// compression is consuming too much memory or CPU, you can adjust this
- /// value downward.
- /// </para>
- ///
- /// <para>
- /// The default value is 16. Different values may deliver better or
- /// worse results, depending on your priorities and the dynamic
- /// performance characteristics of your storage and compute resources.
- /// </para>
- ///
- /// <para>
- /// This property is not the number of buffer pairs to use; it is an
- /// upper limit. An illustration: Suppose you have an application that
- /// uses the default value of this property (which is 16), and it runs
- /// on a machine with 2 CPU cores. In that case, DotNetZip will allocate
- /// 4 buffer pairs per CPU core, for a total of 8 pairs. The upper
- /// limit specified by this property has no effect.
- /// </para>
- ///
- /// <para>
- /// The application can set this value at any time
- /// before calling <c>ZipFile.Save()</c>.
- /// </para>
- /// </remarks>
- ///
- /// <seealso cref="ParallelDeflateThreshold"/>
- ///
- public int ParallelDeflateMaxBufferPairs
- {
- get
- {
- return _maxBufferPairs;
- }
- set
- {
- if (value < 4)
- throw new ArgumentOutOfRangeException("ParallelDeflateMaxBufferPairs",
- "Value must be 4 or greater.");
- _maxBufferPairs = value;
- }
- }
- #endif
- /// <summary>Provides a string representation of the instance.</summary>
- /// <returns>a string representation of the instance.</returns>
- public override String ToString()
- {
- return String.Format("ZipFile::{0}", Name);
- }
- /// <summary>
- /// Returns the version number on the DotNetZip assembly.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This property is exposed as a convenience. Callers could also get the
- /// version value by retrieving GetName().Version on the
- /// System.Reflection.Assembly object pointing to the DotNetZip
- /// assembly. But sometimes it is not clear which assembly is being loaded.
- /// This property makes it clear.
- /// </para>
- /// <para>
- /// This static property is primarily useful for diagnostic purposes.
- /// </para>
- /// </remarks>
- public static System.Version LibraryVersion
- {
- get
- {
- return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
- }
- }
- internal void NotifyEntryChanged()
- {
- _contentsChanged = true;
- }
- internal Stream StreamForDiskNumber(uint diskNumber)
- {
- if (diskNumber + 1 == this._diskNumberWithCd ||
- (diskNumber == 0 && this._diskNumberWithCd == 0))
- {
- //return (this.ReadStream as FileStream);
- return this.ReadStream;
- }
- return ZipSegmentedStream.ForReading(this._readName ?? this._name,
- diskNumber, _diskNumberWithCd);
- }
- // called by ZipEntry in ZipEntry.Extract(), when there is no stream set for the
- // ZipEntry.
- internal void Reset(bool whileSaving)
- {
- if (_JustSaved)
- {
- // read in the just-saved zip archive
- using (ZipFile x = new ZipFile())
- {
- if (File.Exists(this._readName ?? this._name))
- {
- // workitem 10735
- x._readName = x._name = whileSaving
- ? (this._readName ?? this._name)
- : this._name;
- }
- else // if we just saved to a stream no file is available to read from
- {
- if (_readstream.CanSeek)
- _readstream.Seek(0, SeekOrigin.Begin);
- x._readstream = _readstream;
- }
- x.AlternateEncoding = this.AlternateEncoding;
- x.AlternateEncodingUsage = this.AlternateEncodingUsage;
- ReadIntoInstance(x);
- // copy the contents of the entries.
- // cannot just replace the entries - the app may be holding them
- foreach (ZipEntry e1 in x)
- {
- foreach (ZipEntry e2 in this)
- {
- if (e1.FileName == e2.FileName)
- {
- if (!e2.IsChanged)
- e2.CopyMetaData(e1);
- break;
- }
- }
- }
- }
- _JustSaved = false;
- }
- }
- #endregion
- #region Constructors
-
- /// <summary>
- /// Creates a new <c>ZipFile</c> instance, using the specified filename.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// Applications can use this constructor to create a new ZipFile for writing,
- /// or to slurp in an existing zip archive for read and update purposes.
- /// </para>
- ///
- /// <para>
- /// To create a new zip archive, an application can call this constructor,
- /// passing the name of a file that does not exist. The name may be a fully
- /// qualified path. Then the application can add directories or files to the
- /// <c>ZipFile</c> via <c>AddDirectory()</c>, <c>AddFile()</c>, <c>AddItem()</c>
- /// and then write the zip archive to the disk by calling <c>Save()</c>. The
- /// zip file is not actually opened and written to the disk until the
- /// application calls <c>ZipFile.Save()</c>. At that point the new zip file
- /// with the given name is created.
- /// </para>
- ///
- /// <para>
- /// If you won't know the name of the <c>Zipfile</c> until the time you call
- /// <c>ZipFile.Save()</c>, or if you plan to save to a stream (which has no
- /// name), then you should use the no-argument constructor.
- /// </para>
- ///
- /// <para>
- /// The application can also call this constructor to read an existing zip
- /// archive. passing the name of a valid zip file that does exist. But, it's
- /// better form to use the static <see cref="ZipFile.Read(String)"/> method,
- /// passing the name of the zip file, because using <c>ZipFile.Read()</c> in
- /// your code communicates very clearly what you are doing. In either case,
- /// the file is then read into the <c>ZipFile</c> instance. The app can then
- /// enumerate the entries or can modify the zip file, for example adding
- /// entries, removing entries, changing comments, and so on.
- /// </para>
- ///
- /// <para>
- /// One advantage to this parameterized constructor: it allows applications to
- /// use the same code to add items to a zip archive, regardless of whether the
- /// zip file exists.
- /// </para>
- ///
- /// <para>
- /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
- /// not party on a single instance with multiple threads. You may have
- /// multiple threads that each use a distinct <c>ZipFile</c> instance, or you
- /// can synchronize multi-thread access to a single instance.
- /// </para>
- ///
- /// <para>
- /// By the way, since DotNetZip is so easy to use, don't you think <see
- /// href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">you should
- /// donate $5 or $10</see>?
- /// </para>
- ///
- /// </remarks>
- ///
- /// <exception cref="Ionic.Zip.ZipException">
- /// Thrown if name refers to an existing file that is not a valid zip file.
- /// </exception>
- ///
- /// <example>
- /// This example shows how to create a zipfile, and add a few files into it.
- /// <code>
- /// String ZipFileToCreate = "archive1.zip";
- /// String DirectoryToZip = "c:\\reports";
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// // Store all files found in the top level directory, into the zip archive.
- /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
- /// zip.AddFiles(filenames, "files");
- /// zip.Save(ZipFileToCreate);
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Dim ZipFileToCreate As String = "archive1.zip"
- /// Dim DirectoryToZip As String = "c:\reports"
- /// Using zip As ZipFile = New ZipFile()
- /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
- /// zip.AddFiles(filenames, "files")
- /// zip.Save(ZipFileToCreate)
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <param name="fileName">The filename to use for the new zip archive.</param>
- ///
- public ZipFile(string fileName)
- {
- if (DefaultEncoding == null)
- {
- _alternateEncoding = System.Text.Encoding.UTF8;
- AlternateEncodingUsage = ZipOption.Always;
- }
- else
- {
- _alternateEncoding = DefaultEncoding;
- }
- try
- {
- _InitInstance(fileName, null);
- }
- catch (Exception e1)
- {
- throw new ZipException(String.Format("Could not read {0} as a zip file", fileName), e1);
- }
- }
- /// <summary>
- /// Creates a new <c>ZipFile</c> instance, using the specified name for the
- /// filename, and the specified Encoding.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// See the documentation on the <see cref="ZipFile(String)">ZipFile
- /// constructor that accepts a single string argument</see> for basic
- /// information on all the <c>ZipFile</c> constructors.
- /// </para>
- ///
- /// <para>
- /// The Encoding is used as the default alternate encoding for entries with
- /// filenames or comments that cannot be encoded with the IBM437 code page.
- /// This is equivalent to setting the <see
- /// cref="ProvisionalAlternateEncoding"/> property on the <c>ZipFile</c>
- /// instance after construction.
- /// </para>
- ///
- /// <para>
- /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
- /// not party on a single instance with multiple threads. You may have
- /// multiple threads that each use a distinct <c>ZipFile</c> instance, or you
- /// can synchronize multi-thread access to a single instance.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <exception cref="Ionic.Zip.ZipException">
- /// Thrown if name refers to an existing file that is not a valid zip file.
- /// </exception>
- ///
- /// <param name="fileName">The filename to use for the new zip archive.</param>
- /// <param name="encoding">The Encoding is used as the default alternate
- /// encoding for entries with filenames or comments that cannot be encoded
- /// with the IBM437 code page. </param>
- public ZipFile(string fileName, System.Text.Encoding encoding)
- {
- try
- {
- AlternateEncoding = encoding;
- AlternateEncodingUsage = ZipOption.Always;
- _InitInstance(fileName, null);
- }
- catch (Exception e1)
- {
- throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
- }
- }
- /// <summary>
- /// Create a zip file, without specifying a target filename or stream to save to.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// See the documentation on the <see cref="ZipFile(String)">ZipFile
- /// constructor that accepts a single string argument</see> for basic
- /// information on all the <c>ZipFile</c> constructors.
- /// </para>
- ///
- /// <para>
- /// After instantiating with this constructor and adding entries to the
- /// archive, the application should call <see cref="ZipFile.Save(String)"/> or
- /// <see cref="ZipFile.Save(System.IO.Stream)"/> to save to a file or a
- /// stream, respectively. The application can also set the <see cref="Name"/>
- /// property and then call the no-argument <see cref="Save()"/> method. (This
- /// is the preferred approach for applications that use the library through
- /// COM interop.) If you call the no-argument <see cref="Save()"/> method
- /// without having set the <c>Name</c> of the <c>ZipFile</c>, either through
- /// the parameterized constructor or through the explicit property , the
- /// Save() will throw, because there is no place to save the file. </para>
- ///
- /// <para>
- /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
- /// have multiple threads that each use a distinct <c>ZipFile</c> instance, or
- /// you can synchronize multi-thread access to a single instance. </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// This example creates a Zip archive called Backup.zip, containing all the files
- /// in the directory DirectoryToZip. Files within subdirectories are not zipped up.
- /// <code>
- /// using (ZipFile zip = new ZipFile())
- /// {
- /// // Store all files found in the top level directory, into the zip archive.
- /// // note: this code does not recurse subdirectories!
- /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
- /// zip.AddFiles(filenames, "files");
- /// zip.Save("Backup.zip");
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As New ZipFile
- /// ' Store all files found in the top level directory, into the zip archive.
- /// ' note: this code does not recurse subdirectories!
- /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
- /// zip.AddFiles(filenames, "files")
- /// zip.Save("Backup.zip")
- /// End Using
- /// </code>
- /// </example>
- public ZipFile()
- {
- if (DefaultEncoding == null)
- {
- _alternateEncoding = System.Text.Encoding.UTF8;
- AlternateEncodingUsage = ZipOption.Always;
- }
- else
- {
- _alternateEncoding = DefaultEncoding;
- }
- _InitInstance(null, null);
- }
- /// <summary>
- /// Create a zip file, specifying a text Encoding, but without specifying a
- /// target filename or stream to save to.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// See the documentation on the <see cref="ZipFile(String)">ZipFile
- /// constructor that accepts a single string argument</see> for basic
- /// information on all the <c>ZipFile</c> constructors.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <param name="encoding">
- /// The Encoding is used as the default alternate encoding for entries with
- /// filenames or comments that cannot be encoded with the IBM437 code page.
- /// </param>
- public ZipFile(System.Text.Encoding encoding)
- {
- AlternateEncoding = encoding;
- AlternateEncodingUsage = ZipOption.Always;
- _InitInstance(null, null);
- }
- /// <summary>
- /// Creates a new <c>ZipFile</c> instance, using the specified name for the
- /// filename, and the specified status message writer.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// See the documentation on the <see cref="ZipFile(String)">ZipFile
- /// constructor that accepts a single string argument</see> for basic
- /// information on all the <c>ZipFile</c> constructors.
- /// </para>
- ///
- /// <para>
- /// This version of the constructor allows the caller to pass in a TextWriter,
- /// to which verbose messages will be written during extraction or creation of
- /// the zip archive. A console application may wish to pass
- /// System.Console.Out to get messages on the Console. A graphical or headless
- /// application may wish to capture the messages in a different
- /// <c>TextWriter</c>, for example, a <c>StringWriter</c>, and then display
- /// the messages in a TextBox, or generate an audit log of ZipFile operations.
- /// </para>
- ///
- /// <para>
- /// To encrypt the data for the files added to the <c>ZipFile</c> instance,
- /// set the Password property after creating the <c>ZipFile</c> instance.
- /// </para>
- ///
- /// <para>
- /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
- /// not party on a single instance with multiple threads. You may have
- /// multiple threads that each use a distinct <c>ZipFile</c> instance, or you
- /// can synchronize multi-thread access to a single instance.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <exception cref="Ionic.Zip.ZipException">
- /// Thrown if name refers to an existing file that is not a valid zip file.
- /// </exception>
- ///
- /// <example>
- /// <code>
- /// using (ZipFile zip = new ZipFile("Backup.zip", Console.Out))
- /// {
- /// // Store all files found in the top level directory, into the zip archive.
- /// // note: this code does not recurse subdirectories!
- /// // Status messages will be written to Console.Out
- /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
- /// zip.AddFiles(filenames);
- /// zip.Save();
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As New ZipFile("Backup.zip", Console.Out)
- /// ' Store all files found in the top level directory, into the zip archive.
- /// ' note: this code does not recurse subdirectories!
- /// ' Status messages will be written to Console.Out
- /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
- /// zip.AddFiles(filenames)
- /// zip.Save()
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <param name="fileName">The filename to use for the new zip archive.</param>
- /// <param name="statusMessageWriter">A TextWriter to use for writing
- /// verbose status messages.</param>
- public ZipFile(string fileName, TextWriter statusMessageWriter)
- {
- if (DefaultEncoding == null)
- {
- _alternateEncoding = System.Text.Encoding.UTF8;
- AlternateEncodingUsage = ZipOption.Always;
- }
- else
- {
- _alternateEncoding = DefaultEncoding;
- }
- try
- {
- _InitInstance(fileName, statusMessageWriter);
- }
- catch (Exception e1)
- {
- throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
- }
- }
- /// <summary>
- /// Creates a new <c>ZipFile</c> instance, using the specified name for the
- /// filename, the specified status message writer, and the specified Encoding.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This constructor works like the <see cref="ZipFile(String)">ZipFile
- /// constructor that accepts a single string argument.</see> See that
- /// reference for detail on what this constructor does.
- /// </para>
- ///
- /// <para>
- /// This version of the constructor allows the caller to pass in a
- /// <c>TextWriter</c>, and an Encoding. The <c>TextWriter</c> will collect
- /// verbose messages that are generated by the library during extraction or
- /// creation of the zip archive. A console application may wish to pass
- /// <c>System.Console.Out</c> to get messages on the Console. A graphical or
- /// headless application may wish to capture the messages in a different
- /// <c>TextWriter</c>, for example, a <c>StringWriter</c>, and then display
- /// the messages in a <c>TextBox</c>, or generate an audit log of
- /// <c>ZipFile</c> operations.
- /// </para>
- ///
- /// <para>
- /// The <c>Encoding</c> is used as the default alternate encoding for entries
- /// with filenames or comments that cannot be encoded with the IBM437 code
- /// page. This is a equivalent to setting the <see
- /// cref="ProvisionalAlternateEncoding"/> property on the <c>ZipFile</c>
- /// instance after construction.
- /// </para>
- ///
- /// <para>
- /// To encrypt the data for the files added to the <c>ZipFile</c> instance,
- /// set the <c>Password</c> property after creating the <c>ZipFile</c>
- /// instance.
- /// </para>
- ///
- /// <para>
- /// Instances of the <c>ZipFile</c> class are not multi-thread safe. You may
- /// not party on a single instance with multiple threads. You may have
- /// multiple threads that each use a distinct <c>ZipFile</c> instance, or you
- /// can synchronize multi-thread access to a single instance.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <exception cref="Ionic.Zip.ZipException">
- /// Thrown if <c>fileName</c> refers to an existing file that is not a valid zip file.
- /// </exception>
- ///
- /// <param name="fileName">The filename to use for the new zip archive.</param>
- /// <param name="statusMessageWriter">A TextWriter to use for writing verbose
- /// status messages.</param>
- /// <param name="encoding">
- /// The Encoding is used as the default alternate encoding for entries with
- /// filenames or comments that cannot be encoded with the IBM437 code page.
- /// </param>
- public ZipFile(string fileName, TextWriter statusMessageWriter,
- System.Text.Encoding encoding)
- {
- try
- {
- AlternateEncoding = encoding;
- AlternateEncodingUsage = ZipOption.Always;
- _InitInstance(fileName, statusMessageWriter);
- }
- catch (Exception e1)
- {
- throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
- }
- }
- /// <summary>
- /// Initialize a <c>ZipFile</c> instance by reading in a zip file.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// This method is primarily useful from COM Automation environments, when
- /// reading or extracting zip files. In COM, it is not possible to invoke
- /// parameterized constructors for a class. A COM Automation application can
- /// update a zip file by using the <see cref="ZipFile()">default (no argument)
- /// constructor</see>, then calling <c>Initialize()</c> to read the contents
- /// of an on-disk zip archive into the <c>ZipFile</c> instance.
- /// </para>
- ///
- /// <para>
- /// .NET applications are encouraged to use the <c>ZipFile.Read()</c> methods
- /// for better clarity.
- /// </para>
- ///
- /// </remarks>
- /// <param name="fileName">the name of the existing zip file to read in.</param>
- public void Initialize(string fileName)
- {
- try
- {
- _InitInstance(fileName, null);
- }
- catch (Exception e1)
- {
- throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1);
- }
- }
- private void _InitInstance(string zipFileName, TextWriter statusMessageWriter)
- {
- // create a new zipfile
- _name = zipFileName;
- _StatusMessageTextWriter = statusMessageWriter;
- _contentsChanged = true;
- AddDirectoryWillTraverseReparsePoints = true; // workitem 8617
- CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
- #if !NETCF
- ParallelDeflateThreshold = 512 * 1024;
- #endif
- // workitem 7685, 9868
- _entries = new Dictionary<string, ZipEntry>(StringComparer.Ordinal);
- _entriesInsensitive = new Dictionary<string, ZipEntry>(StringComparer.OrdinalIgnoreCase);
- if (File.Exists(_name))
- {
- if (FullScan)
- ReadIntoInstance_Orig(this);
- else
- ReadIntoInstance(this);
- this._fileAlreadyExists = true;
- }
- return;
- }
- #endregion
- #region Indexers and Collections
- private List<ZipEntry> ZipEntriesAsList
- {
- get
- {
- if (_zipEntriesAsList == null)
- _zipEntriesAsList = new List<ZipEntry>(_entries.Values);
- return _zipEntriesAsList;
- }
- }
- /// <summary>
- /// This is an integer indexer into the Zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This property is read-only.
- /// </para>
- ///
- /// <para>
- /// Internally, the <c>ZipEntry</c> instances that belong to the
- /// <c>ZipFile</c> are stored in a Dictionary. When you use this
- /// indexer the first time, it creates a read-only
- /// <c>List<ZipEntry></c> from the Dictionary.Values Collection.
- /// If at any time you modify the set of entries in the <c>ZipFile</c>,
- /// either by adding an entry, removing an entry, or renaming an
- /// entry, a new List will be created, and the numeric indexes for the
- /// remaining entries may be different.
- /// </para>
- ///
- /// <para>
- /// This means you cannot rename any ZipEntry from
- /// inside an enumeration of the zip file.
- /// </para>
- ///
- /// <param name="ix">
- /// The index value.
- /// </param>
- ///
- /// </remarks>
- ///
- /// <returns>
- /// The <c>ZipEntry</c> within the Zip archive at the specified index. If the
- /// entry does not exist in the archive, this indexer throws.
- /// </returns>
- ///
- public ZipEntry this[int ix]
- {
- // workitem 6402
- get
- {
- return ZipEntriesAsList[ix];
- }
- }
- /// <summary>
- /// This is a name-based indexer into the Zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// This property is read-only.
- /// </para>
- ///
- /// <para>
- /// The <see cref="CaseSensitiveRetrieval"/> property on the <c>ZipFile</c>
- /// determines whether retrieval via this indexer is done via case-sensitive
- /// comparisons. By default, retrieval is not case sensitive. This makes
- /// sense on Windows, in which filesystems are not case sensitive.
- /// </para>
- ///
- /// <para>
- /// Regardless of case-sensitivity, it is not always the case that
- /// <c>this[value].FileName == value</c>. In other words, the <c>FileName</c>
- /// property of the <c>ZipEntry</c> retrieved with this indexer, may or may
- /// not be equal to the index value.
- /// </para>
- ///
- /// <para>
- /// This is because DotNetZip performs a normalization of filenames passed to
- /// this indexer, before attempting to retrieve the item. That normalization
- /// includes: removal of a volume letter and colon, swapping backward slashes
- /// for forward slashes. So, <c>zip["dir1\\entry1.txt"].FileName ==
- /// "dir1/entry.txt"</c>.
- /// </para>
- ///
- /// <para>
- /// Directory entries in the zip file may be retrieved via this indexer only
- /// with names that have a trailing slash. DotNetZip automatically appends a
- /// trailing slash to the names of any directory entries added to a zip.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <example>
- /// This example extracts only the entries in a zip file that are .txt files.
- /// <code>
- /// using (ZipFile zip = ZipFile.Read("PackedDocuments.zip"))
- /// {
- /// foreach (string s1 in zip.EntryFilenames)
- /// {
- /// if (s1.EndsWith(".txt"))
- /// zip[s1].Extract("textfiles");
- /// }
- /// }
- /// </code>
- /// <code lang="VB">
- /// Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip")
- /// Dim s1 As String
- /// For Each s1 In zip.EntryFilenames
- /// If s1.EndsWith(".txt") Then
- /// zip(s1).Extract("textfiles")
- /// End If
- /// Next
- /// End Using
- /// </code>
- /// </example>
- /// <seealso cref="Ionic.Zip.ZipFile.RemoveEntry(string)"/>
- ///
- /// <exception cref="System.ArgumentException">
- /// Thrown if the caller attempts to assign a non-null value to the indexer.
- /// </exception>
- ///
- /// <param name="fileName">
- /// The name of the file, including any directory path, to retrieve from the
- /// zip. The filename match is not case-sensitive by default; you can use the
- /// <see cref="CaseSensitiveRetrieval"/> property to change this behavior. The
- /// pathname can use forward-slashes or backward slashes.
- /// </param>
- ///
- /// <returns>
- /// The <c>ZipEntry</c> within the Zip archive, given by the specified
- /// filename. If the named entry does not exist in the archive, this indexer
- /// returns <c>null</c> (<c>Nothing</c> in VB).
- /// </returns>
- ///
- public ZipEntry this[String fileName]
- {
- get
- {
- var entries = RetrievalEntries;
- var key = SharedUtilities.NormalizePathForUseInZipFile(fileName);
- if (entries.ContainsKey(key))
- return entries[key];
- // workitem 11056
- key = key.Replace("/", "\\");
- if (entries.ContainsKey(key))
- return entries[key];
- return null;
- #if MESSY
- foreach (ZipEntry e in _entries.Values)
- {
- if (this.CaseSensitiveRetrieval)
- {
- // check for the file match with a case-sensitive comparison.
- if (e.FileName == fileName) return e;
- // also check for equivalence
- if (fileName.Replace("\\", "/") == e.FileName) return e;
- if (e.FileName.Replace("\\", "/") == fileName) return e;
- // check for a difference only in trailing slash
- if (e.FileName.EndsWith("/"))
- {
- var fileNameNoSlash = e.FileName.Trim("/".ToCharArray());
- if (fileNameNoSlash == fileName) return e;
- // also check for equivalence
- if (fileName.Replace("\\", "/") == fileNameNoSlash) return e;
- if (fileNameNoSlash.Replace("\\", "/") == fileName) return e;
- }
- }
- else
- {
- // check for the file match in a case-insensitive manner.
- if (String.Compare(e.FileName, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
- // also check for equivalence
- if (String.Compare(fileName.Replace("\\", "/"), e.FileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
- if (String.Compare(e.FileName.Replace("\\", "/"), fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
- // check for a difference only in trailing slash
- if (e.FileName.EndsWith("/"))
- {
- var fileNameNoSlash = e.FileName.Trim("/".ToCharArray());
- if (String.Compare(fileNameNoSlash, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
- // also check for equivalence
- if (String.Compare(fileName.Replace("\\", "/"), fileNameNoSlash, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
- if (String.Compare(fileNameNoSlash.Replace("\\", "/"), fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e;
- }
- }
- }
- return null;
- #endif
- }
- }
- /// <summary>
- /// The list of filenames for the entries contained within the zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// According to the ZIP specification, the names of the entries use forward
- /// slashes in pathnames. If you are scanning through the list, you may have
- /// to swap forward slashes for backslashes.
- /// </remarks>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.this[string]"/>
- ///
- /// <example>
- /// This example shows one way to test if a filename is already contained
- /// within a zip archive.
- /// <code>
- /// String zipFileToRead= "PackedDocuments.zip";
- /// string candidate = "DatedMaterial.xps";
- /// using (ZipFile zip = new ZipFile(zipFileToRead))
- /// {
- /// if (zip.EntryFilenames.Contains(candidate))
- /// Console.WriteLine("The file '{0}' exists in the zip archive '{1}'",
- /// candidate,
- /// zipFileName);
- /// else
- /// Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'",
- /// candidate,
- /// zipFileName);
- /// Console.WriteLine();
- /// }
- /// </code>
- /// <code lang="VB">
- /// Dim zipFileToRead As String = "PackedDocuments.zip"
- /// Dim candidate As String = "DatedMaterial.xps"
- /// Using zip As ZipFile.Read(ZipFileToRead)
- /// If zip.EntryFilenames.Contains(candidate) Then
- /// Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", _
- /// candidate, _
- /// zipFileName)
- /// Else
- /// Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", _
- /// candidate, _
- /// zipFileName)
- /// End If
- /// Console.WriteLine
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <returns>
- /// The list of strings for the filenames contained within the Zip archive.
- /// </returns>
- ///
- public System.Collections.Generic.ICollection<String> EntryFileNames
- {
- get
- {
- return _entries.Keys;
- }
- }
- /// <summary>
- /// Returns the readonly collection of entries in the Zip archive.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// If there are no entries in the current <c>ZipFile</c>, the value returned is a
- /// non-null zero-element collection. If there are entries in the zip file,
- /// the elements are returned in no particular order.
- /// </para>
- /// <para>
- /// This is the implied enumerator on the <c>ZipFile</c> class. If you use a
- /// <c>ZipFile</c> instance in a context that expects an enumerator, you will
- /// get this collection.
- /// </para>
- /// </remarks>
- /// <seealso cref="EntriesSorted"/>
- public System.Collections.Generic.ICollection<ZipEntry> Entries
- {
- get
- {
- return _entries.Values;
- }
- }
- /// <summary>
- /// Returns a readonly collection of entries in the Zip archive, sorted by FileName.
- /// </summary>
- ///
- /// <remarks>
- /// If there are no entries in the current <c>ZipFile</c>, the value returned
- /// is a non-null zero-element collection. If there are entries in the zip
- /// file, the elements are returned sorted by the name of the entry.
- /// </remarks>
- ///
- /// <example>
- ///
- /// This example fills a Windows Forms ListView with the entries in a zip file.
- ///
- /// <code lang="C#">
- /// using (ZipFile zip = ZipFile.Read(zipFile))
- /// {
- /// foreach (ZipEntry entry in zip.EntriesSorted)
- /// {
- /// ListViewItem item = new ListViewItem(n.ToString());
- /// n++;
- /// string[] subitems = new string[] {
- /// entry.FileName.Replace("/","\\"),
- /// entry.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
- /// entry.UncompressedSize.ToString(),
- /// String.Format("{0,5:F0}%", entry.CompressionRatio),
- /// entry.CompressedSize.ToString(),
- /// (entry.UsesEncryption) ? "Y" : "N",
- /// String.Format("{0:X8}", entry.Crc)};
- ///
- /// foreach (String s in subitems)
- /// {
- /// ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem();
- /// subitem.Text = s;
- /// item.SubItems.Add(subitem);
- /// }
- ///
- /// this.listView1.Items.Add(item);
- /// }
- /// }
- /// </code>
- /// </example>
- ///
- /// <seealso cref="Entries"/>
- public System.Collections.Generic.ICollection<ZipEntry> EntriesSorted
- {
- get
- {
- var coll = new System.Collections.Generic.List<ZipEntry>();
- foreach (var e in this.Entries)
- {
- coll.Add(e);
- }
- StringComparison sc = (CaseSensitiveRetrieval) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
- coll.Sort((x, y) => { return String.Compare(x.FileName, y.FileName, sc); });
- return coll.AsReadOnly();
- }
- }
- /// <summary>
- /// Returns the number of entries in the Zip archive.
- /// </summary>
- public int Count
- {
- get
- {
- return _entries.Count;
- }
- }
- /// <summary>
- /// Removes the given <c>ZipEntry</c> from the zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// After calling <c>RemoveEntry</c>, the application must call <c>Save</c> to
- /// make the changes permanent.
- /// </para>
- /// </remarks>
- ///
- /// <exception cref="System.ArgumentException">
- /// Thrown if the specified <c>ZipEntry</c> does not exist in the <c>ZipFile</c>.
- /// </exception>
- ///
- /// <example>
- /// In this example, all entries in the zip archive dating from before
- /// December 31st, 2007, are removed from the archive. This is actually much
- /// easier if you use the RemoveSelectedEntries method. But I needed an
- /// example for RemoveEntry, so here it is.
- /// <code>
- /// String ZipFileToRead = "ArchiveToModify.zip";
- /// System.DateTime Threshold = new System.DateTime(2007,12,31);
- /// using (ZipFile zip = ZipFile.Read(ZipFileToRead))
- /// {
- /// var EntriesToRemove = new System.Collections.Generic.List<ZipEntry>();
- /// foreach (ZipEntry e in zip)
- /// {
- /// if (e.LastModified < Threshold)
- /// {
- /// // We cannot remove the entry from the list, within the context of
- /// // an enumeration of said list.
- /// // So we add the doomed entry to a list to be removed later.
- /// EntriesToRemove.Add(e);
- /// }
- /// }
- ///
- /// // actually remove the doomed entries.
- /// foreach (ZipEntry zombie in EntriesToRemove)
- /// zip.RemoveEntry(zombie);
- ///
- /// zip.Comment= String.Format("This zip archive was updated at {0}.",
- /// System.DateTime.Now.ToString("G"));
- ///
- /// // save with a different name
- /// zip.Save("Archive-Updated.zip");
- /// }
- /// </code>
- ///
- /// <code lang="VB">
- /// Dim ZipFileToRead As String = "ArchiveToModify.zip"
- /// Dim Threshold As New DateTime(2007, 12, 31)
- /// Using zip As ZipFile = ZipFile.Read(ZipFileToRead)
- /// Dim EntriesToRemove As New System.Collections.Generic.List(Of ZipEntry)
- /// Dim e As ZipEntry
- /// For Each e In zip
- /// If (e.LastModified < Threshold) Then
- /// ' We cannot remove the entry from the list, within the context of
- /// ' an enumeration of said list.
- /// ' So we add the doomed entry to a list to be removed later.
- /// EntriesToRemove.Add(e)
- /// End If
- /// Next
- ///
- /// ' actually remove the doomed entries.
- /// Dim zombie As ZipEntry
- /// For Each zombie In EntriesToRemove
- /// zip.RemoveEntry(zombie)
- /// Next
- /// zip.Comment = String.Format("This zip archive was updated at {0}.", DateTime.Now.ToString("G"))
- /// 'save as a different name
- /// zip.Save("Archive-Updated.zip")
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <param name="entry">
- /// The <c>ZipEntry</c> to remove from the zip.
- /// </param>
- ///
- /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(string)"/>
- ///
- public void RemoveEntry(ZipEntry entry)
- {
- //if (!_entries.Values.Contains(entry))
- // throw new ArgumentException("The entry you specified does not exist in the zip archive.");
- if (entry == null)
- throw new ArgumentNullException("entry");
- var path = SharedUtilities.NormalizePathForUseInZipFile(entry.FileName);
- _entries.Remove(path);
- if (!AnyCaseInsensitiveMatches(path))
- _entriesInsensitive.Remove(path);
- _zipEntriesAsList = null;
- #if NOTNEEDED
- if (_direntries != null)
- {
- bool FoundAndRemovedDirEntry = false;
- foreach (ZipDirEntry de1 in _direntries)
- {
- if (entry.FileName == de1.FileName)
- {
- _direntries.Remove(de1);
- FoundAndRemovedDirEntry = true;
- break;
- }
- }
- if (!FoundAndRemovedDirEntry)
- throw new BadStateException("The entry to be removed was not found in the directory.");
- }
- #endif
- _contentsChanged = true;
- }
- private bool AnyCaseInsensitiveMatches(string path)
- {
- // this has to search _entries rather than _caseInsensitiveEntries because it's used to determine whether to update the latter
- foreach (var entry in _entries.Values)
- {
- if (String.Equals(entry.FileName, path, StringComparison.OrdinalIgnoreCase))
- return true;
- }
- return false;
- }
- /// <summary>
- /// Removes the <c>ZipEntry</c> with the given filename from the zip archive.
- /// </summary>
- ///
- /// <remarks>
- /// <para>
- /// After calling <c>RemoveEntry</c>, the application must call <c>Save</c> to
- /// make the changes permanent.
- /// </para>
- ///
- /// </remarks>
- ///
- /// <exception cref="System.InvalidOperationException">
- /// Thrown if the <c>ZipFile</c> is not updatable.
- /// </exception>
- ///
- /// <exception cref="System.ArgumentException">
- /// Thrown if a <c>ZipEntry</c> with the specified filename does not exist in
- /// the <c>ZipFile</c>.
- /// </exception>
- ///
- /// <example>
- ///
- /// This example shows one way to remove an entry with a given filename from
- /// an existing zip archive.
- ///
- /// <code>
- /// String zipFileToRead= "PackedDocuments.zip";
- /// string candidate = "DatedMaterial.xps";
- /// using (ZipFile zip = ZipFile.Read(zipFileToRead))
- /// {
- /// if (zip.EntryFilenames.Contains(candidate))
- /// {
- /// zip.RemoveEntry(candidate);
- /// zip.Comment= String.Format("The file '{0}' has been removed from this archive.",
- /// Candidate);
- /// zip.Save();
- /// }
- /// }
- /// </code>
- /// <code lang="VB">
- /// Dim zipFileToRead As String = "PackedDocuments.zip"
- /// Dim candidate As String = "DatedMaterial.xps"
- /// Using zip As ZipFile = ZipFile.Read(zipFileToRead)
- /// If zip.EntryFilenames.Contains(candidate) Then
- /// zip.RemoveEntry(candidate)
- /// zip.Comment = String.Format("The file '{0}' has been removed from this archive.", Candidate)
- /// zip.Save
- /// End If
- /// End Using
- /// </code>
- /// </example>
- ///
- /// <param name="fileName">
- /// The name of the file, including any directory path, to remove from the zip.
- /// The filename match is not case-sensitive by default; you can use the
- /// <c>CaseSensitiveRetrieval</c> property to change this behavior. The
- /// pathname can use forward-slashes or backward slashes.
- /// </param>
- ///
- public void RemoveEntry(String fileName)
- {
- string modifiedName = ZipEntry.NameInArchive(fileName, null);
- ZipEntry e = this[modifiedName];
- if (e == null)
- throw new ArgumentException("The entry you specified was not found in the zip archive.");
- RemoveEntry(e);
- }
- #endregion
- #region Destructors and Disposers
- // /// <summary>
- // /// This is the class Destructor, which gets called implicitly when the instance
- // /// is destroyed. Because the <c>ZipFile</c> type implements IDisposable, this
- // /// method calls Dispose(false).
- // /// </summary>
- // ~ZipFile()
- // {
- // // call Dispose with false. Since we're in the
- // // destructor call, the managed resources will be
- // // disposed of anyways.
- // Dispose(false);
- // }
- /// <summary>
- /// Closes the read and write streams associated
- /// to the <c>ZipFile</c>, if necessary.
- /// </summary>
- ///
- /// <remarks>
- /// The Dispose() method is generally employed implicitly, via a <c>using(..) {..}</c>
- /// statement. (<c>Using...End Using</c> in VB) If you do not employ a using
- /// statement, insure that your application calls Dispose() explicitly. For
- /// example, in a Powershell application, or an application that uses the COM
- /// interop interface, you must call Dispose() explicitly.
- /// </remarks>
- ///
- /// <example>
- /// This example extracts an entry selected by name, from the Zip file to the
- /// Console.
- /// <code>
- /// using (ZipFile zip = ZipFile.Read(zipfile))
- /// {
- /// foreach (ZipEntry e in zip)
- /// {
- /// if (WantThisEntry(e.FileName))
- /// zip.Extract(e.FileName, Console.OpenStandardOutput());
- /// }
- /// } // Dispose() is called implicitly here.
- /// </code>
- ///
- /// <code lang="VB">
- /// Using zip As ZipFile = ZipFile.Read(zipfile)
- /// Dim e As ZipEntry
- /// For Each e In zip
- /// If WantThisEntry(e.FileName) Then
- /// zip.Extract(e.FileName, Console.OpenStandardOutput())
- /// End If
- /// Next
- /// End Using ' Dispose is implicity called here
- /// </code>
- /// </example>
- public void Dispose()
- {
- // dispose of the managed and unmanaged resources
- Dispose(true);
- // tell the GC that the Finalize process no longer needs
- // to be run for this object.
- GC.SuppressFinalize(this);
- }
- /// <summary>
- /// Disposes any managed resources, if the flag is set, then marks the
- /// instance disposed. This method is typically not called explicitly from
- /// application code.
- /// </summary>
- ///
- /// <remarks>
- /// Applications should call <see cref="Dispose()">the no-arg Dispose method</see>.
- /// </remarks>
- ///
- /// <param name="disposeManagedResources">
- /// indicates whether the method should dispose streams or not.
- /// </param>
- protected virtual void Dispose(bool disposeManagedResources)
- {
- if (!this._disposed)
- {
- if (disposeManagedResources)
- {
- // dispose managed resources
- if (_ReadStreamIsOurs)
- {
- if (_readstream != null)
- {
- // workitem 7704
- #if NETCF
- _readstream.Close();
- #else
- _readstream.Dispose();
- #endif
- _readstream = null;
- }
- }
- // only dispose the writestream if there is a backing file
- if ((_temporaryFileName != null) && (_name != null))
- if (_writestream != null)
- {
- // workitem 7704
- #if NETCF
- _writestream.Close();
- #else
- _writestream.Dispose();
- #endif
- _writestream = null;
- }
- #if !NETCF
- // workitem 10030
- if (this.ParallelDeflater != null)
- {
- this.ParallelDeflater.Dispose();
- this.ParallelDeflater = null;
- }
- #endif
- }
- this._disposed = true;
- }
- }
- #endregion
- #region private properties
- internal Stream ReadStream
- {
- get
- {
- if (_readstream == null)
- {
- if (_readName != null || _name !=null)
- {
- _readstream = File.Open(_readName ?? _name,
- FileMode.Open,
- FileAccess.Read,
- FileShare.Read | FileShare.Write);
- _ReadStreamIsOurs = true;
- }
- }
- return _readstream;
- }
- }
- private Stream WriteStream
- {
- // workitem 9763
- get
- {
- if (_writestream != null) return _writestream;
- if (_name == null) return _writestream;
- if (_maxOutputSegmentSize != 0)
- {
- _writestream = ZipSegmentedStream.ForWriting(this._name, _maxOutputSegmentSize);
- return _writestream;
- }
- SharedUtilities.CreateAndOpenUniqueTempFile(TempFileFolder ?? Path.GetDirectoryName(_name),
- out _writestream,
- out _temporaryFileName);
- return _writestream;
- }
- set
- {
- if (value != null)
- throw new ZipException("Cannot set the stream to a non-null value.");
- _writestream = null;
- }
- }
- #endregion
- #region private fields
- private TextWriter _StatusMessageTextWriter;
- private bool _CaseSensitiveRetrieval;
- private bool _IgnoreDuplicateFiles;
- private Stream _readstream;
- private Stream _writestream;
- private UInt16 _versionMadeBy;
- private UInt16 _versionNeededToExtract;
- private UInt32 _diskNumberWithCd;
- private Int32 _maxOutputSegmentSize;
- private UInt32 _numberOfSegmentsForMostRecentSave;
- private ZipErrorAction _zipErrorAction;
- private bool _disposed;
- //private System.Collections.Generic.List<ZipEntry> _entries;
- private System.Collections.Generic.Dictionary<String, ZipEntry> _entries;
- private System.Collections.Generic.Dictionary<String, ZipEntry> _entriesInsensitive;
- private List<ZipEntry> _zipEntriesAsList;
- private string _name;
- private string _readName;
- private string _Comment;
- internal string _Password;
- private bool _emitNtfsTimes = true;
- private bool _emitUnixTimes;
- private Ionic.Zlib.CompressionStrategy _Strategy = Ionic.Zlib.CompressionStrategy.Default;
- private Ionic.Zip.CompressionMethod _compressionMethod = Ionic.Zip.CompressionMethod.Deflate;
- private bool _fileAlreadyExists;
- private string _temporaryFileName;
- private bool _contentsChanged;
- private bool _hasBeenSaved;
- private String _TempFileFolder;
- private bool _ReadStreamIsOurs = true;
- private object LOCK = new object();
- private bool _saveOperationCanceled;
- private bool _extractOperationCanceled;
- private bool _addOperationCanceled;
- private EncryptionAlgorithm _Encryption;
- private bool _JustSaved;
- private long _locEndOfCDS = -1;
- private uint _OffsetOfCentralDirectory;
- private Int64 _OffsetOfCentralDirectory64;
- private Nullable<bool> _OutputUsesZip64;
- internal bool _inExtractAll;
- private System.Text.Encoding _alternateEncoding = null;
- private ZipOption _alternateEncodingUsage = ZipOption.Never;
-
- private int _BufferSize = BufferSizeDefault;
- #if !NETCF
- internal Ionic.Zlib.ParallelDeflateOutputStream ParallelDeflater;
- private long _ParallelDeflateThreshold;
- private int _maxBufferPairs = 16;
- #endif
- internal Zip64Option _zip64 = Zip64Option.Default;
- #pragma warning disable 649
- private bool _SavingSfx;
- #pragma warning restore 649
- /// <summary>
- /// Default size of the buffer used for IO.
- /// </summary>
- public static readonly int BufferSizeDefault = 32768;
- #endregion
- }
- /// <summary>
- /// Options for using ZIP64 extensions when saving zip archives.
- /// </summary>
- ///
- /// <remarks>
- ///
- /// <para>
- /// Designed many years ago, the <see
- /// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">original zip
- /// specification from PKWARE</see> allowed for 32-bit quantities for the
- /// compressed and uncompressed sizes of zip entries, as well as a 32-bit quantity
- /// for specifying the length of the zip archive itself, and a maximum of 65535
- /// entries. These limits are now regularly exceeded in many backup and archival
- /// scenarios. Recently, PKWare added extensions to the original zip spec, called
- /// "ZIP64 extensions", to raise those limitations. This property governs whether
- /// DotNetZip will use those extensions when writing zip archives. The use of
- /// these extensions is optional and explicit in DotNetZip because, despite the
- /// status of ZIP64 as a bona fide standard, many other zip tools and libraries do
- /// not support ZIP64, and therefore a zip file with ZIP64 extensions may be
- /// unreadable by some of those other tools.
- /// </para>
- ///
- /// <para>
- /// Set this property to <see cref="Zip64Option.Always"/> to always use ZIP64
- /// extensions when saving, regardless of whether your zip archive needs it.
- /// Suppose you add 5 files, each under 100k, to a ZipFile. If you specify Always
- /// for this flag, you will get a ZIP64 archive, though the archive does not need
- /// to use ZIP64 because none of the original zip limits had been exceeded.
- /// </para>
- ///
- /// <para>
- /// Set this property to <see cref="Zip64Option.Never"/> to tell the DotNetZip
- /// library to never use ZIP64 extensions. This is useful for maximum
- /// compatibility and interoperability, at the expense of the capability of
- /// handling large files or large archives. NB: Windows Explorer in Windows XP
- /// and Windows Vista cannot currently extract files from a zip64 archive, so if
- /// you want to guarantee that a zip archive produced by this library will work in
- /// Windows Explorer, use <c>Never</c>. If you set this property to <see
- /// cref="Zip64Option.Never"/>, and your application creates a zip that would
- /// exceed one of the Zip limits, the library will throw an exception while saving
- /// the zip file.
- /// </para>
- ///
- /// <para>
- /// Set this property to <see cref="Zip64Option.AsNecessary"/> to tell the
- /// DotNetZip library to use the ZIP64 extensions when required by the
- /// entry. After the file is compressed, the original and compressed sizes are
- /// checked, and if they exceed the limits described above, then zip64 can be
- /// used. That is the general idea, but there is an additional wrinkle when saving
- /// to a non-seekable device, like the ASP.NET <c>Response.OutputStream</c>, or
- /// <c>Console.Out</c>. When using non-seekable streams for output, the entry
- /// header - which indicates whether zip64 is in use - is emitted before it is
- /// known if zip64 is necessary. It is only after all entries have been saved
- /// that it can be known if ZIP64 will be required. On seekable output streams,
- /// after saving all entries, the library can seek backward and re-emit the zip
- /// file header to be consistent with the actual ZIP64 requirement. But using a
- /// non-seekable output stream, the library cannot seek backward, so the header
- /// can never be changed. In other words, the archive's use of ZIP64 extensions is
- /// not alterable after the header is emitted. Therefore, when saving to
- /// non-seekable streams, using <see cref="Zip64Option.AsNecessary"/> is the same
- /// as using <see cref="Zip64Option.Always"/>: it will always produce a zip
- /// archive that uses ZIP64 extensions.
- /// </para>
- ///
- /// </remarks>
- public enum Zip64Option
- {
- /// <summary>
- /// The default behavior, which is "Never".
- /// (For COM clients, this is a 0 (zero).)
- /// </summary>
- Default = 0,
- /// <summary>
- /// Do not use ZIP64 extensions when writing zip archives.
- /// (For COM clients, this is a 0 (zero).)
- /// </summary>
- Never = 0,
- /// <summary>
- /// Use ZIP64 extensions when writing zip archives, as necessary.
- /// For example, when a single entry exceeds 0xFFFFFFFF in size, or when the archive as a whole
- /// exceeds 0xFFFFFFFF in size, or when there are more than 65535 entries in an archive.
- /// (For COM clients, this is a 1.)
- /// </summary>
- AsNecessary = 1,
- /// <summary>
- /// Always use ZIP64 extensions when writing zip archives, even when unnecessary.
- /// (For COM clients, this is a 2.)
- /// </summary>
- Always
- }
- /// <summary>
- /// An enum representing the values on a three-way toggle switch
- /// for various options in the library. This might be used to
- /// specify whether to employ a particular text encoding, or to use
- /// ZIP64 extensions, or some other option.
- /// </summary>
- public enum ZipOption
- {
- /// <summary>
- /// The default behavior. This is the same as "Never".
- /// (For COM clients, this is a 0 (zero).)
- /// </summary>
- Default = 0,
- /// <summary>
- /// Never use the associated option.
- /// (For COM clients, this is a 0 (zero).)
- /// </summary>
- Never = 0,
- /// <summary>
- /// Use the associated behavior "as necessary."
- /// (For COM clients, this is a 1.)
- /// </summary>
- AsNecessary = 1,
- /// <summary>
- /// Use the associated behavior Always, whether necessary or not.
- /// (For COM clients, this is a 2.)
- /// </summary>
- Always
- }
- enum AddOrUpdateAction
- {
- AddOnly = 0,
- AddOrUpdate
- }
- }
- // ==================================================================
- //
- // Information on the ZIP format:
- //
- // From
- // http://www.pkware.com/documents/casestudies/APPNOTE.TXT
- //
- // Overall .ZIP file format:
- //
- // [local file header 1]
- // [file data 1]
- // [data descriptor 1] ** sometimes
- // .
- // .
- // .
- // [local file header n]
- // [file data n]
- // [data descriptor n] ** sometimes
- // [archive decryption header]
- // [archive extra data record]
- // [central directory]
- // [zip64 end of central directory record]
- // [zip64 end of central directory locator]
- // [end of central directory record]
- //
- // Local File Header format:
- // local file header signature ... 4 bytes (0x04034b50)
- // version needed to extract ..... 2 bytes
- // general purpose bit field ..... 2 bytes
- // compression method ............ 2 bytes
- // last mod file time ............ 2 bytes
- // last mod file date............. 2 bytes
- // crc-32 ........................ 4 bytes
- // compressed size................ 4 bytes
- // uncompressed size.............. 4 bytes
- // file name length............... 2 bytes
- // extra field length ............ 2 bytes
- // file name varies
- // extra field varies
- //
- //
- // Data descriptor: (used only when bit 3 of the general purpose bitfield is set)
- // (although, I have found zip files where bit 3 is not set, yet this descriptor is present!)
- // local file header signature 4 bytes (0x08074b50) ** sometimes!!! Not always
- // crc-32 4 bytes
- // compressed size 4 bytes
- // uncompressed size 4 bytes
- //
- //
- // Central directory structure:
- //
- // [file header 1]
- // .
- // .
- // .
- // [file header n]
- // [digital signature]
- //
- //
- // File header: (This is a ZipDirEntry)
- // central file header signature 4 bytes (0x02014b50)
- // version made by 2 bytes
- // version needed to extract 2 bytes
- // general purpose bit flag 2 bytes
- // compression method 2 bytes
- // last mod file time 2 bytes
- // last mod file date 2 bytes
- // crc-32 4 bytes
- // compressed size 4 bytes
- // uncompressed size 4 bytes
- // file name length 2 bytes
- // extra field length 2 bytes
- // file comment length 2 bytes
- // disk number start 2 bytes
- // internal file attributes ** 2 bytes
- // external file attributes *** 4 bytes
- // relative offset of local header 4 bytes
- // file name (variable size)
- // extra field (variable size)
- // file comment (variable size)
- //
- // ** The internal file attributes, near as I can tell,
- // uses 0x01 for a file and a 0x00 for a directory.
- //
- // ***The external file attributes follows the MS-DOS file attribute byte, described here:
- // at http://support.microsoft.com/kb/q125019/
- // 0x0010 => directory
- // 0x0020 => file
- //
- //
- // End of central directory record:
- //
- // end of central dir signature 4 bytes (0x06054b50)
- // number of this disk 2 bytes
- // number of the disk with the
- // start of the central directory 2 bytes
- // total number of entries in the
- // central directory on this disk 2 bytes
- // total number of entries in
- // the central directory 2 bytes
- // size of the central directory 4 bytes
- // offset of start of central
- // directory with respect to
- // the starting disk number 4 bytes
- // .ZIP file comment length 2 bytes
- // .ZIP file comment (variable size)
- //
- // date and time are packed values, as MSDOS did them
- // time: bits 0-4 : seconds (divided by 2)
- // 5-10: minute
- // 11-15: hour
- // date bits 0-4 : day
- // 5-8: month
- // 9-15 year (since 1980)
- //
- // see http://msdn.microsoft.com/en-us/library/ms724274(VS.85).aspx
|