├── .gitignore ├── BZip2 ├── BZip2Compressor.cs ├── BZip2InputStream.cs ├── BZip2OutputStream.cs ├── BitWriter.cs ├── NOTICE.txt ├── ParallelBZip2OutputStream.cs └── Rand.cs ├── Binaries ├── Debug │ ├── Ionic.Zip.Unity.XML │ ├── Ionic.Zip.Unity.dll │ └── Ionic.Zip.Unity.pdb └── Release │ ├── Ionic.Zip.Unity.XML │ ├── Ionic.Zip.Unity.dll │ └── Ionic.Zip.Unity.pdb ├── CommonSrc ├── CRC32.cs └── Iso8859Dash1Encoding.cs ├── DotNetZip.sln ├── License.BZip2.txt ├── License.Combined.rtf ├── License.txt ├── License.zlib.txt ├── README.md ├── Readme.txt ├── SolutionInfo.cs ├── Zip Reduced ├── Properties │ └── AssemblyInfo.cs └── Zip Reduced.csproj ├── Zip ├── ComHelper.cs ├── EncryptionAlgorithm.cs ├── Events.cs ├── Exceptions.cs ├── ExtractExistingFileAction.cs ├── FileSelector.cs ├── OffsetStream.cs ├── Shared.cs ├── WinZipAes.cs ├── ZipConstants.cs ├── ZipCrypto.cs ├── ZipDirEntry.cs ├── ZipEntry.Extract.cs ├── ZipEntry.Read.cs ├── ZipEntry.Write.cs ├── ZipEntry.cs ├── ZipEntrySource.cs ├── ZipErrorAction.cs ├── ZipFile.AddUpdate.cs ├── ZipFile.Check.cs ├── ZipFile.Events.cs ├── ZipFile.Extract.cs ├── ZipFile.Read.cs ├── ZipFile.Save.cs ├── ZipFile.SaveSelfExtractor.cs ├── ZipFile.Selector.cs ├── ZipFile.cs ├── ZipFile.x-IEnumerable.cs ├── ZipInputStream.cs ├── ZipOutputStream.cs └── ZipSegmentedStream.cs └── Zlib ├── Deflate.cs ├── DeflateStream.cs ├── GZipStream.cs ├── InfTree.cs ├── Inflate.cs ├── LICENSE.jzlib.txt ├── License.zlib.txt ├── ParallelDeflateOutputStream.cs ├── Tree.cs ├── Zlib.cs ├── ZlibBaseStream.cs ├── ZlibCodec.cs ├── ZlibConstants.cs └── ZlibStream.cs /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | TestResults 4 | notused 5 | _UpgradeReport_Files 6 | Backup 7 | UpgradeLog.XML 8 | CodePlex-Readme.txt 9 | License.rtf 10 | FixProps.ps1 11 | makeSrcZip.bat 12 | MakeReleaseZips.bat 13 | clean.ps1 14 | AppNote.txt 15 | Todo.txt 16 | MakeZipUtils.ps1 17 | SetVersion.ps1 18 | Help 19 | LastBuild.log 20 | _Resharper* 21 | *.resharper 22 | *.cache 23 | *.suo 24 | *.user 25 | #*.*# 26 | *.*~ 27 | *.zip 28 | -------------------------------------------------------------------------------- /BZip2/BZip2OutputStream.cs: -------------------------------------------------------------------------------- 1 | //#define Trace 2 | 3 | // BZip2OutputStream.cs 4 | // ------------------------------------------------------------------ 5 | // 6 | // Copyright (c) 2011 Dino Chiesa. 7 | // All rights reserved. 8 | // 9 | // This code module is part of DotNetZip, a zipfile class library. 10 | // 11 | // ------------------------------------------------------------------ 12 | // 13 | // This code is licensed under the Microsoft Public License. 14 | // See the file License.txt for the license details. 15 | // More info on: http://dotnetzip.codeplex.com 16 | // 17 | // ------------------------------------------------------------------ 18 | // 19 | // Last Saved: <2011-August-02 16:44:11> 20 | // 21 | // ------------------------------------------------------------------ 22 | // 23 | // This module defines the BZip2OutputStream class, which is a 24 | // compressing stream that handles BZIP2. This code may have been 25 | // derived in part from Apache commons source code. The license below 26 | // applies to the original Apache code. 27 | // 28 | // ------------------------------------------------------------------ 29 | // flymake: csc.exe /t:module BZip2InputStream.cs BZip2Compressor.cs Rand.cs BCRC32.cs @@FILE@@ 30 | 31 | /* 32 | * Licensed to the Apache Software Foundation (ASF) under one 33 | * or more contributor license agreements. See the NOTICE file 34 | * distributed with this work for additional information 35 | * regarding copyright ownership. The ASF licenses this file 36 | * to you under the Apache License, Version 2.0 (the 37 | * "License"); you may not use this file except in compliance 38 | * with the License. You may obtain a copy of the License at 39 | * 40 | * http://www.apache.org/licenses/LICENSE-2.0 41 | * 42 | * Unless required by applicable law or agreed to in writing, 43 | * software distributed under the License is distributed on an 44 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 45 | * KIND, either express or implied. See the License for the 46 | * specific language governing permissions and limitations 47 | * under the License. 48 | */ 49 | 50 | 51 | // Design Notes: 52 | // 53 | // This class follows the classic Decorator pattern: it is a Stream that 54 | // wraps itself around a Stream, and in doing so provides bzip2 55 | // compression as callers Write into it. 56 | // 57 | // BZip2 is a straightforward data format: there are 4 magic bytes at 58 | // the top of the file, followed by 1 or more compressed blocks. There 59 | // is a small "magic byte" trailer after all compressed blocks. This 60 | // class emits the magic bytes for the header and trailer, and relies on 61 | // a BZip2Compressor to generate each of the compressed data blocks. 62 | // 63 | // BZip2 does byte-shredding - it uses partial fractions of bytes to 64 | // represent independent pieces of information. This class relies on the 65 | // BitWriter to adapt the bit-oriented BZip2 output to the byte-oriented 66 | // model of the .NET Stream class. 67 | // 68 | // ---- 69 | // 70 | // Regarding the Apache code base: Most of the code in this particular 71 | // class is related to stream operations, and is my own code. It largely 72 | // does not rely on any code obtained from Apache commons. If you 73 | // compare this code with the Apache commons BZip2OutputStream, you will 74 | // see very little code that is common, except for the 75 | // nearly-boilerplate structure that is common to all subtypes of 76 | // System.IO.Stream. There may be some small remnants of code in this 77 | // module derived from the Apache stuff, which is why I left the license 78 | // in here. Most of the Apache commons compressor magic has been ported 79 | // into the BZip2Compressor class. 80 | // 81 | 82 | using System; 83 | using System.IO; 84 | 85 | 86 | namespace Ionic.BZip2 87 | { 88 | /// 89 | /// A write-only decorator stream that compresses data as it is 90 | /// written using the BZip2 algorithm. 91 | /// 92 | public class BZip2OutputStream : System.IO.Stream 93 | { 94 | int totalBytesWrittenIn; 95 | bool leaveOpen; 96 | BZip2Compressor compressor; 97 | uint combinedCRC; 98 | Stream output; 99 | BitWriter bw; 100 | int blockSize100k; // 0...9 101 | 102 | private TraceBits desiredTrace = TraceBits.Crc | TraceBits.Write; 103 | 104 | /// 105 | /// Constructs a new BZip2OutputStream, that sends its 106 | /// compressed output to the given output stream. 107 | /// 108 | /// 109 | /// 110 | /// The destination stream, to which compressed output will be sent. 111 | /// 112 | /// 113 | /// 114 | /// 115 | /// This example reads a file, then compresses it with bzip2 file, 116 | /// and writes the compressed data into a newly created file. 117 | /// 118 | /// 119 | /// var fname = "logfile.log"; 120 | /// using (var fs = File.OpenRead(fname)) 121 | /// { 122 | /// var outFname = fname + ".bz2"; 123 | /// using (var output = File.Create(outFname)) 124 | /// { 125 | /// using (var compressor = new Ionic.BZip2.BZip2OutputStream(output)) 126 | /// { 127 | /// byte[] buffer = new byte[2048]; 128 | /// int n; 129 | /// while ((n = fs.Read(buffer, 0, buffer.Length)) > 0) 130 | /// { 131 | /// compressor.Write(buffer, 0, n); 132 | /// } 133 | /// } 134 | /// } 135 | /// } 136 | /// 137 | /// 138 | public BZip2OutputStream(Stream output) 139 | : this(output, BZip2.MaxBlockSize, false) 140 | { 141 | } 142 | 143 | 144 | /// 145 | /// Constructs a new BZip2OutputStream with specified blocksize. 146 | /// 147 | /// the destination stream. 148 | /// 149 | /// The blockSize in units of 100000 bytes. 150 | /// The valid range is 1..9. 151 | /// 152 | public BZip2OutputStream(Stream output, int blockSize) 153 | : this(output, blockSize, false) 154 | { 155 | } 156 | 157 | 158 | /// 159 | /// Constructs a new BZip2OutputStream. 160 | /// 161 | /// the destination stream. 162 | /// 163 | /// whether to leave the captive stream open upon closing this stream. 164 | /// 165 | public BZip2OutputStream(Stream output, bool leaveOpen) 166 | : this(output, BZip2.MaxBlockSize, leaveOpen) 167 | { 168 | } 169 | 170 | 171 | /// 172 | /// Constructs a new BZip2OutputStream with specified blocksize, 173 | /// and explicitly specifies whether to leave the wrapped stream open. 174 | /// 175 | /// 176 | /// the destination stream. 177 | /// 178 | /// The blockSize in units of 100000 bytes. 179 | /// The valid range is 1..9. 180 | /// 181 | /// 182 | /// whether to leave the captive stream open upon closing this stream. 183 | /// 184 | public BZip2OutputStream(Stream output, int blockSize, bool leaveOpen) 185 | { 186 | if (blockSize < BZip2.MinBlockSize || 187 | blockSize > BZip2.MaxBlockSize) 188 | { 189 | var msg = String.Format("blockSize={0} is out of range; must be between {1} and {2}", 190 | blockSize, 191 | BZip2.MinBlockSize, BZip2.MaxBlockSize); 192 | throw new ArgumentException(msg, "blockSize"); 193 | } 194 | 195 | this.output = output; 196 | if (!this.output.CanWrite) 197 | throw new ArgumentException("The stream is not writable.", "output"); 198 | 199 | this.bw = new BitWriter(this.output); 200 | this.blockSize100k = blockSize; 201 | this.compressor = new BZip2Compressor(this.bw, blockSize); 202 | this.leaveOpen = leaveOpen; 203 | this.combinedCRC = 0; 204 | EmitHeader(); 205 | } 206 | 207 | 208 | 209 | 210 | /// 211 | /// Close the stream. 212 | /// 213 | /// 214 | /// 215 | /// This may or may not close the underlying stream. Check the 216 | /// constructors that accept a bool value. 217 | /// 218 | /// 219 | public override void Close() 220 | { 221 | if (output != null) 222 | { 223 | Stream o = this.output; 224 | Finish(); 225 | if (!leaveOpen) 226 | o.Close(); 227 | } 228 | } 229 | 230 | 231 | /// 232 | /// Flush the stream. 233 | /// 234 | public override void Flush() 235 | { 236 | if (this.output != null) 237 | { 238 | this.bw.Flush(); 239 | this.output.Flush(); 240 | } 241 | } 242 | 243 | private void EmitHeader() 244 | { 245 | var magic = new byte[] { 246 | (byte) 'B', 247 | (byte) 'Z', 248 | (byte) 'h', 249 | (byte) ('0' + this.blockSize100k) 250 | }; 251 | 252 | // not necessary to shred the initial magic bytes 253 | this.output.Write(magic, 0, magic.Length); 254 | } 255 | 256 | private void EmitTrailer() 257 | { 258 | // A magic 48-bit number, 0x177245385090, to indicate the end 259 | // of the last block. (sqrt(pi), if you want to know) 260 | 261 | TraceOutput(TraceBits.Write, "total written out: {0} (0x{0:X})", 262 | this.bw.TotalBytesWrittenOut); 263 | 264 | // must shred 265 | this.bw.WriteByte(0x17); 266 | this.bw.WriteByte(0x72); 267 | this.bw.WriteByte(0x45); 268 | this.bw.WriteByte(0x38); 269 | this.bw.WriteByte(0x50); 270 | this.bw.WriteByte(0x90); 271 | 272 | this.bw.WriteInt(this.combinedCRC); 273 | 274 | this.bw.FinishAndPad(); 275 | 276 | TraceOutput(TraceBits.Write, "final total: {0} (0x{0:X})", 277 | this.bw.TotalBytesWrittenOut); 278 | } 279 | 280 | void Finish() 281 | { 282 | // Console.WriteLine("BZip2:Finish"); 283 | 284 | try 285 | { 286 | var totalBefore = this.bw.TotalBytesWrittenOut; 287 | this.compressor.CompressAndWrite(); 288 | TraceOutput(TraceBits.Write,"out block length (bytes): {0} (0x{0:X})", 289 | this.bw.TotalBytesWrittenOut - totalBefore); 290 | 291 | TraceOutput(TraceBits.Crc, " combined CRC (before): {0:X8}", 292 | this.combinedCRC); 293 | this.combinedCRC = (this.combinedCRC << 1) | (this.combinedCRC >> 31); 294 | this.combinedCRC ^= (uint) compressor.Crc32; 295 | TraceOutput(TraceBits.Crc, " block CRC : {0:X8}", 296 | this.compressor.Crc32); 297 | TraceOutput(TraceBits.Crc, " combined CRC (final) : {0:X8}", 298 | this.combinedCRC); 299 | 300 | EmitTrailer(); 301 | } 302 | finally 303 | { 304 | this.output = null; 305 | this.compressor = null; 306 | this.bw = null; 307 | } 308 | } 309 | 310 | 311 | /// 312 | /// The blocksize parameter specified at construction time. 313 | /// 314 | public int BlockSize 315 | { 316 | get { return this.blockSize100k; } 317 | } 318 | 319 | 320 | /// 321 | /// Write data to the stream. 322 | /// 323 | /// 324 | /// 325 | /// 326 | /// Use the BZip2OutputStream to compress data while writing: 327 | /// create a BZip2OutputStream with a writable output stream. 328 | /// Then call Write() on that BZip2OutputStream, providing 329 | /// uncompressed data as input. The data sent to the output stream will 330 | /// be the compressed form of the input data. 331 | /// 332 | /// 333 | /// 334 | /// A BZip2OutputStream can be used only for Write() not for Read(). 335 | /// 336 | /// 337 | /// 338 | /// 339 | /// The buffer holding data to write to the stream. 340 | /// the offset within that data array to find the first byte to write. 341 | /// the number of bytes to write. 342 | public override void Write(byte[] buffer, int offset, int count) 343 | { 344 | if (offset < 0) 345 | throw new IndexOutOfRangeException(String.Format("offset ({0}) must be > 0", offset)); 346 | if (count < 0) 347 | throw new IndexOutOfRangeException(String.Format("count ({0}) must be > 0", count)); 348 | if (offset + count > buffer.Length) 349 | throw new IndexOutOfRangeException(String.Format("offset({0}) count({1}) bLength({2})", 350 | offset, count, buffer.Length)); 351 | if (this.output == null) 352 | throw new IOException("the stream is not open"); 353 | 354 | if (count == 0) return; // nothing to do 355 | 356 | int bytesWritten = 0; 357 | int bytesRemaining = count; 358 | 359 | do 360 | { 361 | int n = compressor.Fill(buffer, offset, bytesRemaining); 362 | if (n != bytesRemaining) 363 | { 364 | // The compressor data block is full. Compress and 365 | // write out the compressed data, then reset the 366 | // compressor and continue. 367 | 368 | var totalBefore = this.bw.TotalBytesWrittenOut; 369 | this.compressor.CompressAndWrite(); 370 | TraceOutput(TraceBits.Write,"out block length (bytes): {0} (0x{0:X})", 371 | this.bw.TotalBytesWrittenOut - totalBefore); 372 | 373 | // and now any remaining bits 374 | TraceOutput(TraceBits.Write, 375 | " remaining: {0} 0x{1:X}", 376 | this.bw.NumRemainingBits, 377 | this.bw.RemainingBits); 378 | 379 | TraceOutput(TraceBits.Crc, " combined CRC (before): {0:X8}", 380 | this.combinedCRC); 381 | this.combinedCRC = (this.combinedCRC << 1) | (this.combinedCRC >> 31); 382 | this.combinedCRC ^= (uint) compressor.Crc32; 383 | TraceOutput(TraceBits.Crc, " block CRC : {0:X8}", 384 | compressor.Crc32); 385 | TraceOutput(TraceBits.Crc, " combined CRC (after) : {0:X8}", 386 | this.combinedCRC); 387 | offset += n; 388 | } 389 | bytesRemaining -= n; 390 | bytesWritten += n; 391 | } while (bytesRemaining > 0); 392 | 393 | totalBytesWrittenIn += bytesWritten; 394 | } 395 | 396 | 397 | 398 | 399 | /// 400 | /// Indicates whether the stream can be read. 401 | /// 402 | /// 403 | /// The return value is always false. 404 | /// 405 | public override bool CanRead 406 | { 407 | get { return false; } 408 | } 409 | 410 | /// 411 | /// Indicates whether the stream supports Seek operations. 412 | /// 413 | /// 414 | /// Always returns false. 415 | /// 416 | public override bool CanSeek 417 | { 418 | get { return false; } 419 | } 420 | 421 | /// 422 | /// Indicates whether the stream can be written. 423 | /// 424 | /// 425 | /// The return value should always be true, unless and until the 426 | /// object is disposed and closed. 427 | /// 428 | public override bool CanWrite 429 | { 430 | get 431 | { 432 | if (this.output == null) throw new ObjectDisposedException("BZip2Stream"); 433 | return this.output.CanWrite; 434 | } 435 | } 436 | 437 | /// 438 | /// Reading this property always throws a . 439 | /// 440 | public override long Length 441 | { 442 | get { throw new NotImplementedException(); } 443 | } 444 | 445 | /// 446 | /// The position of the stream pointer. 447 | /// 448 | /// 449 | /// 450 | /// Setting this property always throws a . Reading will return the 452 | /// total number of uncompressed bytes written through. 453 | /// 454 | public override long Position 455 | { 456 | get 457 | { 458 | return this.totalBytesWrittenIn; 459 | } 460 | set { throw new NotImplementedException(); } 461 | } 462 | 463 | /// 464 | /// Calling this method always throws a . 465 | /// 466 | /// this is irrelevant, since it will always throw! 467 | /// this is irrelevant, since it will always throw! 468 | /// irrelevant! 469 | public override long Seek(long offset, System.IO.SeekOrigin origin) 470 | { 471 | throw new NotImplementedException(); 472 | } 473 | 474 | /// 475 | /// Calling this method always throws a . 476 | /// 477 | /// this is irrelevant, since it will always throw! 478 | public override void SetLength(long value) 479 | { 480 | throw new NotImplementedException(); 481 | } 482 | 483 | /// 484 | /// Calling this method always throws a . 485 | /// 486 | /// this parameter is never used 487 | /// this parameter is never used 488 | /// this parameter is never used 489 | /// never returns anything; always throws 490 | public override int Read(byte[] buffer, int offset, int count) 491 | { 492 | throw new NotImplementedException(); 493 | } 494 | 495 | 496 | // used only when Trace is defined 497 | [Flags] 498 | enum TraceBits : uint 499 | { 500 | None = 0, 501 | Crc = 1, 502 | Write = 2, 503 | All = 0xffffffff, 504 | } 505 | 506 | 507 | [System.Diagnostics.ConditionalAttribute("Trace")] 508 | private void TraceOutput(TraceBits bits, string format, params object[] varParams) 509 | { 510 | if ((bits & this.desiredTrace) != 0) 511 | { 512 | //lock(outputLock) 513 | { 514 | int tid = System.Threading.Thread.CurrentThread.GetHashCode(); 515 | #if !SILVERLIGHT && !NETCF 516 | Console.ForegroundColor = (ConsoleColor) (tid % 8 + 10); 517 | #endif 518 | Console.Write("{0:000} PBOS ", tid); 519 | Console.WriteLine(format, varParams); 520 | #if !SILVERLIGHT && !NETCF 521 | Console.ResetColor(); 522 | #endif 523 | } 524 | } 525 | } 526 | 527 | 528 | } 529 | 530 | } 531 | -------------------------------------------------------------------------------- /BZip2/BitWriter.cs: -------------------------------------------------------------------------------- 1 | // BitWriter.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2011 Dino Chiesa. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // Last Saved: <2011-July-25 18:57:31> 18 | // 19 | // ------------------------------------------------------------------ 20 | // 21 | // This module defines the BitWriter class, which writes bits at a time 22 | // to an output stream. It's used by the BZip2Compressor class, and by 23 | // the BZip2OutputStream class and its parallel variant, 24 | // ParallelBZip2OutputStream. 25 | // 26 | // ------------------------------------------------------------------ 27 | 28 | // 29 | // Design notes: 30 | // 31 | // BZip2 employs byte-shredding in its data format - rather than 32 | // aligning all data items in a compressed .bz2 file on byte barriers, 33 | // the BZip2 format uses portions of bytes to represent independent 34 | // pieces of information. This "shredding" starts with the first 35 | // "randomised" bit - just 12 bytes or so into a bz2 file or stream. But 36 | // the approach is used extensively in bzip2 files - sometimes 5 bits 37 | // are used, sometimes 24 or 3 bits, sometimes just 1 bit, and so on. 38 | // It's not possible to send this information directly to a stream in 39 | // this form; Streams in .NET accept byte-oriented input. Therefore, 40 | // when actually writing a bz2 file, the output data must be organized 41 | // into a byte-aligned format before being written to the output stream. 42 | // 43 | // This BitWriter class provides the byte-shredding necessary for BZip2 44 | // output. Think of this class as an Adapter that enables Bit-oriented 45 | // output to a standard byte-oriented .NET stream. This class writes 46 | // data out to the captive output stream only after the data bits have 47 | // been accumulated and aligned. For example, suppose that during 48 | // operation, the BZip2 compressor emits 5 bits, then 24 bits, then 32 49 | // bits. When the first 5 bits are sent to the BitWriter, nothing is 50 | // written to the output stream; instead these 5 bits are simply stored 51 | // in the internal accumulator. When the next 24 bits are written, the 52 | // first 3 bits are gathered with the accumulated bits. The resulting 53 | // 5+3 constitutes an entire byte; the BitWriter then actually writes 54 | // that byte to the output stream. This leaves 21 bits. BitWriter writes 55 | // 2 more whole bytes (16 more bits), in 8-bit chunks, leaving 5 in the 56 | // accumulator. BitWriter then follows the same procedure with the 32 57 | // new bits. And so on. 58 | // 59 | // A quick tour of the implementation: 60 | // 61 | // The accumulator is a uint - so it can accumulate at most 4 bytes of 62 | // information. In practice because of the design of this class, it 63 | // never accumulates more than 3 bytes. 64 | // 65 | // The Flush() method emits all whole bytes available. After calling 66 | // Flush(), there may be between 0-7 bits yet to be emitted into the 67 | // output stream. 68 | // 69 | // FinishAndPad() emits all data, including the last partial byte and 70 | // any necessary padding. In effect, it establishes a byte-alignment 71 | // barrier. To support bzip2, FinishAndPad() should be called only once 72 | // for a bz2 file, after the last bit of data has been written through 73 | // this adapter. Other binary file formats may use byte-alignment at 74 | // various points within the file, and FinishAndPad() would support that 75 | // scenario. 76 | // 77 | // The internal fn Reset() is used to reset the state of the adapter; 78 | // this class is used by BZip2Compressor, instances of which get re-used 79 | // by multiple distinct threads, for different blocks of data. 80 | // 81 | 82 | 83 | using System; 84 | using System.IO; 85 | 86 | namespace Ionic.BZip2 87 | { 88 | 89 | internal class BitWriter 90 | { 91 | uint accumulator; 92 | int nAccumulatedBits; 93 | Stream output; 94 | int totalBytesWrittenOut; 95 | 96 | public BitWriter(Stream s) 97 | { 98 | this.output = s; 99 | } 100 | 101 | /// 102 | /// Delivers the remaining bits, left-aligned, in a byte. 103 | /// 104 | /// 105 | /// 106 | /// This is valid only if NumRemainingBits is less than 8; 107 | /// in other words it is valid only after a call to Flush(). 108 | /// 109 | /// 110 | public byte RemainingBits 111 | { 112 | get 113 | { 114 | return (byte) (this.accumulator >> (32 - this.nAccumulatedBits) & 0xff); 115 | } 116 | } 117 | 118 | public int NumRemainingBits 119 | { 120 | get 121 | { 122 | return this.nAccumulatedBits; 123 | } 124 | } 125 | 126 | public int TotalBytesWrittenOut 127 | { 128 | get 129 | { 130 | return this.totalBytesWrittenOut; 131 | } 132 | } 133 | 134 | /// 135 | /// Reset the BitWriter. 136 | /// 137 | /// 138 | /// 139 | /// This is useful when the BitWriter writes into a MemoryStream, and 140 | /// is used by a BZip2Compressor, which itself is re-used for multiple 141 | /// distinct data blocks. 142 | /// 143 | /// 144 | public void Reset() 145 | { 146 | this.accumulator = 0; 147 | this.nAccumulatedBits = 0; 148 | this.totalBytesWrittenOut = 0; 149 | this.output.Seek(0, SeekOrigin.Begin); 150 | this.output.SetLength(0); 151 | } 152 | 153 | /// 154 | /// Write some number of bits from the given value, into the output. 155 | /// 156 | /// 157 | /// 158 | /// The nbits value should be a max of 25, for safety. For performance 159 | /// reasons, this method does not check! 160 | /// 161 | /// 162 | public void WriteBits(int nbits, uint value) 163 | { 164 | int nAccumulated = this.nAccumulatedBits; 165 | uint u = this.accumulator; 166 | 167 | while (nAccumulated >= 8) 168 | { 169 | this.output.WriteByte ((byte)(u >> 24 & 0xff)); 170 | this.totalBytesWrittenOut++; 171 | u <<= 8; 172 | nAccumulated -= 8; 173 | } 174 | 175 | this.accumulator = u | (value << (32 - nAccumulated - nbits)); 176 | this.nAccumulatedBits = nAccumulated + nbits; 177 | 178 | // Console.WriteLine("WriteBits({0}, 0x{1:X2}) => {2:X8} n({3})", 179 | // nbits, value, accumulator, nAccumulatedBits); 180 | // Console.ReadLine(); 181 | 182 | // At this point the accumulator may contain up to 31 bits waiting for 183 | // output. 184 | } 185 | 186 | 187 | /// 188 | /// Write a full 8-bit byte into the output. 189 | /// 190 | public void WriteByte(byte b) 191 | { 192 | WriteBits(8, b); 193 | } 194 | 195 | /// 196 | /// Write four 8-bit bytes into the output. 197 | /// 198 | public void WriteInt(uint u) 199 | { 200 | WriteBits(8, (u >> 24) & 0xff); 201 | WriteBits(8, (u >> 16) & 0xff); 202 | WriteBits(8, (u >> 8) & 0xff); 203 | WriteBits(8, u & 0xff); 204 | } 205 | 206 | /// 207 | /// Write all available byte-aligned bytes. 208 | /// 209 | /// 210 | /// 211 | /// This method writes no new output, but flushes any accumulated 212 | /// bits. At completion, the accumulator may contain up to 7 213 | /// bits. 214 | /// 215 | /// 216 | /// This is necessary when re-assembling output from N independent 217 | /// compressors, one for each of N blocks. The output of any 218 | /// particular compressor will in general have some fragment of a byte 219 | /// remaining. This fragment needs to be accumulated into the 220 | /// parent BZip2OutputStream. 221 | /// 222 | /// 223 | public void Flush() 224 | { 225 | WriteBits(0,0); 226 | } 227 | 228 | 229 | /// 230 | /// Writes all available bytes, and emits padding for the final byte as 231 | /// necessary. This must be the last method invoked on an instance of 232 | /// BitWriter. 233 | /// 234 | public void FinishAndPad() 235 | { 236 | Flush(); 237 | 238 | if (this.NumRemainingBits > 0) 239 | { 240 | byte b = (byte)((this.accumulator >> 24) & 0xff); 241 | this.output.WriteByte(b); 242 | this.totalBytesWrittenOut++; 243 | } 244 | } 245 | 246 | } 247 | 248 | } -------------------------------------------------------------------------------- /BZip2/NOTICE.txt: -------------------------------------------------------------------------------- 1 | Apache Commons Compress 2 | Copyright 2002-2010 The Apache Software Foundation 3 | 4 | This product includes software developed by 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /BZip2/Rand.cs: -------------------------------------------------------------------------------- 1 | // Rand.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2011 Dino Chiesa. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // Last Saved: <2011-July-31 15:09:16> 18 | // 19 | // ------------------------------------------------------------------ 20 | // 21 | // This module defines a helper class for the BZip2 classes. This code 22 | // is derived from the original BZip2 source code. 23 | // 24 | // ------------------------------------------------------------------ 25 | 26 | 27 | namespace Ionic.BZip2 28 | { 29 | internal static class Rand 30 | { 31 | private static int[] RNUMS = 32 | { 33 | 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 34 | 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 35 | 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 36 | 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 37 | 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 38 | 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 39 | 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 40 | 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 41 | 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 42 | 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 43 | 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 44 | 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 45 | 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 46 | 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 47 | 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 48 | 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 49 | 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 50 | 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 51 | 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 52 | 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 53 | 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 54 | 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 55 | 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 56 | 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 57 | 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 58 | 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 59 | 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 60 | 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 61 | 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 62 | 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 63 | 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 64 | 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 65 | 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 66 | 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 67 | 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 68 | 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 69 | 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 70 | 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 71 | 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 72 | 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 73 | 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 74 | 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 75 | 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 76 | 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 77 | 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 78 | 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 79 | 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 80 | 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 81 | 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 82 | 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 83 | 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 84 | 936, 638 85 | }; 86 | 87 | 88 | /// 89 | /// Returns the "random" number at a specific index. 90 | /// 91 | /// the index 92 | /// the random number 93 | internal static int Rnums(int i) 94 | { 95 | return RNUMS[i]; 96 | } 97 | } 98 | 99 | } -------------------------------------------------------------------------------- /Binaries/Debug/Ionic.Zip.Unity.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r2d2rigo/dotnetzip-for-unity/b6e3951d18a9d28f7ef329c2065b284bd869451a/Binaries/Debug/Ionic.Zip.Unity.dll -------------------------------------------------------------------------------- /Binaries/Debug/Ionic.Zip.Unity.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r2d2rigo/dotnetzip-for-unity/b6e3951d18a9d28f7ef329c2065b284bd869451a/Binaries/Debug/Ionic.Zip.Unity.pdb -------------------------------------------------------------------------------- /Binaries/Release/Ionic.Zip.Unity.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r2d2rigo/dotnetzip-for-unity/b6e3951d18a9d28f7ef329c2065b284bd869451a/Binaries/Release/Ionic.Zip.Unity.dll -------------------------------------------------------------------------------- /Binaries/Release/Ionic.Zip.Unity.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r2d2rigo/dotnetzip-for-unity/b6e3951d18a9d28f7ef329c2065b284bd869451a/Binaries/Release/Ionic.Zip.Unity.pdb -------------------------------------------------------------------------------- /CommonSrc/Iso8859Dash1Encoding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Ionic.Encoding 6 | { 7 | /// 8 | /// Provides a text encoder for the iso-8859-1 encoding, aka Latin1 encoding, 9 | /// for platforms that do not support it, for example on Silverlight or some 10 | /// Compact Framework platforms. 11 | /// 12 | public class Iso8859Dash1Encoding : System.Text.Encoding 13 | { 14 | /// 15 | /// Gets the name registered with the 16 | /// Internet Assigned Numbers Authority (IANA) for the current encoding. 17 | /// 18 | /// 19 | /// Always returns "iso-8859-1". 20 | /// 21 | public override string WebName 22 | { 23 | get { return "iso-8859-1"; } 24 | } 25 | 26 | /// 27 | /// Encodes a set of characters from a character array into 28 | /// a byte array. 29 | /// 30 | /// 31 | /// The actual number of bytes written into . 32 | /// 33 | /// The character array containing the set of characters to encode. 34 | /// The index of the first character to encode. 35 | /// The number of characters to encode. 36 | /// The byte array to contain the resulting sequence of bytes. 37 | /// The index at which to start writing the resulting sequence of bytes. 38 | /// 39 | public override int GetBytes(char[] chars, int start, int count, byte[] bytes, int byteIndex) 40 | { 41 | if (chars == null) 42 | throw new ArgumentNullException("chars", "null array"); 43 | 44 | if (bytes == null) 45 | throw new ArgumentNullException("bytes", "null array"); 46 | 47 | if (start < 0) 48 | throw new ArgumentOutOfRangeException("start"); 49 | if (count < 0) 50 | throw new ArgumentOutOfRangeException("charCount"); 51 | 52 | if ((chars.Length - start) < count) 53 | throw new ArgumentOutOfRangeException("chars"); 54 | 55 | if ((byteIndex < 0) || (byteIndex > bytes.Length)) 56 | throw new ArgumentOutOfRangeException("byteIndex"); 57 | 58 | // iso-8859-1 is special in that it was adopted as the first page of 59 | // UCS - ISO's Universal Coding Standard, described in ISO 10646, 60 | // which is the same as Unicode. This means that a a Unicode 61 | // character in the range of 0 to FF maps to the iso-8859-1 character 62 | // with the same value. Because of that the encoding and decoding is 63 | // trivial. 64 | for (int i=0; i < count; i++) 65 | { 66 | char c = chars[start+i]; // get the unicode char 67 | 68 | if (c >= '\x00FF') // out of range? 69 | bytes[byteIndex+i] = (byte) '?'; 70 | else 71 | bytes[byteIndex+i] = (byte) c; 72 | } 73 | return count; 74 | } 75 | 76 | 77 | /// 78 | /// Decodes a sequence of bytes from the specified byte array into the specified character array. 79 | /// 80 | /// 81 | /// The actual number of characters written into . 82 | /// 83 | /// The byte array containing the sequence of bytes to decode. 84 | /// The index of the first byte to decode. 85 | /// The number of bytes to decode. 86 | /// The character array to contain the resulting set of characters. 87 | /// The index at which to start writing the resulting set of characters. 88 | /// 89 | public override int GetChars(byte[] bytes, int start, int count, char[] chars, int charIndex) 90 | { 91 | if (chars == null) 92 | throw new ArgumentNullException("chars", "null array"); 93 | 94 | if (bytes == null) 95 | throw new ArgumentNullException("bytes", "null array"); 96 | 97 | if (start < 0) 98 | throw new ArgumentOutOfRangeException("start"); 99 | if (count < 0) 100 | throw new ArgumentOutOfRangeException("charCount"); 101 | 102 | if ((bytes.Length - start) < count) 103 | throw new ArgumentOutOfRangeException("bytes"); 104 | 105 | if ((charIndex < 0) || (charIndex > chars.Length)) 106 | throw new ArgumentOutOfRangeException("charIndex"); 107 | 108 | // In the range 00 to FF, the Unicode characters are the same as the 109 | // iso-8859-1 characters; because of that, decoding is trivial. 110 | for (int i = 0; i < count; i++) 111 | chars[charIndex + i] = (char) bytes[i + start]; 112 | 113 | return count; 114 | } 115 | 116 | 117 | /// 118 | /// Calculates the number of bytes produced by encoding a set of characters 119 | /// from the specified character array. 120 | /// 121 | /// 122 | /// The number of bytes produced by encoding the specified characters. This class 123 | /// alwas returns the value of . 124 | /// 125 | public override int GetByteCount(char[] chars, int index, int count) 126 | { 127 | return count; 128 | } 129 | 130 | 131 | /// 132 | /// Calculates the number of characters produced by decoding a sequence 133 | /// of bytes from the specified byte array. 134 | /// 135 | /// 136 | /// The number of characters produced by decoding the specified sequence of bytes. This class 137 | /// alwas returns the value of . 138 | /// 139 | public override int GetCharCount(byte[] bytes, int index, int count) 140 | { 141 | return count; 142 | } 143 | 144 | 145 | /// 146 | /// Calculates the maximum number of bytes produced by encoding the specified number of characters. 147 | /// 148 | /// 149 | /// The maximum number of bytes produced by encoding the specified number of characters. This 150 | /// class alwas returns the value of . 151 | /// 152 | /// The number of characters to encode. 153 | /// 154 | public override int GetMaxByteCount(int charCount) 155 | { 156 | return charCount; 157 | } 158 | 159 | /// 160 | /// Calculates the maximum number of characters produced by decoding the specified number of bytes. 161 | /// 162 | /// 163 | /// The maximum number of characters produced by decoding the specified number of bytes. This class 164 | /// alwas returns the value of . 165 | /// 166 | /// The number of bytes to decode. 167 | public override int GetMaxCharCount(int byteCount) 168 | { 169 | return byteCount; 170 | } 171 | 172 | /// 173 | /// Gets the number of characters that are supported by this encoding. 174 | /// This property returns a maximum value of 256, as the encoding class 175 | /// only supports single byte encodings (1 byte == 256 possible values). 176 | /// 177 | public static int CharacterCount 178 | { 179 | get { return 256; } 180 | } 181 | 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /DotNetZip.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Zip Reduced", "Zip Reduced\Zip Reduced.csproj", "{49A128D3-C3F2-46B1-8F7A-EECD209EA860}" 5 | EndProject 6 | Global 7 | GlobalSection(TestCaseManagementSettings) = postSolution 8 | CategoryFile = DotNetZip.vsmdi 9 | EndGlobalSection 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | Debug|Any CPU = Debug|Any CPU 12 | Debug|Mixed Platforms = Debug|Mixed Platforms 13 | Debug|x86 = Debug|x86 14 | Release|Any CPU = Release|Any CPU 15 | Release|Mixed Platforms = Release|Mixed Platforms 16 | Release|x86 = Release|x86 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 22 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 23 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Debug|x86.ActiveCfg = Debug|Any CPU 24 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 27 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Release|Mixed Platforms.Build.0 = Release|Any CPU 28 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860}.Release|x86.ActiveCfg = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /License.BZip2.txt: -------------------------------------------------------------------------------- 1 | 2 | The managed BZIP2 code included in Ionic.BZip2.dll and Ionic.Zip.dll is 3 | modified code, based on the bzip2 code in the Apache commons compress 4 | library. 5 | 6 | The original BZip2 was created by Julian Seward, and is licensed under 7 | the BSD license. 8 | 9 | The following license applies to the Apache code: 10 | ----------------------------------------------------------------------- 11 | 12 | /* 13 | * Licensed to the Apache Software Foundation (ASF) under one 14 | * or more contributor license agreements. See the NOTICE file 15 | * distributed with this work for additional information 16 | * regarding copyright ownership. The ASF licenses this file 17 | * to you under the Apache License, Version 2.0 (the 18 | * "License"); you may not use this file except in compliance 19 | * with the License. You may obtain a copy of the License at 20 | * 21 | * http://www.apache.org/licenses/LICENSE-2.0 22 | * 23 | * Unless required by applicable law or agreed to in writing, 24 | * software distributed under the License is distributed on an 25 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 26 | * KIND, either express or implied. See the License for the 27 | * specific language governing permissions and limitations 28 | * under the License. 29 | */ 30 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Microsoft Public License (Ms-PL) 2 | 3 | This license governs use of the accompanying software, the DotNetZip library ("the software"). If you use the software, you accept this license. If you do not accept the license, do not use the software. 4 | 5 | 1. Definitions 6 | 7 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. 8 | 9 | A "contribution" is the original software, or any additions or changes to the software. 10 | 11 | A "contributor" is any person that distributes its contribution under this license. 12 | 13 | "Licensed patents" are a contributor's patent claims that read directly on its contribution. 14 | 15 | 2. Grant of Rights 16 | 17 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. 18 | 19 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 20 | 21 | 3. Conditions and Limitations 22 | 23 | (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. 24 | 25 | (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. 26 | 27 | (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 28 | 29 | (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. 30 | 31 | (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. 32 | 33 | 34 | -------------------------------------------------------------------------------- /License.zlib.txt: -------------------------------------------------------------------------------- 1 | 2 | The following licenses govern use of the accompanying software, the 3 | DotNetZip library ("the software"). If you use the software, you accept 4 | these licenses. If you do not accept the license, do not use the software. 5 | 6 | The managed ZLIB code included in Ionic.Zlib.dll and Ionic.Zip.dll is 7 | modified code, based on jzlib. 8 | 9 | 10 | 11 | The following notice applies to jzlib: 12 | ----------------------------------------------------------------------- 13 | 14 | Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. 15 | 16 | Redistribution and use in source and binary forms, with or without 17 | modification, are permitted provided that the following conditions are met: 18 | 19 | 1. Redistributions of source code must retain the above copyright notice, 20 | this list of conditions and the following disclaimer. 21 | 22 | 2. Redistributions in binary form must reproduce the above copyright 23 | notice, this list of conditions and the following disclaimer in 24 | the documentation and/or other materials provided with the distribution. 25 | 26 | 3. The names of the authors may not be used to endorse or promote products 27 | derived from this software without specific prior written permission. 28 | 29 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 30 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, 32 | INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 33 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 35 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 37 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 38 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | 40 | ----------------------------------------------------------------------- 41 | 42 | jzlib is based on zlib-1.1.3. 43 | 44 | The following notice applies to zlib: 45 | 46 | ----------------------------------------------------------------------- 47 | 48 | Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler 49 | 50 | The ZLIB software is provided 'as-is', without any express or implied 51 | warranty. In no event will the authors be held liable for any damages 52 | arising from the use of this software. 53 | 54 | Permission is granted to anyone to use this software for any purpose, 55 | including commercial applications, and to alter it and redistribute it 56 | freely, subject to the following restrictions: 57 | 58 | 1. The origin of this software must not be misrepresented; you must not 59 | claim that you wrote the original software. If you use this software 60 | in a product, an acknowledgment in the product documentation would be 61 | appreciated but is not required. 62 | 2. Altered source versions must be plainly marked as such, and must not be 63 | misrepresented as being the original software. 64 | 3. This notice may not be removed or altered from any source distribution. 65 | 66 | Jean-loup Gailly jloup@gzip.org 67 | Mark Adler madler@alumni.caltech.edu 68 | 69 | 70 | ----------------------------------------------------------------------- 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dotnetzip-for-unity # 2 | This is a stripped-down version of DotNetZip (no BZip2/GZip support for now) with some fixes so it can be used on Unity projects, including those that target Android and iOS. 3 | 4 | This project is licensed under the Ms-PL, packaged within this project as 5 | "License.txt". 6 | 7 | Thanks to Ed Ropple for the original GitHub mirror of DotNetZip. 8 | 9 | ## How to use ## 10 | Clone the repository and compile the project, or download the already compiled libraries from the __Binaries__ folder. Drop them in your Unity project's __Assets/Plugins__ folder and you are good to go. 11 | 12 | The library has been extensively tested in Android devices, however, some issues can arise when targetting iOS devices. Feel free to report any bugs you find. 13 | -------------------------------------------------------------------------------- /SolutionInfo.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r2d2rigo/dotnetzip-for-unity/b6e3951d18a9d28f7ef329c2065b284bd869451a/SolutionInfo.cs -------------------------------------------------------------------------------- /Zip Reduced/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r2d2rigo/dotnetzip-for-unity/b6e3951d18a9d28f7ef329c2065b284bd869451a/Zip Reduced/Properties/AssemblyInfo.cs -------------------------------------------------------------------------------- /Zip Reduced/Zip Reduced.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {49A128D3-C3F2-46B1-8F7A-EECD209EA860} 9 | Library 10 | Properties 11 | Ionic.Zip 12 | Ionic.Zip.Unity 13 | v2.0 14 | 512 15 | 16 | 17 | SAK 18 | SAK 19 | SAK 20 | SAK 21 | false 22 | ..\Ionic.snk 23 | 24 | 25 | 3.5 26 | 27 | publish\ 28 | true 29 | Disk 30 | false 31 | Foreground 32 | 7 33 | Days 34 | false 35 | false 36 | true 37 | 0 38 | 1.0.0.%2a 39 | false 40 | false 41 | true 42 | 43 | 44 | true 45 | full 46 | false 47 | bin\Debug\ 48 | TRACE;DEBUG;AESCRYPTO;BZIP;SILVERLIGHT;NO_LINQ;NO_SFX 49 | prompt 50 | 4 51 | bin\Debug\Ionic.Zip.Unity.XML 52 | AllRules.ruleset 53 | 54 | 55 | pdbonly 56 | true 57 | bin\Release\ 58 | TRACE;AESCRYPTO;BZIP;SILVERLIGHT;NO_LINQ;NO_SFX 59 | prompt 60 | 4 61 | AllRules.ruleset 62 | bin\Release\Ionic.Zip.Unity.XML 63 | 64 | 65 | 72 | 73 | 74 | Zip\%(FileName) 75 | 76 | 77 | BZip2\%(FileName) 78 | 79 | 80 | Zlib\%(FileName) 81 | 82 | 83 | CRC32.cs 84 | 85 | 86 | 87 | Properties\SolutionInfo.cs 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | False 96 | .NET Framework 3.5 SP1 Client Profile 97 | false 98 | 99 | 100 | False 101 | .NET Framework 3.5 SP1 102 | true 103 | 104 | 105 | False 106 | Windows Installer 3.1 107 | true 108 | 109 | 110 | -------------------------------------------------------------------------------- /Zip/ComHelper.cs: -------------------------------------------------------------------------------- 1 | // ComHelper.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2011-June-13 17:04:06> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines a COM Helper class. 23 | // 24 | // Created: Tue, 08 Sep 2009 22:03 25 | // 26 | 27 | using Interop=System.Runtime.InteropServices; 28 | 29 | namespace Ionic.Zip 30 | { 31 | /// 32 | /// This class exposes a set of COM-accessible wrappers for static 33 | /// methods available on the ZipFile class. You don't need this 34 | /// class unless you are using DotNetZip from a COM environment. 35 | /// 36 | [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000F")] 37 | [System.Runtime.InteropServices.ComVisible(true)] 38 | #if !NETCF 39 | [System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDispatch)] 40 | #endif 41 | 42 | public class ComHelper 43 | { 44 | /// 45 | /// A wrapper for ZipFile.IsZipFile(string) 46 | /// 47 | /// The filename to of the zip file to check. 48 | /// true if the file contains a valid zip file. 49 | public bool IsZipFile(string filename) 50 | { 51 | return ZipFile.IsZipFile(filename); 52 | } 53 | 54 | /// 55 | /// A wrapper for ZipFile.IsZipFile(string, bool) 56 | /// 57 | /// 58 | /// We cannot use "overloaded" Method names in COM interop. 59 | /// So, here, we use a unique name. 60 | /// 61 | /// The filename to of the zip file to check. 62 | /// true if the file contains a valid zip file. 63 | public bool IsZipFileWithExtract(string filename) 64 | { 65 | return ZipFile.IsZipFile(filename, true); 66 | } 67 | 68 | #if !NETCF 69 | /// 70 | /// A wrapper for ZipFile.CheckZip(string) 71 | /// 72 | /// The filename to of the zip file to check. 73 | /// 74 | /// true if the named zip file checks OK. Otherwise, false. 75 | public bool CheckZip(string filename) 76 | { 77 | return ZipFile.CheckZip(filename); 78 | } 79 | 80 | /// 81 | /// A COM-friendly wrapper for the static method . 82 | /// 83 | /// 84 | /// The filename to of the zip file to check. 85 | /// 86 | /// The password to check. 87 | /// 88 | /// true if the named zip file checks OK. Otherwise, false. 89 | public bool CheckZipPassword(string filename, string password) 90 | { 91 | return ZipFile.CheckZipPassword(filename, password); 92 | } 93 | 94 | /// 95 | /// A wrapper for ZipFile.FixZipDirectory(string) 96 | /// 97 | /// The filename to of the zip file to fix. 98 | public void FixZipDirectory(string filename) 99 | { 100 | ZipFile.FixZipDirectory(filename); 101 | } 102 | #endif 103 | 104 | /// 105 | /// A wrapper for ZipFile.LibraryVersion 106 | /// 107 | /// 108 | /// the version number on the DotNetZip assembly, formatted as a string. 109 | /// 110 | public string GetZipLibraryVersion() 111 | { 112 | return ZipFile.LibraryVersion.ToString(); 113 | } 114 | 115 | } 116 | } -------------------------------------------------------------------------------- /Zip/EncryptionAlgorithm.cs: -------------------------------------------------------------------------------- 1 | // EncryptionAlgorithm.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-October-21 17:24:45> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines the EncryptionAgorithm enum 23 | // 24 | // 25 | // ------------------------------------------------------------------ 26 | 27 | 28 | namespace Ionic.Zip 29 | { 30 | /// 31 | /// An enum that provides the various encryption algorithms supported by this 32 | /// library. 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// PkzipWeak implies the use of Zip 2.0 encryption, which is known to be 39 | /// weak and subvertible. 40 | /// 41 | /// 42 | /// 43 | /// A note on interoperability: Values of PkzipWeak and None are 44 | /// specified in PKWARE's zip 46 | /// specification, and are considered to be "standard". Zip archives 47 | /// produced using these options will be interoperable with many other zip tools 48 | /// and libraries, including Windows Explorer. 49 | /// 50 | /// 51 | /// 52 | /// Values of WinZipAes128 and WinZipAes256 are not part of the Zip 53 | /// specification, but rather imply the use of a vendor-specific extension from 54 | /// WinZip. If you want to produce interoperable Zip archives, do not use these 55 | /// values. For example, if you produce a zip archive using WinZipAes256, you 56 | /// will be able to open it in Windows Explorer on Windows XP and Vista, but you 57 | /// will not be able to extract entries; trying this will lead to an "unspecified 58 | /// error". For this reason, some people have said that a zip archive that uses 59 | /// WinZip's AES encryption is not actually a zip archive at all. A zip archive 60 | /// produced this way will be readable with the WinZip tool (Version 11 and 61 | /// beyond). 62 | /// 63 | /// 64 | /// 65 | /// There are other third-party tools and libraries, both commercial and 66 | /// otherwise, that support WinZip's AES encryption. These will be able to read 67 | /// AES-encrypted zip archives produced by DotNetZip, and conversely applications 68 | /// that use DotNetZip to read zip archives will be able to read AES-encrypted 69 | /// archives produced by those tools or libraries. Consult the documentation for 70 | /// those other tools and libraries to find out if WinZip's AES encryption is 71 | /// supported. 72 | /// 73 | /// 74 | /// 75 | /// In case you care: According to the WinZip specification, the 77 | /// actual AES key used is derived from the via an 78 | /// algorithm that complies with RFC 2898, using an iteration 80 | /// count of 1000. The algorithm is sometimes referred to as PBKDF2, which stands 81 | /// for "Password Based Key Derivation Function #2". 82 | /// 83 | /// 84 | /// 85 | /// A word about password strength and length: The AES encryption technology is 86 | /// very good, but any system is only as secure as the weakest link. If you want 87 | /// to secure your data, be sure to use a password that is hard to guess. To make 88 | /// it harder to guess (increase its "entropy"), you should make it longer. If 89 | /// you use normal characters from an ASCII keyboard, a password of length 20 will 90 | /// be strong enough that it will be impossible to guess. For more information on 91 | /// that, I'd encourage you to read this 93 | /// article. 94 | /// 95 | /// 96 | /// 97 | /// The WinZip AES algorithms are not supported with the version of DotNetZip that 98 | /// runs on the .NET Compact Framework. This is because .NET CF lacks the 99 | /// HMACSHA1 class that is required for producing the archive. 100 | /// 101 | /// 102 | public enum EncryptionAlgorithm 103 | { 104 | /// 105 | /// No encryption at all. 106 | /// 107 | None = 0, 108 | 109 | /// 110 | /// Traditional or Classic pkzip encryption. 111 | /// 112 | PkzipWeak, 113 | 114 | #if AESCRYPTO 115 | /// 116 | /// WinZip AES encryption (128 key bits). 117 | /// 118 | WinZipAes128, 119 | 120 | /// 121 | /// WinZip AES encryption (256 key bits). 122 | /// 123 | WinZipAes256, 124 | #endif 125 | 126 | /// 127 | /// An encryption algorithm that is not supported by DotNetZip. 128 | /// 129 | Unsupported = 4, 130 | 131 | 132 | // others... not implemented (yet?) 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /Zip/Exceptions.cs: -------------------------------------------------------------------------------- 1 | // Exceptions.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2008, 2009 Dino Chiesa and Microsoft Corporation. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2011-July-12 12:19:10> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines exceptions used in the class library. 23 | // 24 | 25 | 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.Text; 30 | #if !NETCF 31 | using System.Runtime.Serialization; 32 | #endif 33 | 34 | namespace Ionic.Zip 35 | { 36 | ///// 37 | ///// Base exception type for all custom exceptions in the Zip library. It acts as a marker class. 38 | ///// 39 | //[AttributeUsage(AttributeTargets.Class)] 40 | //public class ZipExceptionAttribute : Attribute { } 41 | 42 | 43 | 44 | /// 45 | /// Issued when an ZipEntry.ExtractWithPassword() method is invoked 46 | /// with an incorrect password. 47 | /// 48 | #if !SILVERLIGHT 49 | [Serializable] 50 | #endif 51 | [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000B")] 52 | public class BadPasswordException : ZipException 53 | { 54 | /// 55 | /// Default ctor. 56 | /// 57 | public BadPasswordException() { } 58 | 59 | /// 60 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 61 | /// 62 | /// The message in the exception. 63 | public BadPasswordException(String message) 64 | : base(message) 65 | { } 66 | 67 | /// 68 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 69 | /// 70 | /// The message in the exception. 71 | /// The innerException for this exception. 72 | public BadPasswordException(String message, Exception innerException) 73 | : base(message, innerException) 74 | { 75 | } 76 | 77 | 78 | #if ! (NETCF || SILVERLIGHT) 79 | /// 80 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 81 | /// 82 | /// The serialization info for the exception. 83 | /// The streaming context from which to deserialize. 84 | protected BadPasswordException(SerializationInfo info, StreamingContext context) 85 | : base(info, context) 86 | { } 87 | #endif 88 | 89 | } 90 | 91 | /// 92 | /// Indicates that a read was attempted on a stream, and bad or incomplete data was 93 | /// received. 94 | /// 95 | #if !SILVERLIGHT 96 | [Serializable] 97 | #endif 98 | [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000A")] 99 | public class BadReadException : ZipException 100 | { 101 | /// 102 | /// Default ctor. 103 | /// 104 | public BadReadException() { } 105 | 106 | /// 107 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 108 | /// 109 | /// The message in the exception. 110 | public BadReadException(String message) 111 | : base(message) 112 | { } 113 | 114 | /// 115 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 116 | /// 117 | /// The message in the exception. 118 | /// The innerException for this exception. 119 | public BadReadException(String message, Exception innerException) 120 | : base(message, innerException) 121 | { 122 | } 123 | 124 | #if ! (NETCF || SILVERLIGHT) 125 | /// 126 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 127 | /// 128 | /// The serialization info for the exception. 129 | /// The streaming context from which to deserialize. 130 | protected BadReadException(SerializationInfo info, StreamingContext context) 131 | : base(info, context) 132 | { } 133 | #endif 134 | 135 | } 136 | 137 | 138 | 139 | /// 140 | /// Issued when an CRC check fails upon extracting an entry from a zip archive. 141 | /// 142 | #if !SILVERLIGHT 143 | [Serializable] 144 | #endif 145 | [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00009")] 146 | public class BadCrcException : ZipException 147 | { 148 | /// 149 | /// Default ctor. 150 | /// 151 | public BadCrcException() { } 152 | 153 | /// 154 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 155 | /// 156 | /// The message in the exception. 157 | public BadCrcException(String message) 158 | : base(message) 159 | { } 160 | 161 | 162 | #if ! (NETCF || SILVERLIGHT) 163 | /// 164 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 165 | /// 166 | /// The serialization info for the exception. 167 | /// The streaming context from which to deserialize. 168 | protected BadCrcException(SerializationInfo info, StreamingContext context) 169 | : base(info, context) 170 | { } 171 | #endif 172 | 173 | } 174 | 175 | 176 | /// 177 | /// Issued when errors occur saving a self-extracting archive. 178 | /// 179 | #if !SILVERLIGHT 180 | [Serializable] 181 | #endif 182 | [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00008")] 183 | public class SfxGenerationException : ZipException 184 | { 185 | /// 186 | /// Default ctor. 187 | /// 188 | public SfxGenerationException() { } 189 | 190 | /// 191 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 192 | /// 193 | /// The message in the exception. 194 | public SfxGenerationException(String message) 195 | : base(message) 196 | { } 197 | 198 | #if ! (NETCF || SILVERLIGHT) 199 | /// 200 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 201 | /// 202 | /// The serialization info for the exception. 203 | /// The streaming context from which to deserialize. 204 | protected SfxGenerationException(SerializationInfo info, StreamingContext context) 205 | : base(info, context) 206 | { } 207 | #endif 208 | 209 | } 210 | 211 | 212 | /// 213 | /// Indicates that an operation was attempted on a ZipFile which was not possible 214 | /// given the state of the instance. For example, if you call Save() on a ZipFile 215 | /// which has no filename set, you can get this exception. 216 | /// 217 | #if !SILVERLIGHT 218 | [Serializable] 219 | #endif 220 | [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00007")] 221 | public class BadStateException : ZipException 222 | { 223 | /// 224 | /// Default ctor. 225 | /// 226 | public BadStateException() { } 227 | 228 | /// 229 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 230 | /// 231 | /// The message in the exception. 232 | public BadStateException(String message) 233 | : base(message) 234 | { } 235 | 236 | /// 237 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 238 | /// 239 | /// The message in the exception. 240 | /// The innerException for this exception. 241 | public BadStateException(String message, Exception innerException) 242 | : base(message, innerException) 243 | {} 244 | 245 | #if ! (NETCF || SILVERLIGHT) 246 | /// 247 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 248 | /// 249 | /// The serialization info for the exception. 250 | /// The streaming context from which to deserialize. 251 | protected BadStateException(SerializationInfo info, StreamingContext context) 252 | : base(info, context) 253 | { } 254 | #endif 255 | 256 | } 257 | 258 | /// 259 | /// Base class for all exceptions defined by and throw by the Zip library. 260 | /// 261 | #if !SILVERLIGHT 262 | [Serializable] 263 | #endif 264 | [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00006")] 265 | public class ZipException : Exception 266 | { 267 | /// 268 | /// Default ctor. 269 | /// 270 | public ZipException() { } 271 | 272 | /// 273 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 274 | /// 275 | /// The message in the exception. 276 | public ZipException(String message) : base(message) { } 277 | 278 | /// 279 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 280 | /// 281 | /// The message in the exception. 282 | /// The innerException for this exception. 283 | public ZipException(String message, Exception innerException) 284 | : base(message, innerException) 285 | { } 286 | 287 | #if ! (NETCF || SILVERLIGHT) 288 | /// 289 | /// Come on, you know how exceptions work. Why are you looking at this documentation? 290 | /// 291 | /// The serialization info for the exception. 292 | /// The streaming context from which to deserialize. 293 | protected ZipException(SerializationInfo info, StreamingContext context) 294 | : base(info, context) 295 | { } 296 | #endif 297 | 298 | } 299 | 300 | } 301 | -------------------------------------------------------------------------------- /Zip/ExtractExistingFileAction.cs: -------------------------------------------------------------------------------- 1 | // ExtractExistingFileAction.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-August-25 08:44:37> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines the ExtractExistingFileAction enum 23 | // 24 | // 25 | // ------------------------------------------------------------------ 26 | 27 | 28 | namespace Ionic.Zip 29 | { 30 | 31 | /// 32 | /// An enum for the options when extracting an entry would overwrite an existing file. 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// This enum describes the actions that the library can take when an 38 | /// Extract() or ExtractWithPassword() method is called to extract an 39 | /// entry to a filesystem, and the extraction would overwrite an existing filesystem 40 | /// file. 41 | /// 42 | /// 43 | /// 44 | public enum ExtractExistingFileAction 45 | { 46 | /// 47 | /// Throw an exception when extraction would overwrite an existing file. (For 48 | /// COM clients, this is a 0 (zero).) 49 | /// 50 | Throw, 51 | 52 | /// 53 | /// When extraction would overwrite an existing file, overwrite the file silently. 54 | /// The overwrite will happen even if the target file is marked as read-only. 55 | /// (For COM clients, this is a 1.) 56 | /// 57 | OverwriteSilently, 58 | 59 | /// 60 | /// When extraction would overwrite an existing file, don't overwrite the file, silently. 61 | /// (For COM clients, this is a 2.) 62 | /// 63 | DoNotOverwrite, 64 | 65 | /// 66 | /// When extraction would overwrite an existing file, invoke the ExtractProgress 67 | /// event, using an event type of . In 69 | /// this way, the application can decide, just-in-time, whether to overwrite the 70 | /// file. For example, a GUI application may wish to pop up a dialog to allow 71 | /// the user to choose. You may want to examine the property before making 73 | /// the decision. If, after your processing in the Extract progress event, you 74 | /// want to NOT extract the file, set 75 | /// on the ZipProgressEventArgs.CurrentEntry to DoNotOverwrite. 76 | /// If you do want to extract the file, set ZipEntry.ExtractExistingFile 77 | /// to OverwriteSilently. If you want to cancel the Extraction, set 78 | /// ZipProgressEventArgs.Cancel to true. Cancelling differs from using 79 | /// DoNotOverwrite in that a cancel will not extract any further entries, if 80 | /// there are any. (For COM clients, the value of this enum is a 3.) 81 | /// 82 | InvokeExtractProgressEvent, 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /Zip/OffsetStream.cs: -------------------------------------------------------------------------------- 1 | // OffsetStream.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-August-27 12:50:35> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines logic for handling reading of zip archives embedded 23 | // into larger streams. The initial position of the stream serves as 24 | // the base offset for all future Seek() operations. 25 | // 26 | // ------------------------------------------------------------------ 27 | 28 | 29 | using System; 30 | using System.IO; 31 | 32 | namespace Ionic.Zip 33 | { 34 | internal class OffsetStream : System.IO.Stream, System.IDisposable 35 | { 36 | private Int64 _originalPosition; 37 | private Stream _innerStream; 38 | 39 | public OffsetStream(Stream s) 40 | : base() 41 | { 42 | _originalPosition = s.Position; 43 | _innerStream = s; 44 | } 45 | 46 | public override int Read(byte[] buffer, int offset, int count) 47 | { 48 | return _innerStream.Read(buffer, offset, count); 49 | } 50 | 51 | public override void Write(byte[] buffer, int offset, int count) 52 | { 53 | throw new NotImplementedException(); 54 | } 55 | 56 | public override bool CanRead 57 | { 58 | get { return _innerStream.CanRead; } 59 | } 60 | 61 | public override bool CanSeek 62 | { 63 | get { return _innerStream.CanSeek; } 64 | } 65 | 66 | public override bool CanWrite 67 | { 68 | get { return false; } 69 | } 70 | 71 | public override void Flush() 72 | { 73 | _innerStream.Flush(); 74 | } 75 | 76 | public override long Length 77 | { 78 | get 79 | { 80 | return _innerStream.Length; 81 | } 82 | } 83 | 84 | public override long Position 85 | { 86 | get { return _innerStream.Position - _originalPosition; } 87 | set { _innerStream.Position = _originalPosition + value; } 88 | } 89 | 90 | 91 | public override long Seek(long offset, System.IO.SeekOrigin origin) 92 | { 93 | return _innerStream.Seek(_originalPosition + offset, origin) - _originalPosition; 94 | } 95 | 96 | 97 | public override void SetLength(long value) 98 | { 99 | throw new NotImplementedException(); 100 | } 101 | 102 | void IDisposable.Dispose() 103 | { 104 | Close(); 105 | } 106 | 107 | public override void Close() 108 | { 109 | base.Close(); 110 | } 111 | 112 | } 113 | 114 | } -------------------------------------------------------------------------------- /Zip/ZipConstants.cs: -------------------------------------------------------------------------------- 1 | // ZipConstants.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2006, 2007, 2008, 2009 Dino Chiesa and Microsoft Corporation. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-August-27 23:22:32> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines a few constants that are used in the project. 23 | // 24 | // ------------------------------------------------------------------ 25 | 26 | using System; 27 | 28 | namespace Ionic.Zip 29 | { 30 | static class ZipConstants 31 | { 32 | public const UInt32 PackedToRemovableMedia = 0x30304b50; 33 | public const UInt32 Zip64EndOfCentralDirectoryRecordSignature = 0x06064b50; 34 | public const UInt32 Zip64EndOfCentralDirectoryLocatorSignature = 0x07064b50; 35 | public const UInt32 EndOfCentralDirectorySignature = 0x06054b50; 36 | public const int ZipEntrySignature = 0x04034b50; 37 | public const int ZipEntryDataDescriptorSignature = 0x08074b50; 38 | public const int SplitArchiveSignature = 0x08074b50; 39 | public const int ZipDirEntrySignature = 0x02014b50; 40 | 41 | 42 | // These are dictated by the Zip Spec.See APPNOTE.txt 43 | public const int AesKeySize = 192; // 128, 192, 256 44 | public const int AesBlockSize = 128; // ??? 45 | 46 | public const UInt16 AesAlgId128 = 0x660E; 47 | public const UInt16 AesAlgId192 = 0x660F; 48 | public const UInt16 AesAlgId256 = 0x6610; 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Zip/ZipCrypto.cs: -------------------------------------------------------------------------------- 1 | // ZipCrypto.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2008, 2009, 2011 Dino Chiesa 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2011-July-28 06:30:59> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module provides the implementation for "traditional" Zip encryption. 23 | // 24 | // Created Tue Apr 15 17:39:56 2008 25 | // 26 | // ------------------------------------------------------------------ 27 | 28 | using System; 29 | 30 | namespace Ionic.Zip 31 | { 32 | /// 33 | /// This class implements the "traditional" or "classic" PKZip encryption, 34 | /// which today is considered to be weak. On the other hand it is 35 | /// ubiquitous. This class is intended for use only by the DotNetZip 36 | /// library. 37 | /// 38 | /// 39 | /// 40 | /// Most uses of the DotNetZip library will not involve direct calls into 41 | /// the ZipCrypto class. Instead, the ZipCrypto class is instantiated and 42 | /// used by the ZipEntry() class when encryption or decryption on an entry 43 | /// is employed. If for some reason you really wanted to use a weak 44 | /// encryption algorithm in some other application, you might use this 45 | /// library. But you would be much better off using one of the built-in 46 | /// strong encryption libraries in the .NET Framework, like the AES 47 | /// algorithm or SHA. 48 | /// 49 | internal class ZipCrypto 50 | { 51 | /// 52 | /// The default constructor for ZipCrypto. 53 | /// 54 | /// 55 | /// 56 | /// This class is intended for internal use by the library only. It's 57 | /// probably not useful to you. Seriously. Stop reading this 58 | /// documentation. It's a waste of your time. Go do something else. 59 | /// Check the football scores. Go get an ice cream with a friend. 60 | /// Seriously. 61 | /// 62 | /// 63 | private ZipCrypto() { } 64 | 65 | public static ZipCrypto ForWrite(string password) 66 | { 67 | ZipCrypto z = new ZipCrypto(); 68 | if (password == null) 69 | throw new BadPasswordException("This entry requires a password."); 70 | z.InitCipher(password); 71 | return z; 72 | } 73 | 74 | 75 | public static ZipCrypto ForRead(string password, ZipEntry e) 76 | { 77 | System.IO.Stream s = e._archiveStream; 78 | e._WeakEncryptionHeader = new byte[12]; 79 | byte[] eh = e._WeakEncryptionHeader; 80 | ZipCrypto z = new ZipCrypto(); 81 | 82 | if (password == null) 83 | throw new BadPasswordException("This entry requires a password."); 84 | 85 | z.InitCipher(password); 86 | 87 | ZipEntry.ReadWeakEncryptionHeader(s, eh); 88 | 89 | // Decrypt the header. This has a side effect of "further initializing the 90 | // encryption keys" in the traditional zip encryption. 91 | byte[] DecryptedHeader = z.DecryptMessage(eh, eh.Length); 92 | 93 | // CRC check 94 | // According to the pkzip spec, the final byte in the decrypted header 95 | // is the highest-order byte in the CRC. We check it here. 96 | if (DecryptedHeader[11] != (byte)((e._Crc32 >> 24) & 0xff)) 97 | { 98 | // In the case that bit 3 of the general purpose bit flag is set to 99 | // indicate the presence of an 'Extended File Header' or a 'data 100 | // descriptor' (signature 0x08074b50), the last byte of the decrypted 101 | // header is sometimes compared with the high-order byte of the 102 | // lastmodified time, rather than the high-order byte of the CRC, to 103 | // verify the password. 104 | // 105 | // This is not documented in the PKWare Appnote.txt. It was 106 | // discovered this by analysis of the Crypt.c source file in the 107 | // InfoZip library http://www.info-zip.org/pub/infozip/ 108 | // 109 | // The reason for this is that the CRC for a file cannot be known 110 | // until the entire contents of the file have been streamed. This 111 | // means a tool would have to read the file content TWICE in its 112 | // entirety in order to perform PKZIP encryption - once to compute 113 | // the CRC, and again to actually encrypt. 114 | // 115 | // This is so important for performance that using the timeblob as 116 | // the verification should be the standard practice for DotNetZip 117 | // when using PKZIP encryption. This implies that bit 3 must be 118 | // set. The downside is that some tools still cannot cope with ZIP 119 | // files that use bit 3. Therefore, DotNetZip DOES NOT force bit 3 120 | // when PKZIP encryption is in use, and instead, reads the stream 121 | // twice. 122 | // 123 | 124 | if ((e._BitField & 0x0008) != 0x0008) 125 | { 126 | throw new BadPasswordException("The password did not match."); 127 | } 128 | else if (DecryptedHeader[11] != (byte)((e._TimeBlob >> 8) & 0xff)) 129 | { 130 | throw new BadPasswordException("The password did not match."); 131 | } 132 | 133 | // We have a good password. 134 | } 135 | else 136 | { 137 | // A-OK 138 | } 139 | return z; 140 | } 141 | 142 | 143 | 144 | 145 | /// 146 | /// From AppNote.txt: 147 | /// unsigned char decrypt_byte() 148 | /// local unsigned short temp 149 | /// temp :=- Key(2) | 2 150 | /// decrypt_byte := (temp * (temp ^ 1)) bitshift-right 8 151 | /// end decrypt_byte 152 | /// 153 | private byte MagicByte 154 | { 155 | get 156 | { 157 | UInt16 t = (UInt16)((UInt16)(_Keys[2] & 0xFFFF) | 2); 158 | return (byte)((t * (t ^ 1)) >> 8); 159 | } 160 | } 161 | 162 | // Decrypting: 163 | // From AppNote.txt: 164 | // loop for i from 0 to 11 165 | // C := buffer(i) ^ decrypt_byte() 166 | // update_keys(C) 167 | // buffer(i) := C 168 | // end loop 169 | 170 | 171 | /// 172 | /// Call this method on a cipher text to render the plaintext. You must 173 | /// first initialize the cipher with a call to InitCipher. 174 | /// 175 | /// 176 | /// 177 | /// 178 | /// var cipher = new ZipCrypto(); 179 | /// cipher.InitCipher(Password); 180 | /// // Decrypt the header. This has a side effect of "further initializing the 181 | /// // encryption keys" in the traditional zip encryption. 182 | /// byte[] DecryptedMessage = cipher.DecryptMessage(EncryptedMessage); 183 | /// 184 | /// 185 | /// 186 | /// The encrypted buffer. 187 | /// 188 | /// The number of bytes to encrypt. 189 | /// Should be less than or equal to CipherText.Length. 190 | /// 191 | /// 192 | /// The plaintext. 193 | public byte[] DecryptMessage(byte[] cipherText, int length) 194 | { 195 | if (cipherText == null) 196 | throw new ArgumentNullException("cipherText"); 197 | 198 | if (length > cipherText.Length) 199 | throw new ArgumentOutOfRangeException("length", 200 | "Bad length during Decryption: the length parameter must be smaller than or equal to the size of the destination array."); 201 | 202 | byte[] plainText = new byte[length]; 203 | for (int i = 0; i < length; i++) 204 | { 205 | byte C = (byte)(cipherText[i] ^ MagicByte); 206 | UpdateKeys(C); 207 | plainText[i] = C; 208 | } 209 | return plainText; 210 | } 211 | 212 | /// 213 | /// This is the converse of DecryptMessage. It encrypts the plaintext 214 | /// and produces a ciphertext. 215 | /// 216 | /// 217 | /// The plain text buffer. 218 | /// 219 | /// 220 | /// The number of bytes to encrypt. 221 | /// Should be less than or equal to plainText.Length. 222 | /// 223 | /// 224 | /// The ciphertext. 225 | public byte[] EncryptMessage(byte[] plainText, int length) 226 | { 227 | if (plainText == null) 228 | throw new ArgumentNullException("plaintext"); 229 | 230 | if (length > plainText.Length) 231 | throw new ArgumentOutOfRangeException("length", 232 | "Bad length during Encryption: The length parameter must be smaller than or equal to the size of the destination array."); 233 | 234 | byte[] cipherText = new byte[length]; 235 | for (int i = 0; i < length; i++) 236 | { 237 | byte C = plainText[i]; 238 | cipherText[i] = (byte)(plainText[i] ^ MagicByte); 239 | UpdateKeys(C); 240 | } 241 | return cipherText; 242 | } 243 | 244 | 245 | /// 246 | /// This initializes the cipher with the given password. 247 | /// See AppNote.txt for details. 248 | /// 249 | /// 250 | /// 251 | /// The passphrase for encrypting or decrypting with this cipher. 252 | /// 253 | /// 254 | /// 255 | /// 256 | /// Step 1 - Initializing the encryption keys 257 | /// ----------------------------------------- 258 | /// Start with these keys: 259 | /// Key(0) := 305419896 (0x12345678) 260 | /// Key(1) := 591751049 (0x23456789) 261 | /// Key(2) := 878082192 (0x34567890) 262 | /// 263 | /// Then, initialize the keys with a password: 264 | /// 265 | /// loop for i from 0 to length(password)-1 266 | /// update_keys(password(i)) 267 | /// end loop 268 | /// 269 | /// Where update_keys() is defined as: 270 | /// 271 | /// update_keys(char): 272 | /// Key(0) := crc32(key(0),char) 273 | /// Key(1) := Key(1) + (Key(0) bitwiseAND 000000ffH) 274 | /// Key(1) := Key(1) * 134775813 + 1 275 | /// Key(2) := crc32(key(2),key(1) rightshift 24) 276 | /// end update_keys 277 | /// 278 | /// Where crc32(old_crc,char) is a routine that given a CRC value and a 279 | /// character, returns an updated CRC value after applying the CRC-32 280 | /// algorithm described elsewhere in this document. 281 | /// 282 | /// 283 | /// 284 | /// 285 | /// After the keys are initialized, then you can use the cipher to 286 | /// encrypt the plaintext. 287 | /// 288 | /// 289 | /// 290 | /// Essentially we encrypt the password with the keys, then discard the 291 | /// ciphertext for the password. This initializes the keys for later use. 292 | /// 293 | /// 294 | /// 295 | public void InitCipher(string passphrase) 296 | { 297 | byte[] p = SharedUtilities.StringToByteArray(passphrase); 298 | for (int i = 0; i < passphrase.Length; i++) 299 | UpdateKeys(p[i]); 300 | } 301 | 302 | 303 | private void UpdateKeys(byte byteValue) 304 | { 305 | _Keys[0] = (UInt32)crc32.ComputeCrc32((int)_Keys[0], byteValue); 306 | _Keys[1] = _Keys[1] + (byte)_Keys[0]; 307 | _Keys[1] = _Keys[1] * 0x08088405 + 1; 308 | _Keys[2] = (UInt32)crc32.ComputeCrc32((int)_Keys[2], (byte)(_Keys[1] >> 24)); 309 | } 310 | 311 | ///// 312 | ///// The byte array representing the seed keys used. 313 | ///// Get this after calling InitCipher. The 12 bytes represents 314 | ///// what the zip spec calls the "EncryptionHeader". 315 | ///// 316 | //public byte[] KeyHeader 317 | //{ 318 | // get 319 | // { 320 | // byte[] result = new byte[12]; 321 | // result[0] = (byte)(_Keys[0] & 0xff); 322 | // result[1] = (byte)((_Keys[0] >> 8) & 0xff); 323 | // result[2] = (byte)((_Keys[0] >> 16) & 0xff); 324 | // result[3] = (byte)((_Keys[0] >> 24) & 0xff); 325 | // result[4] = (byte)(_Keys[1] & 0xff); 326 | // result[5] = (byte)((_Keys[1] >> 8) & 0xff); 327 | // result[6] = (byte)((_Keys[1] >> 16) & 0xff); 328 | // result[7] = (byte)((_Keys[1] >> 24) & 0xff); 329 | // result[8] = (byte)(_Keys[2] & 0xff); 330 | // result[9] = (byte)((_Keys[2] >> 8) & 0xff); 331 | // result[10] = (byte)((_Keys[2] >> 16) & 0xff); 332 | // result[11] = (byte)((_Keys[2] >> 24) & 0xff); 333 | // return result; 334 | // } 335 | //} 336 | 337 | // private fields for the crypto stuff: 338 | private UInt32[] _Keys = { 0x12345678, 0x23456789, 0x34567890 }; 339 | private Ionic.Crc.CRC32 crc32 = new Ionic.Crc.CRC32(); 340 | 341 | } 342 | 343 | internal enum CryptoMode 344 | { 345 | Encrypt, 346 | Decrypt 347 | } 348 | 349 | /// 350 | /// A Stream for reading and concurrently decrypting data from a zip file, 351 | /// or for writing and concurrently encrypting data to a zip file. 352 | /// 353 | internal class ZipCipherStream : System.IO.Stream 354 | { 355 | private ZipCrypto _cipher; 356 | private System.IO.Stream _s; 357 | private CryptoMode _mode; 358 | 359 | /// The constructor. 360 | /// The underlying stream 361 | /// To either encrypt or decrypt. 362 | /// The pre-initialized ZipCrypto object. 363 | public ZipCipherStream(System.IO.Stream s, ZipCrypto cipher, CryptoMode mode) 364 | : base() 365 | { 366 | _cipher = cipher; 367 | _s = s; 368 | _mode = mode; 369 | } 370 | 371 | public override int Read(byte[] buffer, int offset, int count) 372 | { 373 | if (_mode == CryptoMode.Encrypt) 374 | throw new NotSupportedException("This stream does not encrypt via Read()"); 375 | 376 | if (buffer == null) 377 | throw new ArgumentNullException("buffer"); 378 | 379 | byte[] db = new byte[count]; 380 | int n = _s.Read(db, 0, count); 381 | byte[] decrypted = _cipher.DecryptMessage(db, n); 382 | for (int i = 0; i < n; i++) 383 | { 384 | buffer[offset + i] = decrypted[i]; 385 | } 386 | return n; 387 | } 388 | 389 | public override void Write(byte[] buffer, int offset, int count) 390 | { 391 | if (_mode == CryptoMode.Decrypt) 392 | throw new NotSupportedException("This stream does not Decrypt via Write()"); 393 | 394 | if (buffer == null) 395 | throw new ArgumentNullException("buffer"); 396 | 397 | // workitem 7696 398 | if (count == 0) return; 399 | 400 | byte[] plaintext = null; 401 | if (offset != 0) 402 | { 403 | plaintext = new byte[count]; 404 | for (int i = 0; i < count; i++) 405 | { 406 | plaintext[i] = buffer[offset + i]; 407 | } 408 | } 409 | else plaintext = buffer; 410 | 411 | byte[] encrypted = _cipher.EncryptMessage(plaintext, count); 412 | _s.Write(encrypted, 0, encrypted.Length); 413 | } 414 | 415 | 416 | public override bool CanRead 417 | { 418 | get { return (_mode == CryptoMode.Decrypt); } 419 | } 420 | public override bool CanSeek 421 | { 422 | get { return false; } 423 | } 424 | 425 | public override bool CanWrite 426 | { 427 | get { return (_mode == CryptoMode.Encrypt); } 428 | } 429 | 430 | public override void Flush() 431 | { 432 | //throw new NotSupportedException(); 433 | } 434 | 435 | public override long Length 436 | { 437 | get { throw new NotSupportedException(); } 438 | } 439 | 440 | public override long Position 441 | { 442 | get { throw new NotSupportedException(); } 443 | set { throw new NotSupportedException(); } 444 | } 445 | public override long Seek(long offset, System.IO.SeekOrigin origin) 446 | { 447 | throw new NotSupportedException(); 448 | } 449 | 450 | public override void SetLength(long value) 451 | { 452 | throw new NotSupportedException(); 453 | } 454 | } 455 | } 456 | -------------------------------------------------------------------------------- /Zip/ZipDirEntry.cs: -------------------------------------------------------------------------------- 1 | // ZipDirEntry.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2006-2011 Dino Chiesa . 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2011-July-11 12:03:03> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines members of the ZipEntry class for reading the 23 | // Zip file central directory. 24 | // 25 | // Created: Tue, 27 Mar 2007 15:30 26 | // 27 | // ------------------------------------------------------------------ 28 | 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | 33 | namespace Ionic.Zip 34 | { 35 | 36 | partial class ZipEntry 37 | { 38 | /// 39 | /// True if the referenced entry is a directory. 40 | /// 41 | internal bool AttributesIndicateDirectory 42 | { 43 | get { return ((_InternalFileAttrs == 0) && ((_ExternalFileAttrs & 0x0010) == 0x0010)); } 44 | } 45 | 46 | 47 | internal void ResetDirEntry() 48 | { 49 | // __FileDataPosition is the position of the file data for an entry. 50 | // It is _RelativeOffsetOfLocalHeader + size of local header. 51 | 52 | // We cannot know the __FileDataPosition until we read the local 53 | // header. 54 | 55 | // The local header is not necessarily the same length as the record 56 | // in the central directory. 57 | 58 | // Set to -1, to indicate we need to read this later. 59 | this.__FileDataPosition = -1; 60 | 61 | // set _LengthOfHeader to 0, to indicate we need to read later. 62 | this._LengthOfHeader = 0; 63 | } 64 | 65 | /// 66 | /// Provides a human-readable string with information about the ZipEntry. 67 | /// 68 | public string Info 69 | { 70 | get 71 | { 72 | var builder = new System.Text.StringBuilder(); 73 | builder 74 | .Append(string.Format(" ZipEntry: {0}\n", this.FileName)) 75 | .Append(string.Format(" Version Made By: {0}\n", this._VersionMadeBy)) 76 | .Append(string.Format(" Needed to extract: {0}\n", this.VersionNeeded)); 77 | 78 | if (this._IsDirectory) 79 | builder.Append(" Entry type: directory\n"); 80 | else 81 | { 82 | builder.Append(string.Format(" File type: {0}\n", this._IsText? "text":"binary")) 83 | .Append(string.Format(" Compression: {0}\n", this.CompressionMethod)) 84 | .Append(string.Format(" Compressed: 0x{0:X}\n", this.CompressedSize)) 85 | .Append(string.Format(" Uncompressed: 0x{0:X}\n", this.UncompressedSize)) 86 | .Append(string.Format(" CRC32: 0x{0:X8}\n", this._Crc32)); 87 | } 88 | builder.Append(string.Format(" Disk Number: {0}\n", this._diskNumber)); 89 | if (this._RelativeOffsetOfLocalHeader > 0xFFFFFFFF) 90 | builder 91 | .Append(string.Format(" Relative Offset: 0x{0:X16}\n", this._RelativeOffsetOfLocalHeader)); 92 | else 93 | builder 94 | .Append(string.Format(" Relative Offset: 0x{0:X8}\n", this._RelativeOffsetOfLocalHeader)); 95 | 96 | builder 97 | .Append(string.Format(" Bit Field: 0x{0:X4}\n", this._BitField)) 98 | .Append(string.Format(" Encrypted?: {0}\n", this._sourceIsEncrypted)) 99 | .Append(string.Format(" Timeblob: 0x{0:X8}\n", this._TimeBlob)) 100 | .Append(string.Format(" Time: {0}\n", Ionic.Zip.SharedUtilities.PackedToDateTime(this._TimeBlob))); 101 | 102 | builder.Append(string.Format(" Is Zip64?: {0}\n", this._InputUsesZip64)); 103 | if (!string.IsNullOrEmpty(this._Comment)) 104 | { 105 | builder.Append(string.Format(" Comment: {0}\n", this._Comment)); 106 | } 107 | builder.Append("\n"); 108 | return builder.ToString(); 109 | } 110 | } 111 | 112 | 113 | // workitem 10330 114 | private class CopyHelper 115 | { 116 | private static System.Text.RegularExpressions.Regex re = 117 | new System.Text.RegularExpressions.Regex(" \\(copy (\\d+)\\)$"); 118 | 119 | private static int callCount = 0; 120 | 121 | internal static string AppendCopyToFileName(string f) 122 | { 123 | callCount++; 124 | if (callCount > 25) 125 | throw new OverflowException("overflow while creating filename"); 126 | 127 | int n = 1; 128 | int r = f.LastIndexOf("."); 129 | 130 | if (r == -1) 131 | { 132 | // there is no extension 133 | System.Text.RegularExpressions.Match m = re.Match(f); 134 | if (m.Success) 135 | { 136 | n = Int32.Parse(m.Groups[1].Value) + 1; 137 | string copy = String.Format(" (copy {0})", n); 138 | f = f.Substring(0, m.Index) + copy; 139 | } 140 | else 141 | { 142 | string copy = String.Format(" (copy {0})", n); 143 | f = f + copy; 144 | } 145 | } 146 | else 147 | { 148 | //System.Console.WriteLine("HasExtension"); 149 | System.Text.RegularExpressions.Match m = re.Match(f.Substring(0, r)); 150 | if (m.Success) 151 | { 152 | n = Int32.Parse(m.Groups[1].Value) + 1; 153 | string copy = String.Format(" (copy {0})", n); 154 | f = f.Substring(0, m.Index) + copy + f.Substring(r); 155 | } 156 | else 157 | { 158 | string copy = String.Format(" (copy {0})", n); 159 | f = f.Substring(0, r) + copy + f.Substring(r); 160 | } 161 | 162 | //System.Console.WriteLine("returning f({0})", f); 163 | } 164 | return f; 165 | } 166 | } 167 | 168 | 169 | 170 | /// 171 | /// Reads one entry from the zip directory structure in the zip file. 172 | /// 173 | /// 174 | /// 175 | /// The zipfile for which a directory entry will be read. From this param, the 176 | /// method gets the ReadStream and the expected text encoding 177 | /// (ProvisionalAlternateEncoding) which is used if the entry is not marked 178 | /// UTF-8. 179 | /// 180 | /// 181 | /// 182 | /// a list of previously seen entry names; used to prevent duplicates. 183 | /// 184 | /// 185 | /// the entry read from the archive. 186 | internal static ZipEntry ReadDirEntry(ZipFile zf, 187 | Dictionary previouslySeen) 188 | { 189 | System.IO.Stream s = zf.ReadStream; 190 | System.Text.Encoding expectedEncoding = (zf.AlternateEncodingUsage == ZipOption.Always) 191 | ? zf.AlternateEncoding 192 | : ZipFile.DefaultEncoding; 193 | 194 | int signature = Ionic.Zip.SharedUtilities.ReadSignature(s); 195 | // return null if this is not a local file header signature 196 | if (IsNotValidZipDirEntrySig(signature)) 197 | { 198 | s.Seek(-4, System.IO.SeekOrigin.Current); 199 | // workitem 10178 200 | Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); 201 | 202 | // Getting "not a ZipDirEntry signature" here is not always wrong or an 203 | // error. This can happen when walking through a zipfile. After the 204 | // last ZipDirEntry, we expect to read an 205 | // EndOfCentralDirectorySignature. When we get this is how we know 206 | // we've reached the end of the central directory. 207 | if (signature != ZipConstants.EndOfCentralDirectorySignature && 208 | signature != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature && 209 | signature != ZipConstants.ZipEntrySignature // workitem 8299 210 | ) 211 | { 212 | throw new BadReadException(String.Format(" Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, s.Position)); 213 | } 214 | return null; 215 | } 216 | 217 | int bytesRead = 42 + 4; 218 | byte[] block = new byte[42]; 219 | int n = s.Read(block, 0, block.Length); 220 | if (n != block.Length) return null; 221 | 222 | int i = 0; 223 | ZipEntry zde = new ZipEntry(); 224 | zde.AlternateEncoding = expectedEncoding; 225 | zde._Source = ZipEntrySource.ZipFile; 226 | zde._container = new ZipContainer(zf); 227 | 228 | unchecked 229 | { 230 | zde._VersionMadeBy = (short)(block[i++] + block[i++] * 256); 231 | zde._VersionNeeded = (short)(block[i++] + block[i++] * 256); 232 | zde._BitField = (short)(block[i++] + block[i++] * 256); 233 | zde._CompressionMethod = (Int16)(block[i++] + block[i++] * 256); 234 | zde._TimeBlob = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; 235 | zde._LastModified = Ionic.Zip.SharedUtilities.PackedToDateTime(zde._TimeBlob); 236 | zde._timestamp |= ZipEntryTimestamp.DOS; 237 | 238 | zde._Crc32 = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; 239 | zde._CompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); 240 | zde._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); 241 | } 242 | 243 | // preserve 244 | zde._CompressionMethod_FromZipFile = zde._CompressionMethod; 245 | 246 | zde._filenameLength = (short)(block[i++] + block[i++] * 256); 247 | zde._extraFieldLength = (short)(block[i++] + block[i++] * 256); 248 | zde._commentLength = (short)(block[i++] + block[i++] * 256); 249 | zde._diskNumber = (UInt32)(block[i++] + block[i++] * 256); 250 | 251 | zde._InternalFileAttrs = (short)(block[i++] + block[i++] * 256); 252 | zde._ExternalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; 253 | 254 | zde._RelativeOffsetOfLocalHeader = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); 255 | 256 | // workitem 7801 257 | zde.IsText = ((zde._InternalFileAttrs & 0x01) == 0x01); 258 | 259 | block = new byte[zde._filenameLength]; 260 | n = s.Read(block, 0, block.Length); 261 | bytesRead += n; 262 | if ((zde._BitField & 0x0800) == 0x0800) 263 | { 264 | // UTF-8 is in use 265 | zde._FileNameInArchive = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block); 266 | } 267 | else 268 | { 269 | zde._FileNameInArchive = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding); 270 | } 271 | 272 | // workitem 10330 273 | // insure unique entry names 274 | while (previouslySeen.ContainsKey(zde._FileNameInArchive)) 275 | { 276 | zde._FileNameInArchive = CopyHelper.AppendCopyToFileName(zde._FileNameInArchive); 277 | zde._metadataChanged = true; 278 | } 279 | 280 | if (zde.AttributesIndicateDirectory) 281 | zde.MarkAsDirectory(); // may append a slash to filename if nec. 282 | // workitem 6898 283 | else if (zde._FileNameInArchive.EndsWith("/")) zde.MarkAsDirectory(); 284 | 285 | zde._CompressedFileDataSize = zde._CompressedSize; 286 | if ((zde._BitField & 0x01) == 0x01) 287 | { 288 | // this may change after processing the Extra field 289 | zde._Encryption_FromZipFile = zde._Encryption = 290 | EncryptionAlgorithm.PkzipWeak; 291 | zde._sourceIsEncrypted = true; 292 | } 293 | 294 | if (zde._extraFieldLength > 0) 295 | { 296 | zde._InputUsesZip64 = (zde._CompressedSize == 0xFFFFFFFF || 297 | zde._UncompressedSize == 0xFFFFFFFF || 298 | zde._RelativeOffsetOfLocalHeader == 0xFFFFFFFF); 299 | 300 | // Console.WriteLine(" Input uses Z64?: {0}", zde._InputUsesZip64); 301 | 302 | bytesRead += zde.ProcessExtraField(s, zde._extraFieldLength); 303 | zde._CompressedFileDataSize = zde._CompressedSize; 304 | } 305 | 306 | // we've processed the extra field, so we know the encryption method is set now. 307 | if (zde._Encryption == EncryptionAlgorithm.PkzipWeak) 308 | { 309 | // the "encryption header" of 12 bytes precedes the file data 310 | zde._CompressedFileDataSize -= 12; 311 | } 312 | #if AESCRYPTO 313 | else if (zde.Encryption == EncryptionAlgorithm.WinZipAes128 || 314 | zde.Encryption == EncryptionAlgorithm.WinZipAes256) 315 | { 316 | zde._CompressedFileDataSize = zde.CompressedSize - 317 | (ZipEntry.GetLengthOfCryptoHeaderBytes(zde.Encryption) + 10); 318 | zde._LengthOfTrailer = 10; 319 | } 320 | #endif 321 | 322 | // tally the trailing descriptor 323 | if ((zde._BitField & 0x0008) == 0x0008) 324 | { 325 | // sig, CRC, Comp and Uncomp sizes 326 | if (zde._InputUsesZip64) 327 | zde._LengthOfTrailer += 24; 328 | else 329 | zde._LengthOfTrailer += 16; 330 | } 331 | 332 | // workitem 12744 333 | zde.AlternateEncoding = ((zde._BitField & 0x0800) == 0x0800) 334 | ? System.Text.Encoding.UTF8 335 | :expectedEncoding; 336 | 337 | zde.AlternateEncodingUsage = ZipOption.Always; 338 | 339 | if (zde._commentLength > 0) 340 | { 341 | block = new byte[zde._commentLength]; 342 | n = s.Read(block, 0, block.Length); 343 | bytesRead += n; 344 | if ((zde._BitField & 0x0800) == 0x0800) 345 | { 346 | // UTF-8 is in use 347 | zde._Comment = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block); 348 | } 349 | else 350 | { 351 | zde._Comment = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding); 352 | } 353 | } 354 | //zde._LengthOfDirEntry = bytesRead; 355 | return zde; 356 | } 357 | 358 | 359 | /// 360 | /// Returns true if the passed-in value is a valid signature for a ZipDirEntry. 361 | /// 362 | /// the candidate 4-byte signature value. 363 | /// true, if the signature is valid according to the PKWare spec. 364 | internal static bool IsNotValidZipDirEntrySig(int signature) 365 | { 366 | return (signature != ZipConstants.ZipDirEntrySignature); 367 | } 368 | 369 | 370 | private Int16 _VersionMadeBy; 371 | private Int16 _InternalFileAttrs; 372 | private Int32 _ExternalFileAttrs; 373 | 374 | //private Int32 _LengthOfDirEntry; 375 | private Int16 _filenameLength; 376 | private Int16 _extraFieldLength; 377 | private Int16 _commentLength; 378 | } 379 | 380 | 381 | } 382 | -------------------------------------------------------------------------------- /Zip/ZipEntrySource.cs: -------------------------------------------------------------------------------- 1 | // ZipEntrySource.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-November-19 11:18:42> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | 23 | namespace Ionic.Zip 24 | { 25 | /// 26 | /// An enum that specifies the source of the ZipEntry. 27 | /// 28 | public enum ZipEntrySource 29 | { 30 | /// 31 | /// Default value. Invalid on a bonafide ZipEntry. 32 | /// 33 | None = 0, 34 | 35 | /// 36 | /// The entry was instantiated by calling AddFile() or another method that 37 | /// added an entry from the filesystem. 38 | /// 39 | FileSystem, 40 | 41 | /// 42 | /// The entry was instantiated via or 43 | /// . 44 | /// 45 | Stream, 46 | 47 | /// 48 | /// The ZipEntry was instantiated by reading a zipfile. 49 | /// 50 | ZipFile, 51 | 52 | /// 53 | /// The content for the ZipEntry will be or was provided by the WriteDelegate. 54 | /// 55 | WriteDelegate, 56 | 57 | /// 58 | /// The content for the ZipEntry will be obtained from the stream dispensed by the OpenDelegate. 59 | /// The entry was instantiated via . 60 | /// 61 | JitStream, 62 | 63 | /// 64 | /// The content for the ZipEntry will be or was obtained from a ZipOutputStream. 65 | /// 66 | ZipOutputStream, 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /Zip/ZipErrorAction.cs: -------------------------------------------------------------------------------- 1 | // ZipErrorAction.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-September-01 18:43:20> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines the ZipErrorAction enum, which provides 23 | // an action to take when errors occur when opening or reading 24 | // files to be added to a zip file. 25 | // 26 | // ------------------------------------------------------------------ 27 | 28 | 29 | namespace Ionic.Zip 30 | { 31 | /// 32 | /// An enum providing the options when an error occurs during opening or reading 33 | /// of a file or directory that is being saved to a zip file. 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// This enum describes the actions that the library can take when an error occurs 39 | /// opening or reading a file, as it is being saved into a Zip archive. 40 | /// 41 | /// 42 | /// 43 | /// In some cases an error will occur when DotNetZip tries to open a file to be 44 | /// added to the zip archive. In other cases, an error might occur after the 45 | /// file has been successfully opened, while DotNetZip is reading the file. 46 | /// 47 | /// 48 | /// 49 | /// The first problem might occur when calling AddDirectory() on a directory 50 | /// that contains a Clipper .dbf file; the file is locked by Clipper and 51 | /// cannot be opened by another process. An example of the second problem is 52 | /// the ERROR_LOCK_VIOLATION that results when a file is opened by another 53 | /// process, but not locked, and a range lock has been taken on the file. 54 | /// Microsoft Outlook takes range locks on .PST files. 55 | /// 56 | /// 57 | public enum ZipErrorAction 58 | { 59 | /// 60 | /// Throw an exception when an error occurs while zipping. This is the default 61 | /// behavior. (For COM clients, this is a 0 (zero).) 62 | /// 63 | Throw, 64 | 65 | /// 66 | /// When an error occurs during zipping, for example a file cannot be opened, 67 | /// skip the file causing the error, and continue zipping. (For COM clients, 68 | /// this is a 1.) 69 | /// 70 | Skip, 71 | 72 | /// 73 | /// When an error occurs during zipping, for example a file cannot be opened, 74 | /// retry the operation that caused the error. Be careful with this option. If 75 | /// the error is not temporary, the library will retry forever. (For COM 76 | /// clients, this is a 2.) 77 | /// 78 | Retry, 79 | 80 | /// 81 | /// When an error occurs, invoke the zipError event. The event type used is 82 | /// . A typical use of this option: 83 | /// a GUI application may wish to pop up a dialog to allow the user to view the 84 | /// error that occurred, and choose an appropriate action. After your 85 | /// processing in the error event, if you want to skip the file, set on the 87 | /// ZipProgressEventArgs.CurrentEntry to Skip. If you want the 88 | /// exception to be thrown, set ZipErrorAction on the CurrentEntry 89 | /// to Throw. If you want to cancel the zip, set 90 | /// ZipProgressEventArgs.Cancel to true. Cancelling differs from using 91 | /// Skip in that a cancel will not save any further entries, if there are any. 92 | /// (For COM clients, the value of this enum is a 3.) 93 | /// 94 | InvokeErrorEvent, 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /Zip/ZipFile.Check.cs: -------------------------------------------------------------------------------- 1 | // ZipFile.Check.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009-2011 Dino Chiesa. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2011-July-31 14:40:50> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines the methods for doing Checks on zip files. 23 | // These are not necessary to include in the Reduced or CF 24 | // version of the library. 25 | // 26 | // ------------------------------------------------------------------ 27 | // 28 | 29 | 30 | using System; 31 | using System.IO; 32 | using System.Collections.Generic; 33 | 34 | namespace Ionic.Zip 35 | { 36 | public partial class ZipFile 37 | { 38 | /// 39 | /// Checks a zip file to see if its directory is consistent. 40 | /// 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// In cases of data error, the directory within a zip file can get out 46 | /// of synch with the entries in the zip file. This method checks the 47 | /// given zip file and returns true if this has occurred. 48 | /// 49 | /// 50 | /// This method may take a long time to run for large zip files. 51 | /// 52 | /// 53 | /// This method is not supported in the Reduced or Compact Framework 54 | /// versions of DotNetZip. 55 | /// 56 | /// 57 | /// 58 | /// Developers using COM can use the ComHelper.CheckZip(String) 60 | /// method. 61 | /// 62 | /// 63 | /// 64 | /// 65 | /// The filename to of the zip file to check. 66 | /// 67 | /// true if the named zip file checks OK. Otherwise, false. 68 | /// 69 | /// 70 | /// 71 | public static bool CheckZip(string zipFileName) 72 | { 73 | return CheckZip(zipFileName, false, null); 74 | } 75 | 76 | 77 | /// 78 | /// Checks a zip file to see if its directory is consistent, 79 | /// and optionally fixes the directory if necessary. 80 | /// 81 | /// 82 | /// 83 | /// 84 | /// 85 | /// In cases of data error, the directory within a zip file can get out of 86 | /// synch with the entries in the zip file. This method checks the given 87 | /// zip file, and returns true if this has occurred. It also optionally 88 | /// fixes the zipfile, saving the fixed copy in Name_Fixed.zip. 89 | /// 90 | /// 91 | /// 92 | /// This method may take a long time to run for large zip files. It 93 | /// will take even longer if the file actually needs to be fixed, and if 94 | /// fixIfNecessary is true. 95 | /// 96 | /// 97 | /// 98 | /// This method is not supported in the Reduced or Compact 99 | /// Framework versions of DotNetZip. 100 | /// 101 | /// 102 | /// 103 | /// 104 | /// The filename to of the zip file to check. 105 | /// 106 | /// If true, the method will fix the zip file if 107 | /// necessary. 108 | /// 109 | /// 110 | /// a TextWriter in which messages generated while checking will be written. 111 | /// 112 | /// 113 | /// true if the named zip is OK; false if the file needs to be fixed. 114 | /// 115 | /// 116 | /// 117 | public static bool CheckZip(string zipFileName, bool fixIfNecessary, 118 | TextWriter writer) 119 | 120 | { 121 | ZipFile zip1 = null, zip2 = null; 122 | bool isOk = true; 123 | try 124 | { 125 | zip1 = new ZipFile(); 126 | zip1.FullScan = true; 127 | zip1.Initialize(zipFileName); 128 | 129 | zip2 = ZipFile.Read(zipFileName); 130 | 131 | foreach (var e1 in zip1) 132 | { 133 | foreach (var e2 in zip2) 134 | { 135 | if (e1.FileName == e2.FileName) 136 | { 137 | if (e1._RelativeOffsetOfLocalHeader != e2._RelativeOffsetOfLocalHeader) 138 | { 139 | isOk = false; 140 | if (writer != null) 141 | writer.WriteLine("{0}: mismatch in RelativeOffsetOfLocalHeader (0x{1:X16} != 0x{2:X16})", 142 | e1.FileName, e1._RelativeOffsetOfLocalHeader, 143 | e2._RelativeOffsetOfLocalHeader); 144 | } 145 | if (e1._CompressedSize != e2._CompressedSize) 146 | { 147 | isOk = false; 148 | if (writer != null) 149 | writer.WriteLine("{0}: mismatch in CompressedSize (0x{1:X16} != 0x{2:X16})", 150 | e1.FileName, e1._CompressedSize, 151 | e2._CompressedSize); 152 | } 153 | if (e1._UncompressedSize != e2._UncompressedSize) 154 | { 155 | isOk = false; 156 | if (writer != null) 157 | writer.WriteLine("{0}: mismatch in UncompressedSize (0x{1:X16} != 0x{2:X16})", 158 | e1.FileName, e1._UncompressedSize, 159 | e2._UncompressedSize); 160 | } 161 | if (e1.CompressionMethod != e2.CompressionMethod) 162 | { 163 | isOk = false; 164 | if (writer != null) 165 | writer.WriteLine("{0}: mismatch in CompressionMethod (0x{1:X4} != 0x{2:X4})", 166 | e1.FileName, e1.CompressionMethod, 167 | e2.CompressionMethod); 168 | } 169 | if (e1.Crc != e2.Crc) 170 | { 171 | isOk = false; 172 | if (writer != null) 173 | writer.WriteLine("{0}: mismatch in Crc32 (0x{1:X4} != 0x{2:X4})", 174 | e1.FileName, e1.Crc, 175 | e2.Crc); 176 | } 177 | 178 | // found a match, so stop the inside loop 179 | break; 180 | } 181 | } 182 | } 183 | 184 | zip2.Dispose(); 185 | zip2 = null; 186 | 187 | if (!isOk && fixIfNecessary) 188 | { 189 | string newFileName = Path.GetFileNameWithoutExtension(zipFileName); 190 | newFileName = System.String.Format("{0}_fixed.zip", newFileName); 191 | zip1.Save(newFileName); 192 | } 193 | } 194 | finally 195 | { 196 | if (zip1 != null) zip1.Dispose(); 197 | if (zip2 != null) zip2.Dispose(); 198 | } 199 | return isOk; 200 | } 201 | 202 | 203 | 204 | /// 205 | /// Rewrite the directory within a zipfile. 206 | /// 207 | /// 208 | /// 209 | /// 210 | /// 211 | /// In cases of data error, the directory in a zip file can get out of 212 | /// synch with the entries in the zip file. This method attempts to fix 213 | /// the zip file if this has occurred. 214 | /// 215 | /// 216 | /// This can take a long time for large zip files. 217 | /// 218 | /// This won't work if the zip file uses a non-standard 219 | /// code page - neither IBM437 nor UTF-8. 220 | /// 221 | /// 222 | /// This method is not supported in the Reduced or Compact Framework 223 | /// versions of DotNetZip. 224 | /// 225 | /// 226 | /// 227 | /// Developers using COM can use the ComHelper.FixZipDirectory(String) 229 | /// method. 230 | /// 231 | /// 232 | /// 233 | /// 234 | /// The filename to of the zip file to fix. 235 | /// 236 | /// 237 | /// 238 | public static void FixZipDirectory(string zipFileName) 239 | { 240 | using (var zip = new ZipFile()) 241 | { 242 | zip.FullScan = true; 243 | zip.Initialize(zipFileName); 244 | zip.Save(zipFileName); 245 | } 246 | } 247 | 248 | 249 | 250 | /// 251 | /// Verify the password on a zip file. 252 | /// 253 | /// 254 | /// 255 | /// 256 | /// Keep in mind that passwords in zipfiles are applied to 257 | /// zip entries, not to the entire zip file. So testing a 258 | /// zipfile for a particular password doesn't work in the 259 | /// general case. On the other hand, it's often the case 260 | /// that a single password will be used on all entries in a 261 | /// zip file. This method works for that case. 262 | /// 263 | /// 264 | /// There is no way to check a password without doing the 265 | /// decryption. So this code decrypts and extracts the given 266 | /// zipfile into 267 | /// 268 | /// 269 | /// 270 | /// The filename to of the zip file to fix. 271 | /// 272 | /// The password to check. 273 | /// 274 | /// a bool indicating whether the password matches. 275 | public static bool CheckZipPassword(string zipFileName, string password) 276 | { 277 | // workitem 13664 278 | bool success = false; 279 | try 280 | { 281 | using (ZipFile zip1 = ZipFile.Read(zipFileName)) 282 | { 283 | foreach (var e in zip1) 284 | { 285 | if (!e.IsDirectory && e.UsesEncryption) 286 | { 287 | e.ExtractWithPassword(System.IO.Stream.Null, password); 288 | } 289 | } 290 | } 291 | success = true; 292 | } 293 | catch(Ionic.Zip.BadPasswordException) { } 294 | return success; 295 | } 296 | 297 | 298 | /// 299 | /// Provides a human-readable string with information about the ZipFile. 300 | /// 301 | /// 302 | /// 303 | /// 304 | /// The information string contains 10 lines or so, about each ZipEntry, 305 | /// describing whether encryption is in use, the compressed and uncompressed 306 | /// length of the entry, the offset of the entry, and so on. As a result the 307 | /// information string can be very long for zip files that contain many 308 | /// entries. 309 | /// 310 | /// 311 | /// This information is mostly useful for diagnostic purposes. 312 | /// 313 | /// 314 | public string Info 315 | { 316 | get 317 | { 318 | var builder = new System.Text.StringBuilder(); 319 | builder.Append(string.Format(" ZipFile: {0}\n", this.Name)); 320 | if (!string.IsNullOrEmpty(this._Comment)) 321 | { 322 | builder.Append(string.Format(" Comment: {0}\n", this._Comment)); 323 | } 324 | if (this._versionMadeBy != 0) 325 | { 326 | builder.Append(string.Format(" version made by: 0x{0:X4}\n", this._versionMadeBy)); 327 | } 328 | if (this._versionNeededToExtract != 0) 329 | { 330 | builder.Append(string.Format("needed to extract: 0x{0:X4}\n", this._versionNeededToExtract)); 331 | } 332 | 333 | builder.Append(string.Format(" uses ZIP64: {0}\n", this.InputUsesZip64)); 334 | 335 | builder.Append(string.Format(" disk with CD: {0}\n", this._diskNumberWithCd)); 336 | if (this._OffsetOfCentralDirectory == 0xFFFFFFFF) 337 | builder.Append(string.Format(" CD64 offset: 0x{0:X16}\n", this._OffsetOfCentralDirectory64)); 338 | else 339 | builder.Append(string.Format(" CD offset: 0x{0:X8}\n", this._OffsetOfCentralDirectory)); 340 | builder.Append("\n"); 341 | foreach (ZipEntry entry in this._entries.Values) 342 | { 343 | builder.Append(entry.Info); 344 | } 345 | return builder.ToString(); 346 | } 347 | } 348 | 349 | 350 | } 351 | 352 | } -------------------------------------------------------------------------------- /Zip/ZipFile.Extract.cs: -------------------------------------------------------------------------------- 1 | // ZipFile.Extract.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2011-July-31 14:45:18> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines the methods for Extract operations on zip files. 23 | // 24 | // ------------------------------------------------------------------ 25 | // 26 | 27 | 28 | using System; 29 | using System.IO; 30 | using System.Collections.Generic; 31 | 32 | namespace Ionic.Zip 33 | { 34 | 35 | public partial class ZipFile 36 | { 37 | 38 | /// 39 | /// Extracts all of the items in the zip archive, to the specified path in the 40 | /// filesystem. The path can be relative or fully-qualified. 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// This method will extract all entries in the ZipFile to the 46 | /// specified path. 47 | /// 48 | /// 49 | /// 50 | /// If an extraction of a file from the zip archive would overwrite an 51 | /// existing file in the filesystem, the action taken is dictated by the 52 | /// ExtractExistingFile property, which overrides any setting you may have 53 | /// made on individual ZipEntry instances. By default, if you have not 54 | /// set that property on the ZipFile instance, the entry will not 55 | /// be extracted, the existing file will not be overwritten and an 56 | /// exception will be thrown. To change this, set the property, or use the 57 | /// overload that allows you to 59 | /// specify an ExtractExistingFileAction parameter. 60 | /// 61 | /// 62 | /// 63 | /// The action to take when an extract would overwrite an existing file 64 | /// applies to all entries. If you want to set this on a per-entry basis, 65 | /// then you must use one of the ZipEntry.Extract methods. 67 | /// 68 | /// 69 | /// 70 | /// This method will send verbose output messages to the , if it is set on the ZipFile 72 | /// instance. 73 | /// 74 | /// 75 | /// 76 | /// You may wish to take advantage of the ExtractProgress event. 77 | /// 78 | /// 79 | /// 80 | /// About timestamps: When extracting a file entry from a zip archive, the 81 | /// extracted file gets the last modified time of the entry as stored in 82 | /// the archive. The archive may also store extended file timestamp 83 | /// information, including last accessed and created times. If these are 84 | /// present in the ZipEntry, then the extracted file will also get 85 | /// these times. 86 | /// 87 | /// 88 | /// 89 | /// A Directory entry is somewhat different. It will get the times as 90 | /// described for a file entry, but, if there are file entries in the zip 91 | /// archive that, when extracted, appear in the just-created directory, 92 | /// then when those file entries are extracted, the last modified and last 93 | /// accessed times of the directory will change, as a side effect. The 94 | /// result is that after an extraction of a directory and a number of 95 | /// files within the directory, the last modified and last accessed 96 | /// timestamps on the directory will reflect the time that the last file 97 | /// was extracted into the directory, rather than the time stored in the 98 | /// zip archive for the directory. 99 | /// 100 | /// 101 | /// 102 | /// To compensate, when extracting an archive with ExtractAll, 103 | /// DotNetZip will extract all the file and directory entries as described 104 | /// above, but it will then make a second pass on the directories, and 105 | /// reset the times on the directories to reflect what is stored in the 106 | /// zip archive. 107 | /// 108 | /// 109 | /// 110 | /// This compensation is performed only within the context of an 111 | /// ExtractAll. If you call ZipEntry.Extract on a directory 112 | /// entry, the timestamps on directory in the filesystem will reflect the 113 | /// times stored in the zip. If you then call ZipEntry.Extract on 114 | /// a file entry, which is extracted into the directory, the timestamps on 115 | /// the directory will be updated to the current time. 116 | /// 117 | /// 118 | /// 119 | /// 120 | /// This example extracts all the entries in a zip archive file, to the 121 | /// specified target directory. The extraction will overwrite any 122 | /// existing files silently. 123 | /// 124 | /// 125 | /// String TargetDirectory= "unpack"; 126 | /// using(ZipFile zip= ZipFile.Read(ZipFileToExtract)) 127 | /// { 128 | /// zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently; 129 | /// zip.ExtractAll(TargetDirectory); 130 | /// } 131 | /// 132 | /// 133 | /// 134 | /// Dim TargetDirectory As String = "unpack" 135 | /// Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) 136 | /// zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently 137 | /// zip.ExtractAll(TargetDirectory) 138 | /// End Using 139 | /// 140 | /// 141 | /// 142 | /// 143 | /// 144 | /// 145 | /// 146 | /// The path to which the contents of the zipfile will be extracted. 147 | /// The path can be relative or fully-qualified. 148 | /// 149 | /// 150 | public void ExtractAll(string path) 151 | { 152 | _InternalExtractAll(path, true); 153 | } 154 | 155 | 156 | 157 | /// 158 | /// Extracts all of the items in the zip archive, to the specified path in the 159 | /// filesystem, using the specified behavior when extraction would overwrite an 160 | /// existing file. 161 | /// 162 | /// 163 | /// 164 | /// 165 | /// 166 | /// This method will extract all entries in the ZipFile to the specified 167 | /// path. For an extraction that would overwrite an existing file, the behavior 168 | /// is dictated by , which overrides any 169 | /// setting you may have made on individual ZipEntry instances. 170 | /// 171 | /// 172 | /// 173 | /// The action to take when an extract would overwrite an existing file 174 | /// applies to all entries. If you want to set this on a per-entry basis, 175 | /// then you must use or one of the similar methods. 177 | /// 178 | /// 179 | /// 180 | /// Calling this method is equivalent to setting the property and then calling . 183 | /// 184 | /// 185 | /// 186 | /// This method will send verbose output messages to the 187 | /// , if it is set on the ZipFile instance. 188 | /// 189 | /// 190 | /// 191 | /// 192 | /// This example extracts all the entries in a zip archive file, to the 193 | /// specified target directory. It does not overwrite any existing files. 194 | /// 195 | /// String TargetDirectory= "c:\\unpack"; 196 | /// using(ZipFile zip= ZipFile.Read(ZipFileToExtract)) 197 | /// { 198 | /// zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite); 199 | /// } 200 | /// 201 | /// 202 | /// 203 | /// Dim TargetDirectory As String = "c:\unpack" 204 | /// Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) 205 | /// zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite) 206 | /// End Using 207 | /// 208 | /// 209 | /// 210 | /// 211 | /// The path to which the contents of the zipfile will be extracted. 212 | /// The path can be relative or fully-qualified. 213 | /// 214 | /// 215 | /// 216 | /// The action to take if extraction would overwrite an existing file. 217 | /// 218 | /// 219 | public void ExtractAll(string path, ExtractExistingFileAction extractExistingFile) 220 | { 221 | ExtractExistingFile = extractExistingFile; 222 | _InternalExtractAll(path, true); 223 | } 224 | 225 | 226 | private void _InternalExtractAll(string path, bool overrideExtractExistingProperty) 227 | { 228 | bool header = Verbose; 229 | _inExtractAll = true; 230 | try 231 | { 232 | OnExtractAllStarted(path); 233 | 234 | int n = 0; 235 | foreach (ZipEntry e in _entries.Values) 236 | { 237 | if (header) 238 | { 239 | StatusMessageTextWriter.WriteLine("\n{1,-22} {2,-8} {3,4} {4,-8} {0}", 240 | "Name", "Modified", "Size", "Ratio", "Packed"); 241 | StatusMessageTextWriter.WriteLine(new System.String('-', 72)); 242 | header = false; 243 | } 244 | if (Verbose) 245 | { 246 | StatusMessageTextWriter.WriteLine("{1,-22} {2,-8} {3,4:F0}% {4,-8} {0}", 247 | e.FileName, 248 | e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), 249 | e.UncompressedSize, 250 | e.CompressionRatio, 251 | e.CompressedSize); 252 | if (!String.IsNullOrEmpty(e.Comment)) 253 | StatusMessageTextWriter.WriteLine(" Comment: {0}", e.Comment); 254 | } 255 | e.Password = _Password; // this may be null 256 | OnExtractEntry(n, true, e, path); 257 | if (overrideExtractExistingProperty) 258 | e.ExtractExistingFile = this.ExtractExistingFile; 259 | e.Extract(path); 260 | n++; 261 | OnExtractEntry(n, false, e, path); 262 | if (_extractOperationCanceled) 263 | break; 264 | } 265 | 266 | if (!_extractOperationCanceled) 267 | { 268 | // workitem 8264: 269 | // now, set times on directory entries, again. 270 | // The problem is, extracting a file changes the times on the parent 271 | // directory. So after all files have been extracted, we have to 272 | // run through the directories again. 273 | foreach (ZipEntry e in _entries.Values) 274 | { 275 | // check if it is a directory 276 | if ((e.IsDirectory) || (e.FileName.EndsWith("/"))) 277 | { 278 | string outputFile = (e.FileName.StartsWith("/")) 279 | ? Path.Combine(path, e.FileName.Substring(1)) 280 | : Path.Combine(path, e.FileName); 281 | 282 | e._SetTimes(outputFile, false); 283 | } 284 | } 285 | OnExtractAllCompleted(path); 286 | } 287 | 288 | } 289 | finally 290 | { 291 | 292 | _inExtractAll = false; 293 | } 294 | } 295 | 296 | 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /Zip/ZipFile.SaveSelfExtractor.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r2d2rigo/dotnetzip-for-unity/b6e3951d18a9d28f7ef329c2065b284bd869451a/Zip/ZipFile.SaveSelfExtractor.cs -------------------------------------------------------------------------------- /Zip/ZipFile.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/r2d2rigo/dotnetzip-for-unity/b6e3951d18a9d28f7ef329c2065b284bd869451a/Zip/ZipFile.cs -------------------------------------------------------------------------------- /Zip/ZipFile.x-IEnumerable.cs: -------------------------------------------------------------------------------- 1 | // ZipFile.x-IEnumerable.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2006, 2007, 2008, 2009 Dino Chiesa and Microsoft Corporation. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-December-26 15:13:26> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines smoe methods for IEnumerable support. It is 23 | // particularly important for COM to have these things in a separate module. 24 | // 25 | // ------------------------------------------------------------------ 26 | 27 | 28 | namespace Ionic.Zip 29 | { 30 | 31 | // For some weird reason, the method with the DispId(-4) attribute, which is used as 32 | // the _NewEnum() method, and which is required to get enumeration to work from COM 33 | // environments like VBScript and Javascript (etc) must be the LAST MEMBER in the 34 | // source. In the event of Partial classes, it needs to be the last member defined 35 | // in the last source module. The source modules are ordered alphabetically by 36 | // filename. Not sure why this is true. In any case, we put the enumeration stuff 37 | // here in this oddly-named module, for this reason. 38 | // 39 | 40 | 41 | 42 | public partial class ZipFile 43 | { 44 | 45 | 46 | 47 | 48 | /// 49 | /// Generic IEnumerator support, for use of a ZipFile in an enumeration. 50 | /// 51 | /// 52 | /// 53 | /// You probably do not want to call GetEnumerator explicitly. Instead 54 | /// it is implicitly called when you use a loop in C#, or a 55 | /// For Each loop in VB.NET. 56 | /// 57 | /// 58 | /// 59 | /// This example reads a zipfile of a given name, then enumerates the 60 | /// entries in that zip file, and displays the information about each 61 | /// entry on the Console. 62 | /// 63 | /// using (ZipFile zip = ZipFile.Read(zipfile)) 64 | /// { 65 | /// bool header = true; 66 | /// foreach (ZipEntry e in zip) 67 | /// { 68 | /// if (header) 69 | /// { 70 | /// System.Console.WriteLine("Zipfile: {0}", zip.Name); 71 | /// System.Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded); 72 | /// System.Console.WriteLine("BitField: 0x{0:X2}", e.BitField); 73 | /// System.Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod); 74 | /// System.Console.WriteLine("\n{1,-22} {2,-6} {3,4} {4,-8} {0}", 75 | /// "Filename", "Modified", "Size", "Ratio", "Packed"); 76 | /// System.Console.WriteLine(new System.String('-', 72)); 77 | /// header = false; 78 | /// } 79 | /// 80 | /// System.Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", 81 | /// e.FileName, 82 | /// e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), 83 | /// e.UncompressedSize, 84 | /// e.CompressionRatio, 85 | /// e.CompressedSize); 86 | /// 87 | /// e.Extract(); 88 | /// } 89 | /// } 90 | /// 91 | /// 92 | /// 93 | /// Dim ZipFileToExtract As String = "c:\foo.zip" 94 | /// Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) 95 | /// Dim header As Boolean = True 96 | /// Dim e As ZipEntry 97 | /// For Each e In zip 98 | /// If header Then 99 | /// Console.WriteLine("Zipfile: {0}", zip.Name) 100 | /// Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded) 101 | /// Console.WriteLine("BitField: 0x{0:X2}", e.BitField) 102 | /// Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod) 103 | /// Console.WriteLine(ChrW(10) & "{1,-22} {2,-6} {3,4} {4,-8} {0}", _ 104 | /// "Filename", "Modified", "Size", "Ratio", "Packed" ) 105 | /// Console.WriteLine(New String("-"c, 72)) 106 | /// header = False 107 | /// End If 108 | /// Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", _ 109 | /// e.FileName, _ 110 | /// e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), _ 111 | /// e.UncompressedSize, _ 112 | /// e.CompressionRatio, _ 113 | /// e.CompressedSize ) 114 | /// e.Extract 115 | /// Next 116 | /// End Using 117 | /// 118 | /// 119 | /// 120 | /// A generic enumerator suitable for use within a foreach loop. 121 | public System.Collections.Generic.IEnumerator GetEnumerator() 122 | { 123 | foreach (ZipEntry e in _entries.Values) 124 | yield return e; 125 | } 126 | 127 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 128 | { 129 | return GetEnumerator(); 130 | } 131 | 132 | 133 | /// 134 | /// An IEnumerator, for use of a ZipFile in a foreach construct. 135 | /// 136 | /// 137 | /// 138 | /// This method is included for COM support. An application generally does not call 139 | /// this method directly. It is called implicitly by COM clients when enumerating 140 | /// the entries in the ZipFile instance. In VBScript, this is done with a For Each 141 | /// statement. In Javascript, this is done with new Enumerator(zipfile). 142 | /// 143 | /// 144 | /// 145 | /// The IEnumerator over the entries in the ZipFile. 146 | /// 147 | [System.Runtime.InteropServices.DispId(-4)] 148 | public System.Collections.IEnumerator GetNewEnum() // the name of this method is not significant 149 | { 150 | return GetEnumerator(); 151 | } 152 | 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /Zip/ZipSegmentedStream.cs: -------------------------------------------------------------------------------- 1 | // ZipSegmentedStream.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009-2011 Dino Chiesa. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2011-July-13 22:25:45> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines logic for zip streams that span disk files. 23 | // 24 | // ------------------------------------------------------------------ 25 | 26 | 27 | using System; 28 | using System.Collections.Generic; 29 | using System.IO; 30 | 31 | namespace Ionic.Zip 32 | { 33 | internal class ZipSegmentedStream : System.IO.Stream 34 | { 35 | enum RwMode 36 | { 37 | None = 0, 38 | ReadOnly = 1, 39 | Write = 2, 40 | //Update = 3 41 | } 42 | 43 | private RwMode rwMode; 44 | private bool _exceptionPending; // **see note below 45 | private string _baseName; 46 | private string _baseDir; 47 | //private bool _isDisposed; 48 | private string _currentName; 49 | private string _currentTempName; 50 | private uint _currentDiskNumber; 51 | private uint _maxDiskNumber; 52 | private int _maxSegmentSize; 53 | private System.IO.Stream _innerStream; 54 | 55 | // **Note regarding exceptions: 56 | // 57 | // When ZipSegmentedStream is employed within a using clause, 58 | // which is the typical scenario, and an exception is thrown 59 | // within the scope of the using, Dispose() is invoked 60 | // implicitly before processing the initial exception. If that 61 | // happens, this class sets _exceptionPending to true, and then 62 | // within the Dispose(bool), takes special action as 63 | // appropriate. Need to be careful: any additional exceptions 64 | // will mask the original one. 65 | 66 | private ZipSegmentedStream() : base() 67 | { 68 | _exceptionPending = false; 69 | } 70 | 71 | public static ZipSegmentedStream ForReading(string name, 72 | uint initialDiskNumber, 73 | uint maxDiskNumber) 74 | { 75 | ZipSegmentedStream zss = new ZipSegmentedStream() 76 | { 77 | rwMode = RwMode.ReadOnly, 78 | CurrentSegment = initialDiskNumber, 79 | _maxDiskNumber = maxDiskNumber, 80 | _baseName = name, 81 | }; 82 | 83 | // Console.WriteLine("ZSS: ForReading ({0})", 84 | // Path.GetFileName(zss.CurrentName)); 85 | 86 | zss._SetReadStream(); 87 | 88 | return zss; 89 | } 90 | 91 | 92 | public static ZipSegmentedStream ForWriting(string name, int maxSegmentSize) 93 | { 94 | ZipSegmentedStream zss = new ZipSegmentedStream() 95 | { 96 | rwMode = RwMode.Write, 97 | CurrentSegment = 0, 98 | _baseName = name, 99 | _maxSegmentSize = maxSegmentSize, 100 | _baseDir = Path.GetDirectoryName(name) 101 | }; 102 | 103 | // workitem 9522 104 | if (zss._baseDir=="") zss._baseDir="."; 105 | 106 | zss._SetWriteStream(0); 107 | 108 | // Console.WriteLine("ZSS: ForWriting ({0})", 109 | // Path.GetFileName(zss.CurrentName)); 110 | 111 | return zss; 112 | } 113 | 114 | 115 | /// 116 | /// Sort-of like a factory method, ForUpdate is used only when 117 | /// the application needs to update the zip entry metadata for 118 | /// a segmented zip file, when the starting segment is earlier 119 | /// than the ending segment, for a particular entry. 120 | /// 121 | /// 122 | /// 123 | /// The update is always contiguous, never rolls over. As a 124 | /// result, this method doesn't need to return a ZSS; it can 125 | /// simply return a FileStream. That's why it's "sort of" 126 | /// like a Factory method. 127 | /// 128 | /// 129 | /// Caller must Close/Dispose the stream object returned by 130 | /// this method. 131 | /// 132 | /// 133 | public static Stream ForUpdate(string name, uint diskNumber) 134 | { 135 | if (diskNumber >= 99) 136 | throw new ArgumentOutOfRangeException("diskNumber"); 137 | 138 | string fname = 139 | String.Format("{0}.z{1:D2}", 140 | Path.Combine(Path.GetDirectoryName(name), 141 | Path.GetFileNameWithoutExtension(name)), 142 | diskNumber + 1); 143 | 144 | // Console.WriteLine("ZSS: ForUpdate ({0})", 145 | // Path.GetFileName(fname)); 146 | 147 | // This class assumes that the update will not expand the 148 | // size of the segment. Update is used only for an in-place 149 | // update of zip metadata. It never will try to write beyond 150 | // the end of a segment. 151 | 152 | return File.Open(fname, 153 | FileMode.Open, 154 | FileAccess.ReadWrite, 155 | FileShare.None); 156 | } 157 | 158 | public bool ContiguousWrite 159 | { 160 | get; 161 | set; 162 | } 163 | 164 | 165 | public UInt32 CurrentSegment 166 | { 167 | get 168 | { 169 | return _currentDiskNumber; 170 | } 171 | private set 172 | { 173 | _currentDiskNumber = value; 174 | _currentName = null; // it will get updated next time referenced 175 | } 176 | } 177 | 178 | /// 179 | /// Name of the filesystem file corresponding to the current segment. 180 | /// 181 | /// 182 | /// 183 | /// The name is not always the name currently being used in the 184 | /// filesystem. When rwMode is RwMode.Write, the filesystem file has a 185 | /// temporary name until the stream is closed or until the next segment is 186 | /// started. 187 | /// 188 | /// 189 | public String CurrentName 190 | { 191 | get 192 | { 193 | if (_currentName==null) 194 | _currentName = _NameForSegment(CurrentSegment); 195 | 196 | return _currentName; 197 | } 198 | } 199 | 200 | 201 | public String CurrentTempName 202 | { 203 | get 204 | { 205 | return _currentTempName; 206 | } 207 | } 208 | 209 | private string _NameForSegment(uint diskNumber) 210 | { 211 | if (diskNumber >= 99) 212 | { 213 | _exceptionPending = true; 214 | throw new OverflowException("The number of zip segments would exceed 99."); 215 | } 216 | 217 | return String.Format("{0}.z{1:D2}", 218 | Path.Combine(Path.GetDirectoryName(_baseName), 219 | Path.GetFileNameWithoutExtension(_baseName)), 220 | diskNumber + 1); 221 | } 222 | 223 | 224 | // Returns the segment that WILL be current if writing 225 | // a block of the given length. 226 | // This isn't exactly true. It could roll over beyond 227 | // this number. 228 | public UInt32 ComputeSegment(int length) 229 | { 230 | if (_innerStream.Position + length > _maxSegmentSize) 231 | // the block will go AT LEAST into the next segment 232 | return CurrentSegment + 1; 233 | 234 | // it will fit in the current segment 235 | return CurrentSegment; 236 | } 237 | 238 | 239 | public override String ToString() 240 | { 241 | return String.Format("{0}[{1}][{2}], pos=0x{3:X})", 242 | "ZipSegmentedStream", CurrentName, 243 | rwMode.ToString(), 244 | this.Position); 245 | } 246 | 247 | 248 | private void _SetReadStream() 249 | { 250 | if (_innerStream != null) 251 | { 252 | #if NETCF 253 | _innerStream.Close(); 254 | #else 255 | _innerStream.Dispose(); 256 | #endif 257 | } 258 | 259 | if (CurrentSegment + 1 == _maxDiskNumber) 260 | _currentName = _baseName; 261 | 262 | // Console.WriteLine("ZSS: SRS ({0})", 263 | // Path.GetFileName(CurrentName)); 264 | 265 | _innerStream = File.OpenRead(CurrentName); 266 | } 267 | 268 | 269 | /// 270 | /// Read from the stream 271 | /// 272 | /// the buffer to read 273 | /// the offset at which to start 274 | /// the number of bytes to read 275 | /// the number of bytes actually read 276 | public override int Read(byte[] buffer, int offset, int count) 277 | { 278 | if (rwMode != RwMode.ReadOnly) 279 | { 280 | _exceptionPending = true; 281 | throw new InvalidOperationException("Stream Error: Cannot Read."); 282 | } 283 | 284 | int r = _innerStream.Read(buffer, offset, count); 285 | int r1 = r; 286 | 287 | while (r1 != count) 288 | { 289 | if (_innerStream.Position != _innerStream.Length) 290 | { 291 | _exceptionPending = true; 292 | throw new ZipException(String.Format("Read error in file {0}", CurrentName)); 293 | 294 | } 295 | 296 | if (CurrentSegment + 1 == _maxDiskNumber) 297 | return r; // no more to read 298 | 299 | CurrentSegment++; 300 | _SetReadStream(); 301 | offset += r1; 302 | count -= r1; 303 | r1 = _innerStream.Read(buffer, offset, count); 304 | r += r1; 305 | } 306 | return r; 307 | } 308 | 309 | 310 | 311 | private void _SetWriteStream(uint increment) 312 | { 313 | if (_innerStream != null) 314 | { 315 | #if NETCF 316 | _innerStream.Close(); 317 | #else 318 | _innerStream.Dispose(); 319 | #endif 320 | if (File.Exists(CurrentName)) 321 | File.Delete(CurrentName); 322 | File.Move(_currentTempName, CurrentName); 323 | // Console.WriteLine("ZSS: SWS close ({0})", 324 | // Path.GetFileName(CurrentName)); 325 | } 326 | 327 | if (increment > 0) 328 | CurrentSegment += increment; 329 | 330 | SharedUtilities.CreateAndOpenUniqueTempFile(_baseDir, 331 | out _innerStream, 332 | out _currentTempName); 333 | 334 | // Console.WriteLine("ZSS: SWS open ({0})", 335 | // Path.GetFileName(_currentTempName)); 336 | 337 | if (CurrentSegment == 0) 338 | _innerStream.Write(BitConverter.GetBytes(ZipConstants.SplitArchiveSignature), 0, 4); 339 | } 340 | 341 | 342 | /// 343 | /// Write to the stream. 344 | /// 345 | /// the buffer from which to write 346 | /// the offset at which to start writing 347 | /// the number of bytes to write 348 | public override void Write(byte[] buffer, int offset, int count) 349 | { 350 | if (rwMode != RwMode.Write) 351 | { 352 | _exceptionPending = true; 353 | throw new InvalidOperationException("Stream Error: Cannot Write."); 354 | } 355 | 356 | 357 | if (ContiguousWrite) 358 | { 359 | // enough space for a contiguous write? 360 | if (_innerStream.Position + count > _maxSegmentSize) 361 | _SetWriteStream(1); 362 | } 363 | else 364 | { 365 | while (_innerStream.Position + count > _maxSegmentSize) 366 | { 367 | int c = unchecked(_maxSegmentSize - (int)_innerStream.Position); 368 | _innerStream.Write(buffer, offset, c); 369 | _SetWriteStream(1); 370 | count -= c; 371 | offset += c; 372 | } 373 | } 374 | 375 | _innerStream.Write(buffer, offset, count); 376 | } 377 | 378 | 379 | public long TruncateBackward(uint diskNumber, long offset) 380 | { 381 | // Console.WriteLine("***ZSS.Trunc to disk {0}", diskNumber); 382 | // Console.WriteLine("***ZSS.Trunc: current disk {0}", CurrentSegment); 383 | if (diskNumber >= 99) 384 | throw new ArgumentOutOfRangeException("diskNumber"); 385 | 386 | if (rwMode != RwMode.Write) 387 | { 388 | _exceptionPending = true; 389 | throw new ZipException("bad state."); 390 | } 391 | 392 | // Seek back in the segmented stream to a (maybe) prior segment. 393 | 394 | // Check if it is the same segment. If it is, very simple. 395 | if (diskNumber == CurrentSegment) 396 | { 397 | var x =_innerStream.Seek(offset, SeekOrigin.Begin); 398 | // workitem 10178 399 | Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_innerStream); 400 | return x; 401 | } 402 | 403 | // Seeking back to a prior segment. 404 | // The current segment and any intervening segments must be removed. 405 | // First, close the current segment, and then remove it. 406 | if (_innerStream != null) 407 | { 408 | #if NETCF 409 | _innerStream.Close(); 410 | #else 411 | _innerStream.Dispose(); 412 | #endif 413 | if (File.Exists(_currentTempName)) 414 | File.Delete(_currentTempName); 415 | } 416 | 417 | // Now, remove intervening segments. 418 | for (uint j= CurrentSegment-1; j > diskNumber; j--) 419 | { 420 | string s = _NameForSegment(j); 421 | // Console.WriteLine("***ZSS.Trunc: removing file {0}", s); 422 | if (File.Exists(s)) 423 | File.Delete(s); 424 | } 425 | 426 | // now, open the desired segment. It must exist. 427 | CurrentSegment = diskNumber; 428 | 429 | // get a new temp file, try 3 times: 430 | for (int i = 0; i < 3; i++) 431 | { 432 | try 433 | { 434 | _currentTempName = SharedUtilities.InternalGetTempFileName(); 435 | // move the .z0x file back to a temp name 436 | File.Move(CurrentName, _currentTempName); 437 | break; // workitem 12403 438 | } 439 | catch(IOException) 440 | { 441 | if (i == 2) throw; 442 | } 443 | } 444 | 445 | // open it 446 | _innerStream = new FileStream(_currentTempName, FileMode.Open); 447 | 448 | var r = _innerStream.Seek(offset, SeekOrigin.Begin); 449 | 450 | // workitem 10178 451 | Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_innerStream); 452 | 453 | return r; 454 | } 455 | 456 | 457 | 458 | public override bool CanRead 459 | { 460 | get 461 | { 462 | return (rwMode == RwMode.ReadOnly && 463 | (_innerStream != null) && 464 | _innerStream.CanRead); 465 | } 466 | } 467 | 468 | 469 | public override bool CanSeek 470 | { 471 | get 472 | { 473 | return (_innerStream != null) && 474 | _innerStream.CanSeek; 475 | } 476 | } 477 | 478 | 479 | public override bool CanWrite 480 | { 481 | get 482 | { 483 | return (rwMode == RwMode.Write) && 484 | (_innerStream != null) && 485 | _innerStream.CanWrite; 486 | } 487 | } 488 | 489 | public override void Flush() 490 | { 491 | _innerStream.Flush(); 492 | } 493 | 494 | public override long Length 495 | { 496 | get 497 | { 498 | return _innerStream.Length; 499 | } 500 | } 501 | 502 | public override long Position 503 | { 504 | get { return _innerStream.Position; } 505 | set { _innerStream.Position = value; } 506 | } 507 | 508 | public override long Seek(long offset, System.IO.SeekOrigin origin) 509 | { 510 | var x = _innerStream.Seek(offset, origin); 511 | // workitem 10178 512 | Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_innerStream); 513 | return x; 514 | } 515 | 516 | public override void SetLength(long value) 517 | { 518 | if (rwMode != RwMode.Write) 519 | { 520 | _exceptionPending = true; 521 | throw new InvalidOperationException(); 522 | } 523 | _innerStream.SetLength(value); 524 | } 525 | 526 | 527 | protected override void Dispose(bool disposing) 528 | { 529 | // this gets called by Stream.Close() 530 | 531 | // if (_isDisposed) return; 532 | // _isDisposed = true; 533 | //Console.WriteLine("Dispose (mode={0})\n", rwMode.ToString()); 534 | 535 | try 536 | { 537 | if (_innerStream != null) 538 | { 539 | #if NETCF 540 | _innerStream.Close(); 541 | #else 542 | _innerStream.Dispose(); 543 | #endif 544 | //_innerStream = null; 545 | if (rwMode == RwMode.Write) 546 | { 547 | if (_exceptionPending) 548 | { 549 | // possibly could try to clean up all the 550 | // temp files created so far... 551 | } 552 | else 553 | { 554 | // // move the final temp file to the .zNN name 555 | // if (File.Exists(CurrentName)) 556 | // File.Delete(CurrentName); 557 | // if (File.Exists(_currentTempName)) 558 | // File.Move(_currentTempName, CurrentName); 559 | } 560 | } 561 | } 562 | } 563 | finally 564 | { 565 | base.Dispose(disposing); 566 | } 567 | } 568 | 569 | } 570 | 571 | } -------------------------------------------------------------------------------- /Zlib/LICENSE.jzlib.txt: -------------------------------------------------------------------------------- 1 | The ZLIB library, available as Ionic.Zlib.dll or as part of DotNetZip, 2 | is a ported-then-modified version of jzlib. The following applies to jzlib: 3 | 4 | JZlib 0.0.* were released under the GNU LGPL license. Later, we have switched 5 | over to a BSD-style license. 6 | 7 | ------------------------------------------------------------------------------ 8 | Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright 17 | notice, this list of conditions and the following disclaimer in 18 | the documentation and/or other materials provided with the distribution. 19 | 20 | 3. The names of the authors may not be used to endorse or promote products 21 | derived from this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 24 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 25 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, 26 | INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 29 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /Zlib/License.zlib.txt: -------------------------------------------------------------------------------- 1 | The ZLIB library, available as Ionic.Zlib.dll or as part of DotNetZip, 2 | is a ported-then-modified version of jzlib, which itself is based on 3 | zlib-1.1.3, the well-known C-language compression library. 4 | 5 | The following notice applies to zlib: 6 | 7 | ----------------------------------------------------------------------- 8 | 9 | Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler 10 | 11 | The ZLIB software is provided 'as-is', without any express or implied 12 | warranty. In no event will the authors be held liable for any damages 13 | arising from the use of this software. 14 | 15 | Permission is granted to anyone to use this software for any purpose, 16 | including commercial applications, and to alter it and redistribute it 17 | freely, subject to the following restrictions: 18 | 19 | 1. The origin of this software must not be misrepresented; you must not 20 | claim that you wrote the original software. If you use this software 21 | in a product, an acknowledgment in the product documentation would be 22 | appreciated but is not required. 23 | 2. Altered source versions must be plainly marked as such, and must not be 24 | misrepresented as being the original software. 25 | 3. This notice may not be removed or altered from any source distribution. 26 | 27 | Jean-loup Gailly jloup@gzip.org 28 | Mark Adler madler@alumni.caltech.edu 29 | 30 | 31 | ----------------------------------------------------------------------- 32 | -------------------------------------------------------------------------------- /Zlib/Tree.cs: -------------------------------------------------------------------------------- 1 | // Tree.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-October-28 13:29:50> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines classes for zlib compression and 23 | // decompression. This code is derived from the jzlib implementation of 24 | // zlib. In keeping with the license for jzlib, the copyright to that 25 | // code is below. 26 | // 27 | // ------------------------------------------------------------------ 28 | // 29 | // Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. 30 | // 31 | // Redistribution and use in source and binary forms, with or without 32 | // modification, are permitted provided that the following conditions are met: 33 | // 34 | // 1. Redistributions of source code must retain the above copyright notice, 35 | // this list of conditions and the following disclaimer. 36 | // 37 | // 2. Redistributions in binary form must reproduce the above copyright 38 | // notice, this list of conditions and the following disclaimer in 39 | // the documentation and/or other materials provided with the distribution. 40 | // 41 | // 3. The names of the authors may not be used to endorse or promote products 42 | // derived from this software without specific prior written permission. 43 | // 44 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 45 | // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 46 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, 47 | // INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 48 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 49 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 50 | // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 51 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 52 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 53 | // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 | // 55 | // ----------------------------------------------------------------------- 56 | // 57 | // This program is based on zlib-1.1.3; credit to authors 58 | // Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) 59 | // and contributors of zlib. 60 | // 61 | // ----------------------------------------------------------------------- 62 | 63 | 64 | using System; 65 | 66 | namespace Ionic.Zlib 67 | { 68 | sealed class Tree 69 | { 70 | private static readonly int HEAP_SIZE = (2 * InternalConstants.L_CODES + 1); 71 | 72 | // extra bits for each length code 73 | internal static readonly int[] ExtraLengthBits = new int[] 74 | { 75 | 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 76 | 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 77 | }; 78 | 79 | // extra bits for each distance code 80 | internal static readonly int[] ExtraDistanceBits = new int[] 81 | { 82 | 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 83 | 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 84 | }; 85 | 86 | // extra bits for each bit length code 87 | internal static readonly int[] extra_blbits = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7}; 88 | 89 | internal static readonly sbyte[] bl_order = new sbyte[]{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; 90 | 91 | 92 | // The lengths of the bit length codes are sent in order of decreasing 93 | // probability, to avoid transmitting the lengths for unused bit 94 | // length codes. 95 | 96 | internal const int Buf_size = 8 * 2; 97 | 98 | // see definition of array dist_code below 99 | //internal const int DIST_CODE_LEN = 512; 100 | 101 | private static readonly sbyte[] _dist_code = new sbyte[] 102 | { 103 | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 104 | 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 105 | 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 106 | 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 107 | 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 108 | 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 109 | 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 110 | 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 111 | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 112 | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 113 | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 114 | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 115 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 116 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 117 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 118 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 119 | 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 120 | 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 121 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 122 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 123 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 124 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 125 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 126 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 127 | 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 128 | 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 129 | 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 130 | 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 131 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 132 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 133 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 134 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 135 | }; 136 | 137 | internal static readonly sbyte[] LengthCode = new sbyte[] 138 | { 139 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 140 | 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 141 | 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 142 | 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 143 | 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 144 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 145 | 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 146 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 147 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 148 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 149 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 150 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 151 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 152 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 153 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 154 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 155 | }; 156 | 157 | 158 | internal static readonly int[] LengthBase = new int[] 159 | { 160 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 161 | 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 162 | }; 163 | 164 | 165 | internal static readonly int[] DistanceBase = new int[] 166 | { 167 | 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 168 | 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 169 | }; 170 | 171 | 172 | /// 173 | /// Map from a distance to a distance code. 174 | /// 175 | /// 176 | /// No side effects. _dist_code[256] and _dist_code[257] are never used. 177 | /// 178 | internal static int DistanceCode(int dist) 179 | { 180 | return (dist < 256) 181 | ? _dist_code[dist] 182 | : _dist_code[256 + SharedUtils.URShift(dist, 7)]; 183 | } 184 | 185 | internal short[] dyn_tree; // the dynamic tree 186 | internal int max_code; // largest code with non zero frequency 187 | internal StaticTree staticTree; // the corresponding static tree 188 | 189 | // Compute the optimal bit lengths for a tree and update the total bit length 190 | // for the current block. 191 | // IN assertion: the fields freq and dad are set, heap[heap_max] and 192 | // above are the tree nodes sorted by increasing frequency. 193 | // OUT assertions: the field len is set to the optimal bit length, the 194 | // array bl_count contains the frequencies for each bit length. 195 | // The length opt_len is updated; static_len is also updated if stree is 196 | // not null. 197 | internal void gen_bitlen(DeflateManager s) 198 | { 199 | short[] tree = dyn_tree; 200 | short[] stree = staticTree.treeCodes; 201 | int[] extra = staticTree.extraBits; 202 | int base_Renamed = staticTree.extraBase; 203 | int max_length = staticTree.maxLength; 204 | int h; // heap index 205 | int n, m; // iterate over the tree elements 206 | int bits; // bit length 207 | int xbits; // extra bits 208 | short f; // frequency 209 | int overflow = 0; // number of elements with bit length too large 210 | 211 | for (bits = 0; bits <= InternalConstants.MAX_BITS; bits++) 212 | s.bl_count[bits] = 0; 213 | 214 | // In a first pass, compute the optimal bit lengths (which may 215 | // overflow in the case of the bit length tree). 216 | tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap 217 | 218 | for (h = s.heap_max + 1; h < HEAP_SIZE; h++) 219 | { 220 | n = s.heap[h]; 221 | bits = tree[tree[n * 2 + 1] * 2 + 1] + 1; 222 | if (bits > max_length) 223 | { 224 | bits = max_length; overflow++; 225 | } 226 | tree[n * 2 + 1] = (short) bits; 227 | // We overwrite tree[n*2+1] which is no longer needed 228 | 229 | if (n > max_code) 230 | continue; // not a leaf node 231 | 232 | s.bl_count[bits]++; 233 | xbits = 0; 234 | if (n >= base_Renamed) 235 | xbits = extra[n - base_Renamed]; 236 | f = tree[n * 2]; 237 | s.opt_len += f * (bits + xbits); 238 | if (stree != null) 239 | s.static_len += f * (stree[n * 2 + 1] + xbits); 240 | } 241 | if (overflow == 0) 242 | return ; 243 | 244 | // This happens for example on obj2 and pic of the Calgary corpus 245 | // Find the first bit length which could increase: 246 | do 247 | { 248 | bits = max_length - 1; 249 | while (s.bl_count[bits] == 0) 250 | bits--; 251 | s.bl_count[bits]--; // move one leaf down the tree 252 | s.bl_count[bits + 1] = (short) (s.bl_count[bits + 1] + 2); // move one overflow item as its brother 253 | s.bl_count[max_length]--; 254 | // The brother of the overflow item also moves one step up, 255 | // but this does not affect bl_count[max_length] 256 | overflow -= 2; 257 | } 258 | while (overflow > 0); 259 | 260 | for (bits = max_length; bits != 0; bits--) 261 | { 262 | n = s.bl_count[bits]; 263 | while (n != 0) 264 | { 265 | m = s.heap[--h]; 266 | if (m > max_code) 267 | continue; 268 | if (tree[m * 2 + 1] != bits) 269 | { 270 | s.opt_len = (int) (s.opt_len + ((long) bits - (long) tree[m * 2 + 1]) * (long) tree[m * 2]); 271 | tree[m * 2 + 1] = (short) bits; 272 | } 273 | n--; 274 | } 275 | } 276 | } 277 | 278 | // Construct one Huffman tree and assigns the code bit strings and lengths. 279 | // Update the total bit length for the current block. 280 | // IN assertion: the field freq is set for all tree elements. 281 | // OUT assertions: the fields len and code are set to the optimal bit length 282 | // and corresponding code. The length opt_len is updated; static_len is 283 | // also updated if stree is not null. The field max_code is set. 284 | internal void build_tree(DeflateManager s) 285 | { 286 | short[] tree = dyn_tree; 287 | short[] stree = staticTree.treeCodes; 288 | int elems = staticTree.elems; 289 | int n, m; // iterate over heap elements 290 | int max_code = -1; // largest code with non zero frequency 291 | int node; // new node being created 292 | 293 | // Construct the initial heap, with least frequent element in 294 | // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. 295 | // heap[0] is not used. 296 | s.heap_len = 0; 297 | s.heap_max = HEAP_SIZE; 298 | 299 | for (n = 0; n < elems; n++) 300 | { 301 | if (tree[n * 2] != 0) 302 | { 303 | s.heap[++s.heap_len] = max_code = n; 304 | s.depth[n] = 0; 305 | } 306 | else 307 | { 308 | tree[n * 2 + 1] = 0; 309 | } 310 | } 311 | 312 | // The pkzip format requires that at least one distance code exists, 313 | // and that at least one bit should be sent even if there is only one 314 | // possible code. So to avoid special checks later on we force at least 315 | // two codes of non zero frequency. 316 | while (s.heap_len < 2) 317 | { 318 | node = s.heap[++s.heap_len] = (max_code < 2?++max_code:0); 319 | tree[node * 2] = 1; 320 | s.depth[node] = 0; 321 | s.opt_len--; 322 | if (stree != null) 323 | s.static_len -= stree[node * 2 + 1]; 324 | // node is 0 or 1 so it does not have extra bits 325 | } 326 | this.max_code = max_code; 327 | 328 | // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, 329 | // establish sub-heaps of increasing lengths: 330 | 331 | for (n = s.heap_len / 2; n >= 1; n--) 332 | s.pqdownheap(tree, n); 333 | 334 | // Construct the Huffman tree by repeatedly combining the least two 335 | // frequent nodes. 336 | 337 | node = elems; // next internal node of the tree 338 | do 339 | { 340 | // n = node of least frequency 341 | n = s.heap[1]; 342 | s.heap[1] = s.heap[s.heap_len--]; 343 | s.pqdownheap(tree, 1); 344 | m = s.heap[1]; // m = node of next least frequency 345 | 346 | s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency 347 | s.heap[--s.heap_max] = m; 348 | 349 | // Create a new node father of n and m 350 | tree[node * 2] = unchecked((short) (tree[n * 2] + tree[m * 2])); 351 | s.depth[node] = (sbyte) (System.Math.Max((byte) s.depth[n], (byte) s.depth[m]) + 1); 352 | tree[n * 2 + 1] = tree[m * 2 + 1] = (short) node; 353 | 354 | // and insert the new node in the heap 355 | s.heap[1] = node++; 356 | s.pqdownheap(tree, 1); 357 | } 358 | while (s.heap_len >= 2); 359 | 360 | s.heap[--s.heap_max] = s.heap[1]; 361 | 362 | // At this point, the fields freq and dad are set. We can now 363 | // generate the bit lengths. 364 | 365 | gen_bitlen(s); 366 | 367 | // The field len is now set, we can generate the bit codes 368 | gen_codes(tree, max_code, s.bl_count); 369 | } 370 | 371 | // Generate the codes for a given tree and bit counts (which need not be 372 | // optimal). 373 | // IN assertion: the array bl_count contains the bit length statistics for 374 | // the given tree and the field len is set for all tree elements. 375 | // OUT assertion: the field code is set for all tree elements of non 376 | // zero code length. 377 | internal static void gen_codes(short[] tree, int max_code, short[] bl_count) 378 | { 379 | short[] next_code = new short[InternalConstants.MAX_BITS + 1]; // next code value for each bit length 380 | short code = 0; // running code value 381 | int bits; // bit index 382 | int n; // code index 383 | 384 | // The distribution counts are first used to generate the code values 385 | // without bit reversal. 386 | for (bits = 1; bits <= InternalConstants.MAX_BITS; bits++) 387 | unchecked { 388 | next_code[bits] = code = (short) ((code + bl_count[bits - 1]) << 1); 389 | } 390 | 391 | // Check that the bit counts in bl_count are consistent. The last code 392 | // must be all ones. 393 | //Assert (code + bl_count[MAX_BITS]-1 == (1<>= 1; //SharedUtils.URShift(code, 1); 417 | res <<= 1; 418 | } 419 | while (--len > 0); 420 | return res >> 1; 421 | } 422 | } 423 | } -------------------------------------------------------------------------------- /Zlib/ZlibConstants.cs: -------------------------------------------------------------------------------- 1 | // ZlibConstants.cs 2 | // ------------------------------------------------------------------ 3 | // 4 | // Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. 5 | // All rights reserved. 6 | // 7 | // This code module is part of DotNetZip, a zipfile class library. 8 | // 9 | // ------------------------------------------------------------------ 10 | // 11 | // This code is licensed under the Microsoft Public License. 12 | // See the file License.txt for the license details. 13 | // More info on: http://dotnetzip.codeplex.com 14 | // 15 | // ------------------------------------------------------------------ 16 | // 17 | // last saved (in emacs): 18 | // Time-stamp: <2009-November-03 18:50:19> 19 | // 20 | // ------------------------------------------------------------------ 21 | // 22 | // This module defines constants used by the zlib class library. This 23 | // code is derived from the jzlib implementation of zlib, but 24 | // significantly modified. In keeping with the license for jzlib, the 25 | // copyright to that code is included here. 26 | // 27 | // ------------------------------------------------------------------ 28 | // 29 | // Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. 30 | // 31 | // Redistribution and use in source and binary forms, with or without 32 | // modification, are permitted provided that the following conditions are met: 33 | // 34 | // 1. Redistributions of source code must retain the above copyright notice, 35 | // this list of conditions and the following disclaimer. 36 | // 37 | // 2. Redistributions in binary form must reproduce the above copyright 38 | // notice, this list of conditions and the following disclaimer in 39 | // the documentation and/or other materials provided with the distribution. 40 | // 41 | // 3. The names of the authors may not be used to endorse or promote products 42 | // derived from this software without specific prior written permission. 43 | // 44 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 45 | // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 46 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, 47 | // INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 48 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 49 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 50 | // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 51 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 52 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 53 | // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 | // 55 | // ----------------------------------------------------------------------- 56 | // 57 | // This program is based on zlib-1.1.3; credit to authors 58 | // Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) 59 | // and contributors of zlib. 60 | // 61 | // ----------------------------------------------------------------------- 62 | 63 | 64 | using System; 65 | 66 | namespace Ionic.Zlib 67 | { 68 | /// 69 | /// A bunch of constants used in the Zlib interface. 70 | /// 71 | public static class ZlibConstants 72 | { 73 | /// 74 | /// The maximum number of window bits for the Deflate algorithm. 75 | /// 76 | public const int WindowBitsMax = 15; // 32K LZ77 window 77 | 78 | /// 79 | /// The default number of window bits for the Deflate algorithm. 80 | /// 81 | public const int WindowBitsDefault = WindowBitsMax; 82 | 83 | /// 84 | /// indicates everything is A-OK 85 | /// 86 | public const int Z_OK = 0; 87 | 88 | /// 89 | /// Indicates that the last operation reached the end of the stream. 90 | /// 91 | public const int Z_STREAM_END = 1; 92 | 93 | /// 94 | /// The operation ended in need of a dictionary. 95 | /// 96 | public const int Z_NEED_DICT = 2; 97 | 98 | /// 99 | /// There was an error with the stream - not enough data, not open and readable, etc. 100 | /// 101 | public const int Z_STREAM_ERROR = -2; 102 | 103 | /// 104 | /// There was an error with the data - not enough data, bad data, etc. 105 | /// 106 | public const int Z_DATA_ERROR = -3; 107 | 108 | /// 109 | /// There was an error with the working buffer. 110 | /// 111 | public const int Z_BUF_ERROR = -5; 112 | 113 | /// 114 | /// The size of the working buffer used in the ZlibCodec class. Defaults to 8192 bytes. 115 | /// 116 | #if NETCF 117 | public const int WorkingBufferSizeDefault = 8192; 118 | #else 119 | public const int WorkingBufferSizeDefault = 16384; 120 | #endif 121 | /// 122 | /// The minimum size of the working buffer used in the ZlibCodec class. Currently it is 128 bytes. 123 | /// 124 | public const int WorkingBufferSizeMin = 1024; 125 | } 126 | 127 | } 128 | 129 | --------------------------------------------------------------------------------