changeset 1:94e25b786321

Re #311: can't read ZIP file packed by Linux app Archive Manager/File Roller Initial commit of clean SharpZipLib 0860 source. Only change is build paths.
author IBBoard <dev@ibboard.co.uk>
date Sat, 30 Oct 2010 14:03:17 +0000
parents d16ef17fa7bb
children 2a27eaa6a6c7
files AssemblyInfo.cs BZip2/BZip2.cs BZip2/BZip2Constants.cs BZip2/BZip2Exception.cs BZip2/BZip2InputStream.cs BZip2/BZip2OutputStream.cs Checksums/Adler32.cs Checksums/CRC32.cs Checksums/IChecksum.cs Checksums/StrangeCRC.cs Core/FileSystemScanner.cs Core/INameTransform.cs Core/IScanFilter.cs Core/NameFilter.cs Core/PathFilter.cs Core/StreamUtils.cs Core/WindowsPathUtils.cs Encryption/PkzipClassic.cs Encryption/ZipAESStream.cs Encryption/ZipAESTransform.cs GZip/GZIPConstants.cs GZip/GZipException.cs GZip/GzipInputStream.cs GZip/GzipOutputStream.cs ICSharpCode.SharpZLib.csproj Main.cs SharpZipBaseException.cs Tar/InvalidHeaderException.cs Tar/TarArchive.cs Tar/TarBuffer.cs Tar/TarEntry.cs Tar/TarException.cs Tar/TarHeader.cs Tar/TarInputStream.cs Tar/TarOutputStream.cs Zip/Compression/Deflater.cs Zip/Compression/DeflaterConstants.cs Zip/Compression/DeflaterEngine.cs Zip/Compression/DeflaterHuffman.cs Zip/Compression/DeflaterPending.cs Zip/Compression/Inflater.cs Zip/Compression/InflaterDynHeader.cs Zip/Compression/InflaterHuffmanTree.cs Zip/Compression/PendingBuffer.cs Zip/Compression/Streams/DeflaterOutputStream.cs Zip/Compression/Streams/InflaterInputStream.cs Zip/Compression/Streams/OutputWindow.cs Zip/Compression/Streams/StreamManipulator.cs Zip/FastZip.cs Zip/IEntryFactory.cs Zip/WindowsNameTransform.cs Zip/ZipConstants.cs Zip/ZipEntry.cs Zip/ZipEntryFactory.cs Zip/ZipException.cs Zip/ZipExtraData.cs Zip/ZipFile.cs Zip/ZipHelperStream.cs Zip/ZipInputStream.cs Zip/ZipNameTransform.cs Zip/ZipOutputStream.cs
diffstat 61 files changed, 29890 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/AssemblyInfo.cs	Sat Oct 30 14:03:17 2010 +0000
     1.3 @@ -0,0 +1,134 @@
     1.4 +// AssemblyInfo.cs
     1.5 +//
     1.6 +// Copyright (C) 2001 Mike Krueger
     1.7 +// Copyright 2004 John Reilly
     1.8 +//
     1.9 +// This program is free software; you can redistribute it and/or
    1.10 +// modify it under the terms of the GNU General Public License
    1.11 +// as published by the Free Software Foundation; either version 2
    1.12 +// of the License, or (at your option) any later version.
    1.13 +//
    1.14 +// This program is distributed in the hope that it will be useful,
    1.15 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.17 +// GNU General Public License for more details.
    1.18 +//
    1.19 +// You should have received a copy of the GNU General Public License
    1.20 +// along with this program; if not, write to the Free Software
    1.21 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    1.22 +//
    1.23 +// Linking this library statically or dynamically with other modules is
    1.24 +// making a combined work based on this library.  Thus, the terms and
    1.25 +// conditions of the GNU General Public License cover the whole
    1.26 +// combination.
    1.27 +// 
    1.28 +// As a special exception, the copyright holders of this library give you
    1.29 +// permission to link this library with independent modules to produce an
    1.30 +// executable, regardless of the license terms of these independent
    1.31 +// modules, and to copy and distribute the resulting executable under
    1.32 +// terms of your choice, provided that you also meet, for each linked
    1.33 +// independent module, the terms and conditions of the license of that
    1.34 +// module.  An independent module is a module which is not derived from
    1.35 +// or based on this library.  If you modify this library, you may extend
    1.36 +// this exception to your version of the library, but you are not
    1.37 +// obligated to do so.  If you do not wish to do so, delete this
    1.38 +// exception statement from your version.
    1.39 +
    1.40 +using System;
    1.41 +using System.Reflection;
    1.42 +using System.Runtime.CompilerServices;
    1.43 +using System.Runtime.InteropServices;
    1.44 +
    1.45 +#if (NET_1_0)
    1.46 +[assembly: AssemblyTitle("SharpZipLib for .NET Framework 1.0")]
    1.47 +#elif (NET_1_1)
    1.48 +[assembly: AssemblyTitle("SharpZipLib for .NET Framework 1.1")]
    1.49 +#elif (NET_2_0)
    1.50 +[assembly: AssemblyTitle("SharpZipLib for .NET Framework 2.0")]
    1.51 +#elif (NET_3_0)
    1.52 +[assembly: AssemblyTitle("SharpZipLib for .NET Framework 3.0")]
    1.53 +#elif (NET_3_5)
    1.54 +[assembly: AssemblyTitle("SharpZipLib for .NET Framework 3.5")]
    1.55 +#elif (NETCF_1_0)
    1.56 +[assembly: AssemblyTitle("SharpZipLib for .NET Compact Framework 1.0")]
    1.57 +#elif (NETCF_2_0)
    1.58 +[assembly: AssemblyTitle("SharpZipLib for .NET Compact Framework 2.0")]
    1.59 +#elif (MONO_1_0)
    1.60 +[assembly: AssemblyTitle("SharpZipLib for Mono 1.0")]
    1.61 +#elif (MONO_2_0)
    1.62 +[assembly: AssemblyTitle("SharpZipLib for Mono 2.0")]
    1.63 +#else
    1.64 +[assembly: AssemblyTitle("SharpZipLibrary unlabelled version")]
    1.65 +#endif
    1.66 +
    1.67 +[assembly: AssemblyDescription("A free C# compression library")]
    1.68 +[assembly: AssemblyProduct("#ZipLibrary")]
    1.69 +[assembly: AssemblyDefaultAlias("SharpZipLib")]
    1.70 +[assembly: AssemblyCulture("")]
    1.71 +
    1.72 +#if DEBUG
    1.73 +[assembly: AssemblyConfiguration("Debug")]
    1.74 +#else
    1.75 +[assembly: AssemblyConfiguration("Release")]
    1.76 +#endif
    1.77 +
    1.78 +
    1.79 +[assembly: AssemblyCompany("ICSharpCode.net")]
    1.80 +[assembly: AssemblyCopyright("Copyright 2001-2010 Mike Krueger, John Reilly")]
    1.81 +[assembly: AssemblyTrademark("Copyright 2001-2010 Mike Krueger, John Reilly")]
    1.82 +
    1.83 +[assembly: AssemblyVersion("0.86.0.518")]
    1.84 +[assembly: AssemblyInformationalVersionAttribute("0.86.0")]
    1.85 +
    1.86 +
    1.87 +[assembly: CLSCompliant(true)]
    1.88 +
    1.89 +#if (!NETCF)
    1.90 +//
    1.91 +// If #Zip is strongly named it still allows partially trusted callers
    1.92 +//
    1.93 +[assembly: System.Security.AllowPartiallyTrustedCallers]
    1.94 +#endif
    1.95 +
    1.96 +// Setting ComVisible to false makes the types in this assembly not visible 
    1.97 +// to COM components.  If you need to access a type in this assembly from 
    1.98 +// COM, set the ComVisible attribute to true on that type.
    1.99 +[assembly: ComVisible(false)]
   1.100 +
   1.101 +//
   1.102 +// In order to sign your assembly you must specify a key to use. Refer to the 
   1.103 +// Microsoft .NET Framework documentation for more information on assembly signing.
   1.104 +//
   1.105 +// Use the attributes below to control which key is used for signing. 
   1.106 +//
   1.107 +// Notes: 
   1.108 +//   (*) If no key is specified, the assembly is not signed.
   1.109 +//   (*) KeyName refers to a key that has been installed in the Crypto Service
   1.110 +//       Provider (CSP) on your machine. KeyFile refers to a file which contains
   1.111 +//       a key.
   1.112 +//   (*) If the KeyFile and the KeyName values are both specified, the 
   1.113 +//       following processing occurs:
   1.114 +//       (1) If the KeyName can be found in the CSP, that key is used.
   1.115 +//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
   1.116 +//           in the KeyFile is installed into the CSP and used.
   1.117 +//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
   1.118 +//       When specifying the KeyFile, the location of the KeyFile should be
   1.119 +//       relative to the project output directory which is
   1.120 +//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
   1.121 +//       located in the project directory, you would specify the AssemblyKeyFile 
   1.122 +//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
   1.123 +//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
   1.124 +//       documentation for more information on this.
   1.125 +//
   1.126 +#if (CLI_1_0 || NET_1_0 || NET_1_1 || NETCF_1_0 || SSCLI)
   1.127 +[assembly: AssemblyDelaySign(false)]
   1.128 +#if VSTUDIO
   1.129 +[assembly: AssemblyKeyFile("../../ICSharpCode.SharpZipLib.key")]
   1.130 +#elif AUTOBUILD
   1.131 +[assembly: AssemblyKeyFile("ICSharpCode.SharpZipLib.key")]
   1.132 +#else
   1.133 +[assembly: AssemblyKeyFile("../ICSharpCode.SharpZipLib.key")]
   1.134 +#endif
   1.135 +#endif
   1.136 +
   1.137 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/BZip2/BZip2.cs	Sat Oct 30 14:03:17 2010 +0000
     2.3 @@ -0,0 +1,105 @@
     2.4 +// BZip2.cs
     2.5 +//
     2.6 +// Copyright (C) 2010 David Pierson
     2.7 +//
     2.8 +// This program is free software; you can redistribute it and/or
     2.9 +// modify it under the terms of the GNU General Public License
    2.10 +// as published by the Free Software Foundation; either version 2
    2.11 +// of the License, or (at your option) any later version.
    2.12 +//
    2.13 +// This program is distributed in the hope that it will be useful,
    2.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16 +// GNU General Public License for more details.
    2.17 +//
    2.18 +// You should have received a copy of the GNU General Public License
    2.19 +// along with this program; if not, write to the Free Software
    2.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    2.21 +//
    2.22 +// Linking this library statically or dynamically with other modules is
    2.23 +// making a combined work based on this library.  Thus, the terms and
    2.24 +// conditions of the GNU General Public License cover the whole
    2.25 +// combination.
    2.26 +// 
    2.27 +// As a special exception, the copyright holders of this library give you
    2.28 +// permission to link this library with independent modules to produce an
    2.29 +// executable, regardless of the license terms of these independent
    2.30 +// modules, and to copy and distribute the resulting executable under
    2.31 +// terms of your choice, provided that you also meet, for each linked
    2.32 +// independent module, the terms and conditions of the license of that
    2.33 +// module.  An independent module is a module which is not derived from
    2.34 +// or based on this library.  If you modify this library, you may extend
    2.35 +// this exception to your version of the library, but you are not
    2.36 +// obligated to do so.  If you do not wish to do so, delete this
    2.37 +// exception statement from your version.
    2.38 +
    2.39 +// Suppress this in CF and 1.1, not needed. Static classes introduced in C# version 2.0
    2.40 +#if !NETCF_2_0 && !NET_1_1
    2.41 +
    2.42 +using System;
    2.43 +using System.IO;
    2.44 +
    2.45 +namespace ICSharpCode.SharpZipLib.BZip2 {
    2.46 +	
    2.47 +	/// <summary>
    2.48 +	/// An example class to demonstrate compression and decompression of BZip2 streams.
    2.49 +	/// </summary>
    2.50 +	public static class BZip2
    2.51 +	{
    2.52 +		/// <summary>
    2.53 +		/// Decompress the <paramref name="inStream">input</paramref> writing 
    2.54 +		/// uncompressed data to the <paramref name="outStream">output stream</paramref>
    2.55 +		/// </summary>
    2.56 +		/// <param name="inStream">The readable stream containing data to decompress.</param>
    2.57 +		/// <param name="outStream">The output stream to receive the decompressed data.</param>
    2.58 +		/// <param name="isStreamOwner">Both streams are closed on completion if true.</param>
    2.59 +		public static void Decompress(Stream inStream, Stream outStream, bool isStreamOwner) 
    2.60 +		{
    2.61 +			if (inStream == null || outStream == null) {
    2.62 +				throw new Exception("Null Stream");
    2.63 +			}
    2.64 +			
    2.65 +			try {
    2.66 +				using (BZip2InputStream bzipInput = new BZip2InputStream(inStream)) {
    2.67 +					bzipInput.IsStreamOwner = isStreamOwner;
    2.68 +					Core.StreamUtils.Copy(bzipInput, outStream, new byte[4096]);
    2.69 +				}
    2.70 +			} finally {
    2.71 +				if (isStreamOwner) {
    2.72 +					// inStream is closed by the BZip2InputStream if stream owner
    2.73 +					outStream.Close();
    2.74 +				}
    2.75 +			}
    2.76 +		}
    2.77 +		
    2.78 +		/// <summary>
    2.79 +		/// Compress the <paramref name="inStream">input stream</paramref> sending 
    2.80 +		/// result data to <paramref name="outStream">output stream</paramref>
    2.81 +		/// </summary>
    2.82 +		/// <param name="inStream">The readable stream to compress.</param>
    2.83 +		/// <param name="outStream">The output stream to receive the compressed data.</param>
    2.84 +		/// <param name="isStreamOwner">Both streams are closed on completion if true.</param>
    2.85 +		/// <param name="level">Block size acts as compression level (1 to 9) with 1 giving 
    2.86 +		/// the lowest compression and 9 the highest.</param>
    2.87 +		public static void Compress(Stream inStream, Stream outStream, bool isStreamOwner, int level) 
    2.88 +		{
    2.89 +			if (inStream == null || outStream == null) {
    2.90 +				throw new Exception("Null Stream");
    2.91 +			}
    2.92 +
    2.93 +			try {
    2.94 +				using (BZip2OutputStream bzipOutput = new BZip2OutputStream(outStream, level)) {
    2.95 +					bzipOutput.IsStreamOwner = isStreamOwner;
    2.96 +					Core.StreamUtils.Copy(inStream, bzipOutput, new byte[4096]);
    2.97 +				}
    2.98 +			} finally {
    2.99 +				if (isStreamOwner) {
   2.100 +					// outStream is closed by the BZip2OutputStream if stream owner
   2.101 +					inStream.Close();
   2.102 +				}
   2.103 +			}
   2.104 +		}
   2.105 +
   2.106 +	}
   2.107 +}
   2.108 +#endif
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/BZip2/BZip2Constants.cs	Sat Oct 30 14:03:17 2010 +0000
     3.3 @@ -0,0 +1,197 @@
     3.4 +// BZip2Constants.cs
     3.5 +// Copyright (C) 2001 Mike Krueger
     3.6 +//
     3.7 +// This program is free software; you can redistribute it and/or
     3.8 +// modify it under the terms of the GNU General Public License
     3.9 +// as published by the Free Software Foundation; either version 2
    3.10 +// of the License, or (at your option) any later version.
    3.11 +//
    3.12 +// This program is distributed in the hope that it will be useful,
    3.13 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 +// GNU General Public License for more details.
    3.16 +//
    3.17 +// You should have received a copy of the GNU General Public License
    3.18 +// along with this program; if not, write to the Free Software
    3.19 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    3.20 +//
    3.21 +// Linking this library statically or dynamically with other modules is
    3.22 +// making a combined work based on this library.  Thus, the terms and
    3.23 +// conditions of the GNU General Public License cover the whole
    3.24 +// combination.
    3.25 +// 
    3.26 +// As a special exception, the copyright holders of this library give you
    3.27 +// permission to link this library with independent modules to produce an
    3.28 +// executable, regardless of the license terms of these independent
    3.29 +// modules, and to copy and distribute the resulting executable under
    3.30 +// terms of your choice, provided that you also meet, for each linked
    3.31 +// independent module, the terms and conditions of the license of that
    3.32 +// module.  An independent module is a module which is not derived from
    3.33 +// or based on this library.  If you modify this library, you may extend
    3.34 +// this exception to your version of the library, but you are not
    3.35 +// obligated to do so.  If you do not wish to do so, delete this
    3.36 +// exception statement from your version.
    3.37 +
    3.38 +namespace ICSharpCode.SharpZipLib.BZip2 
    3.39 +{
    3.40 +	
    3.41 +	/// <summary>
    3.42 +	/// Defines internal values for both compression and decompression
    3.43 +	/// </summary>
    3.44 +	internal sealed class BZip2Constants
    3.45 +	{
    3.46 +		/// <summary>
    3.47 +		/// Random numbers used to randomise repetitive blocks
    3.48 +		/// </summary>
    3.49 +		public readonly static int[] RandomNumbers = {
    3.50 +			619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
    3.51 +			985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
    3.52 +			733, 859, 335, 708, 621, 574,  73, 654, 730, 472,
    3.53 +			419, 436, 278, 496, 867, 210, 399, 680, 480,  51,
    3.54 +			878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
    3.55 +			862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
    3.56 +			150, 238,  59, 379, 684, 877, 625, 169, 643, 105,
    3.57 +			170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
    3.58 +			 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
    3.59 +			909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
    3.60 +			641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
    3.61 +			161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
    3.62 +			382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
    3.63 +			 98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
    3.64 +			227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
    3.65 +			469,  68, 770, 919, 190, 373, 294, 822, 808, 206,
    3.66 +			184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
    3.67 +			715,  67, 618, 276, 204, 918, 873, 777, 604, 560,
    3.68 +			951, 160, 578, 722,  79, 804,  96, 409, 713, 940,
    3.69 +			652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
    3.70 +			645, 863, 803, 350, 139,  93, 354,  99, 820, 908,
    3.71 +			609, 772, 154, 274, 580, 184,  79, 626, 630, 742,
    3.72 +			653, 282, 762, 623, 680,  81, 927, 626, 789, 125,
    3.73 +			411, 521, 938, 300, 821,  78, 343, 175, 128, 250,
    3.74 +			170, 774, 972, 275, 999, 639, 495,  78, 352, 126,
    3.75 +			857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
    3.76 +			669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
    3.77 +			944, 375, 748,  52, 600, 747, 642, 182, 862,  81,
    3.78 +			344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
    3.79 +			897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
    3.80 +			433, 837, 553, 268, 926, 240, 102, 654, 459,  51,
    3.81 +			686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
    3.82 +			946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
    3.83 +			978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
    3.84 +			680, 879, 194, 572, 640, 724, 926,  56, 204, 700,
    3.85 +			707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
    3.86 +			297,  59,  87, 824, 713, 663, 412, 693, 342, 606,
    3.87 +			134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
    3.88 +			343,  97, 430, 751, 497, 314, 983, 374, 822, 928,
    3.89 +			140, 206,  73, 263, 980, 736, 876, 478, 430, 305,
    3.90 +			170, 514, 364, 692, 829,  82, 855, 953, 676, 246,
    3.91 +			369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
    3.92 +			804, 378, 215, 828, 592, 281, 565, 555, 710,  82,
    3.93 +			896, 831, 547, 261, 524, 462, 293, 465, 502,  56,
    3.94 +			661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
    3.95 +			768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
    3.96 +			 61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
    3.97 +			372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
    3.98 +			780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
    3.99 +			920, 176, 193, 713, 857, 265, 203,  50, 668, 108,
   3.100 +			645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
   3.101 +			936, 638
   3.102 +		};
   3.103 +
   3.104 +		/// <summary>
   3.105 +		/// When multiplied by compression parameter (1-9) gives the block size for compression
   3.106 +		/// 9 gives the best compression but uses the most memory.
   3.107 +		/// </summary>		
   3.108 +		public const int BaseBlockSize = 100000;
   3.109 +		
   3.110 +		/// <summary>
   3.111 +		/// Backend constant
   3.112 +		/// </summary>
   3.113 +		public const int MaximumAlphaSize = 258;
   3.114 +		
   3.115 +		/// <summary>
   3.116 +		/// Backend constant
   3.117 +		/// </summary>
   3.118 +		public const int MaximumCodeLength = 23;
   3.119 +		
   3.120 +		/// <summary>
   3.121 +		/// Backend constant
   3.122 +		/// </summary>
   3.123 +		public const int RunA = 0;
   3.124 +		
   3.125 +		/// <summary>
   3.126 +		/// Backend constant
   3.127 +		/// </summary>
   3.128 +		public const int RunB = 1;
   3.129 +		
   3.130 +		/// <summary>
   3.131 +		/// Backend constant
   3.132 +		/// </summary>
   3.133 +		public const int GroupCount = 6;
   3.134 +		
   3.135 +		/// <summary>
   3.136 +		/// Backend constant
   3.137 +		/// </summary>
   3.138 +		public const int GroupSize = 50;
   3.139 +		
   3.140 +		/// <summary>
   3.141 +		/// Backend constant
   3.142 +		/// </summary>
   3.143 +		public const int NumberOfIterations = 4;
   3.144 +		
   3.145 +		/// <summary>
   3.146 +		/// Backend constant
   3.147 +		/// </summary>
   3.148 +		public const int MaximumSelectors = (2 + (900000 / GroupSize));
   3.149 +		
   3.150 +		/// <summary>
   3.151 +		/// Backend constant
   3.152 +		/// </summary>
   3.153 +		public const int OvershootBytes = 20;
   3.154 +		
   3.155 +		private BZip2Constants()
   3.156 +		{
   3.157 +		}
   3.158 +	}
   3.159 +}
   3.160 +	
   3.161 +/* This file was derived from a file containing this license:
   3.162 + * 
   3.163 + * This file is a part of bzip2 and/or libbzip2, a program and
   3.164 + * library for lossless, block-sorting data compression.
   3.165 + * 
   3.166 + * Copyright (C) 1996-1998 Julian R Seward.  All rights reserved.
   3.167 + * 
   3.168 + * Redistribution and use in source and binary forms, with or without
   3.169 + * modification, are permitted provided that the following conditions
   3.170 + * are met:
   3.171 + * 
   3.172 + * 1. Redistributions of source code must retain the above copyright
   3.173 + * notice, this list of conditions and the following disclaimer.
   3.174 + * 
   3.175 + * 2. The origin of this software must not be misrepresented; you must 
   3.176 + * not claim that you wrote the original software.  If you use this 
   3.177 + * software in a product, an acknowledgment in the product 
   3.178 + * documentation would be appreciated but is not required.
   3.179 + * 
   3.180 + * 3. Altered source versions must be plainly marked as such, and must
   3.181 + * not be misrepresented as being the original software.
   3.182 + * 
   3.183 + * 4. The name of the author may not be used to endorse or promote 
   3.184 + * products derived from this software without specific prior written 
   3.185 + * permission.
   3.186 + * 
   3.187 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   3.188 + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   3.189 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   3.190 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
   3.191 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   3.192 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   3.193 + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   3.194 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   3.195 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   3.196 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   3.197 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   3.198 + * 
   3.199 + * Java version ported by Keiron Liddle, Aftex Software <keiron@aftexsw.com> 1999-2001
   3.200 + */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/BZip2/BZip2Exception.cs	Sat Oct 30 14:03:17 2010 +0000
     4.3 @@ -0,0 +1,90 @@
     4.4 +// BZip2.cs
     4.5 +//
     4.6 +// Copyright 2004 John Reilly
     4.7 +//
     4.8 +// This program is free software; you can redistribute it and/or
     4.9 +// modify it under the terms of the GNU General Public License
    4.10 +// as published by the Free Software Foundation; either version 2
    4.11 +// of the License, or (at your option) any later version.
    4.12 +//
    4.13 +// This program is distributed in the hope that it will be useful,
    4.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.16 +// GNU General Public License for more details.
    4.17 +//
    4.18 +// You should have received a copy of the GNU General Public License
    4.19 +// along with this program; if not, write to the Free Software
    4.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    4.21 +//
    4.22 +// Linking this library statically or dynamically with other modules is
    4.23 +// making a combined work based on this library.  Thus, the terms and
    4.24 +// conditions of the GNU General Public License cover the whole
    4.25 +// combination.
    4.26 +// 
    4.27 +// As a special exception, the copyright holders of this library give you
    4.28 +// permission to link this library with independent modules to produce an
    4.29 +// executable, regardless of the license terms of these independent
    4.30 +// modules, and to copy and distribute the resulting executable under
    4.31 +// terms of your choice, provided that you also meet, for each linked
    4.32 +// independent module, the terms and conditions of the license of that
    4.33 +// module.  An independent module is a module which is not derived from
    4.34 +// or based on this library.  If you modify this library, you may extend
    4.35 +// this exception to your version of the library, but you are not
    4.36 +// obligated to do so.  If you do not wish to do so, delete this
    4.37 +// exception statement from your version.
    4.38 +
    4.39 +using System;
    4.40 +
    4.41 +#if !NETCF_1_0 && !NETCF_2_0
    4.42 +using System.Runtime.Serialization;
    4.43 +#endif
    4.44 +
    4.45 +namespace ICSharpCode.SharpZipLib.BZip2
    4.46 +{
    4.47 +	/// <summary>
    4.48 +	/// BZip2Exception represents exceptions specific to Bzip2 algorithm
    4.49 +	/// </summary>
    4.50 +#if !NETCF_1_0 && !NETCF_2_0
    4.51 +	[Serializable]
    4.52 +#endif	
    4.53 +	public class BZip2Exception : SharpZipBaseException
    4.54 +	{
    4.55 +
    4.56 +#if !NETCF_1_0 && !NETCF_2_0
    4.57 +		/// <summary>
    4.58 +		/// Deserialization constructor 
    4.59 +		/// </summary>
    4.60 +		/// <param name="info"><see cref="SerializationInfo"/> for this constructor</param>
    4.61 +		/// <param name="context"><see cref="StreamingContext"/> for this constructor</param>
    4.62 +		protected BZip2Exception(SerializationInfo info, StreamingContext context)
    4.63 +			: base(info, context)
    4.64 +
    4.65 +		{
    4.66 +		}
    4.67 +#endif
    4.68 +		/// <summary>
    4.69 +		/// Initialise a new instance of BZip2Exception.
    4.70 +		/// </summary>
    4.71 +		public BZip2Exception()
    4.72 +		{
    4.73 +		}
    4.74 +		
    4.75 +		/// <summary>
    4.76 +		/// Initialise a new instance of BZip2Exception with its message set to message.
    4.77 +		/// </summary>
    4.78 +		/// <param name="message">The message describing the error.</param>
    4.79 +		public BZip2Exception(string message) : base(message)
    4.80 +		{
    4.81 +		}
    4.82 +
    4.83 +		/// <summary>
    4.84 +		/// Initialise an instance of BZip2Exception
    4.85 +		/// </summary>
    4.86 +		/// <param name="message">A message describing the error.</param>
    4.87 +		/// <param name="exception">The exception that is the cause of the current exception.</param>
    4.88 +		public BZip2Exception(string message, Exception exception)
    4.89 +			: base(message, exception)
    4.90 +		{
    4.91 +		}
    4.92 +	}
    4.93 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/BZip2/BZip2InputStream.cs	Sat Oct 30 14:03:17 2010 +0000
     5.3 @@ -0,0 +1,1003 @@
     5.4 +// BZip2InputStream.cs
     5.5 +//
     5.6 +// Copyright (C) 2001 Mike Krueger
     5.7 +//
     5.8 +// This program is free software; you can redistribute it and/or
     5.9 +// modify it under the terms of the GNU General Public License
    5.10 +// as published by the Free Software Foundation; either version 2
    5.11 +// of the License, or (at your option) any later version.
    5.12 +//
    5.13 +// This program is distributed in the hope that it will be useful,
    5.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.16 +// GNU General Public License for more details.
    5.17 +//
    5.18 +// You should have received a copy of the GNU General Public License
    5.19 +// along with this program; if not, write to the Free Software
    5.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    5.21 +//
    5.22 +// Linking this library statically or dynamically with other modules is
    5.23 +// making a combined work based on this library.  Thus, the terms and
    5.24 +// conditions of the GNU General Public License cover the whole
    5.25 +// combination.
    5.26 +// 
    5.27 +// As a special exception, the copyright holders of this library give you
    5.28 +// permission to link this library with independent modules to produce an
    5.29 +// executable, regardless of the license terms of these independent
    5.30 +// modules, and to copy and distribute the resulting executable under
    5.31 +// terms of your choice, provided that you also meet, for each linked
    5.32 +// independent module, the terms and conditions of the license of that
    5.33 +// module.  An independent module is a module which is not derived from
    5.34 +// or based on this library.  If you modify this library, you may extend
    5.35 +// this exception to your version of the library, but you are not
    5.36 +// obligated to do so.  If you do not wish to do so, delete this
    5.37 +// exception statement from your version.
    5.38 +
    5.39 +using System;
    5.40 +using System.IO;
    5.41 +
    5.42 +using ICSharpCode.SharpZipLib.Checksums;
    5.43 +
    5.44 +namespace ICSharpCode.SharpZipLib.BZip2 
    5.45 +{
    5.46 +	
    5.47 +	/// <summary>
    5.48 +	/// An input stream that decompresses files in the BZip2 format 
    5.49 +	/// </summary>
    5.50 +	public class BZip2InputStream : Stream
    5.51 +	{
    5.52 +		#region Constants
    5.53 +		const int START_BLOCK_STATE = 1;
    5.54 +		const int RAND_PART_A_STATE = 2;
    5.55 +		const int RAND_PART_B_STATE = 3;
    5.56 +		const int RAND_PART_C_STATE = 4;
    5.57 +		const int NO_RAND_PART_A_STATE = 5;
    5.58 +		const int NO_RAND_PART_B_STATE = 6;
    5.59 +		const int NO_RAND_PART_C_STATE = 7;
    5.60 +		#endregion
    5.61 +		#region Constructors
    5.62 +		/// <summary>
    5.63 +		/// Construct instance for reading from stream
    5.64 +		/// </summary>
    5.65 +		/// <param name="stream">Data source</param>
    5.66 +		public BZip2InputStream(Stream stream) 
    5.67 +		{
    5.68 +			// init arrays
    5.69 +			for (int i = 0; i < BZip2Constants.GroupCount; ++i) 
    5.70 +			{
    5.71 +				limit[i] = new int[BZip2Constants.MaximumAlphaSize];
    5.72 +				baseArray[i]  = new int[BZip2Constants.MaximumAlphaSize];
    5.73 +				perm[i]  = new int[BZip2Constants.MaximumAlphaSize];
    5.74 +			}
    5.75 +			
    5.76 +			BsSetStream(stream);
    5.77 +			Initialize();
    5.78 +			InitBlock();
    5.79 +			SetupBlock();
    5.80 +		}
    5.81 +		
    5.82 +		#endregion
    5.83 +
    5.84 +		/// <summary>
    5.85 +		/// Get/set flag indicating ownership of underlying stream.
    5.86 +		/// When the flag is true <see cref="Close"></see> will close the underlying stream also.
    5.87 +		/// </summary>
    5.88 +		public bool IsStreamOwner
    5.89 +		{
    5.90 +			get { return isStreamOwner; }
    5.91 +			set { isStreamOwner = value; }
    5.92 +		}
    5.93 +		
    5.94 +
    5.95 +		#region Stream Overrides
    5.96 +		/// <summary>
    5.97 +		/// Gets a value indicating if the stream supports reading
    5.98 +		/// </summary>
    5.99 +		public override bool CanRead 
   5.100 +		{
   5.101 +			get {
   5.102 +				return baseStream.CanRead;
   5.103 +			}
   5.104 +		}
   5.105 +		
   5.106 +		/// <summary>
   5.107 +		/// Gets a value indicating whether the current stream supports seeking.
   5.108 +		/// </summary>
   5.109 +		public override bool CanSeek {
   5.110 +			get {
   5.111 +				return baseStream.CanSeek;
   5.112 +			}
   5.113 +		}
   5.114 +		
   5.115 +		/// <summary>
   5.116 +		/// Gets a value indicating whether the current stream supports writing.
   5.117 +		/// This property always returns false
   5.118 +		/// </summary>
   5.119 +		public override bool CanWrite {
   5.120 +			get {
   5.121 +				return false;
   5.122 +			}
   5.123 +		}
   5.124 +		
   5.125 +		/// <summary>
   5.126 +		/// Gets the length in bytes of the stream.
   5.127 +		/// </summary>
   5.128 +		public override long Length {
   5.129 +			get {
   5.130 +				return baseStream.Length;
   5.131 +			}
   5.132 +		}
   5.133 +		
   5.134 +		/// <summary>
   5.135 +		/// Gets or sets the streams position.
   5.136 +		/// Setting the position is not supported and will throw a NotSupportException
   5.137 +		/// </summary>
   5.138 +		/// <exception cref="NotSupportedException">Any attempt to set the position</exception>
   5.139 +		public override long Position {
   5.140 +			get {
   5.141 +				return baseStream.Position;
   5.142 +			}
   5.143 +			set {
   5.144 +				throw new NotSupportedException("BZip2InputStream position cannot be set");
   5.145 +			}
   5.146 +		}
   5.147 +		
   5.148 +		/// <summary>
   5.149 +		/// Flushes the stream.
   5.150 +		/// </summary>
   5.151 +		public override void Flush()
   5.152 +		{
   5.153 +			if (baseStream != null) {
   5.154 +				baseStream.Flush();
   5.155 +			}
   5.156 +		}
   5.157 +		
   5.158 +		/// <summary>
   5.159 +		/// Set the streams position.  This operation is not supported and will throw a NotSupportedException
   5.160 +		/// </summary>
   5.161 +		/// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param>
   5.162 +		/// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the new position.</param>
   5.163 +		/// <returns>The new position of the stream.</returns>
   5.164 +		/// <exception cref="NotSupportedException">Any access</exception>
   5.165 +		public override long Seek(long offset, SeekOrigin origin)
   5.166 +		{
   5.167 +			throw new NotSupportedException("BZip2InputStream Seek not supported");
   5.168 +		}
   5.169 +		
   5.170 +		/// <summary>
   5.171 +		/// Sets the length of this stream to the given value.
   5.172 +		/// This operation is not supported and will throw a NotSupportedExceptionortedException
   5.173 +		/// </summary>
   5.174 +		/// <param name="value">The new length for the stream.</param>
   5.175 +		/// <exception cref="NotSupportedException">Any access</exception>
   5.176 +		public override void SetLength(long value)
   5.177 +		{
   5.178 +			throw new NotSupportedException("BZip2InputStream SetLength not supported");
   5.179 +		}
   5.180 +		
   5.181 +		/// <summary>
   5.182 +		/// Writes a block of bytes to this stream using data from a buffer.
   5.183 +		/// This operation is not supported and will throw a NotSupportedException
   5.184 +		/// </summary>
   5.185 +		/// <param name="buffer">The buffer to source data from.</param>
   5.186 +		/// <param name="offset">The offset to start obtaining data from.</param>
   5.187 +		/// <param name="count">The number of bytes of data to write.</param>
   5.188 +		/// <exception cref="NotSupportedException">Any access</exception>
   5.189 +		public override void Write(byte[] buffer, int offset, int count)
   5.190 +		{
   5.191 +			throw new NotSupportedException("BZip2InputStream Write not supported");
   5.192 +		}
   5.193 +		
   5.194 +		/// <summary>
   5.195 +		/// Writes a byte to the current position in the file stream.
   5.196 +		/// This operation is not supported and will throw a NotSupportedException
   5.197 +		/// </summary>
   5.198 +		/// <param name="value">The value to write.</param>
   5.199 +		/// <exception cref="NotSupportedException">Any access</exception>
   5.200 +		public override void WriteByte(byte value)
   5.201 +		{
   5.202 +			throw new NotSupportedException("BZip2InputStream WriteByte not supported");
   5.203 +		}
   5.204 +		
   5.205 +		/// <summary>
   5.206 +		/// Read a sequence of bytes and advances the read position by one byte.
   5.207 +		/// </summary>
   5.208 +		/// <param name="buffer">Array of bytes to store values in</param>
   5.209 +		/// <param name="offset">Offset in array to begin storing data</param>
   5.210 +		/// <param name="count">The maximum number of bytes to read</param>
   5.211 +		/// <returns>The total number of bytes read into the buffer. This might be less
   5.212 +		/// than the number of bytes requested if that number of bytes are not 
   5.213 +		/// currently available or zero if the end of the stream is reached.
   5.214 +		/// </returns>
   5.215 +		public override int Read(byte[] buffer, int offset, int count)
   5.216 +		{
   5.217 +			if ( buffer == null )
   5.218 +			{
   5.219 +				throw new ArgumentNullException("buffer");
   5.220 +			}
   5.221 +
   5.222 +			for (int i = 0; i < count; ++i) {
   5.223 +				int rb = ReadByte();
   5.224 +				if (rb == -1) {
   5.225 +					return i;
   5.226 +				}
   5.227 +				buffer[offset + i] = (byte)rb;
   5.228 +			}
   5.229 +			return count;
   5.230 +		}
   5.231 +		
   5.232 +		/// <summary>
   5.233 +		/// Closes the stream, releasing any associated resources.
   5.234 +		/// </summary>
   5.235 +		public override void Close()
   5.236 +		{
   5.237 +			if ( IsStreamOwner && (baseStream != null) ) {
   5.238 +				baseStream.Close();
   5.239 +			}
   5.240 +		}
   5.241 +		/// <summary>
   5.242 +		/// Read a byte from stream advancing position
   5.243 +		/// </summary>
   5.244 +		/// <returns>byte read or -1 on end of stream</returns>
   5.245 +		public override int ReadByte()
   5.246 +		{
   5.247 +			if (streamEnd) 
   5.248 +			{
   5.249 +				return -1; // ok
   5.250 +			}
   5.251 +			
   5.252 +			int retChar = currentChar;
   5.253 +			switch (currentState) 
   5.254 +			{
   5.255 +				case RAND_PART_B_STATE:
   5.256 +					SetupRandPartB();
   5.257 +					break;
   5.258 +				case RAND_PART_C_STATE:
   5.259 +					SetupRandPartC();
   5.260 +					break;
   5.261 +				case NO_RAND_PART_B_STATE:
   5.262 +					SetupNoRandPartB();
   5.263 +					break;
   5.264 +				case NO_RAND_PART_C_STATE:
   5.265 +					SetupNoRandPartC();
   5.266 +					break;
   5.267 +				case START_BLOCK_STATE:
   5.268 +				case NO_RAND_PART_A_STATE:
   5.269 +				case RAND_PART_A_STATE:
   5.270 +					break;
   5.271 +				default:
   5.272 +					break;
   5.273 +			}
   5.274 +			return retChar;
   5.275 +		}
   5.276 +		
   5.277 +		#endregion
   5.278 +
   5.279 +		void MakeMaps() 
   5.280 +		{
   5.281 +			nInUse = 0;
   5.282 +			for (int i = 0; i < 256; ++i) {
   5.283 +				if (inUse[i]) {
   5.284 +					seqToUnseq[nInUse] = (byte)i;
   5.285 +					unseqToSeq[i] = (byte)nInUse;
   5.286 +					nInUse++;
   5.287 +				}
   5.288 +			}
   5.289 +		}
   5.290 +				
   5.291 +		void Initialize() 
   5.292 +		{
   5.293 +			char magic1 = BsGetUChar();
   5.294 +			char magic2 = BsGetUChar();
   5.295 +			
   5.296 +			char magic3 = BsGetUChar();
   5.297 +			char magic4 = BsGetUChar();
   5.298 +			
   5.299 +			if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') {
   5.300 +				streamEnd = true;
   5.301 +				return;
   5.302 +			}
   5.303 +			
   5.304 +			SetDecompressStructureSizes(magic4 - '0');
   5.305 +			computedCombinedCRC = 0;
   5.306 +		}
   5.307 +		
   5.308 +		void InitBlock() 
   5.309 +		{
   5.310 +			char magic1 = BsGetUChar();
   5.311 +			char magic2 = BsGetUChar();
   5.312 +			char magic3 = BsGetUChar();
   5.313 +			char magic4 = BsGetUChar();
   5.314 +			char magic5 = BsGetUChar();
   5.315 +			char magic6 = BsGetUChar();
   5.316 +			
   5.317 +			if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
   5.318 +				Complete();
   5.319 +				return;
   5.320 +			}
   5.321 +			
   5.322 +			if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
   5.323 +				BadBlockHeader();
   5.324 +				streamEnd = true;
   5.325 +				return;
   5.326 +			}
   5.327 +			
   5.328 +			storedBlockCRC  = BsGetInt32();
   5.329 +			
   5.330 +			blockRandomised = (BsR(1) == 1);
   5.331 +			
   5.332 +			GetAndMoveToFrontDecode();
   5.333 +			
   5.334 +			mCrc.Reset();
   5.335 +			currentState = START_BLOCK_STATE;
   5.336 +		}
   5.337 +		
   5.338 +		void EndBlock() 
   5.339 +		{
   5.340 +			computedBlockCRC = (int)mCrc.Value;
   5.341 +			
   5.342 +			// -- A bad CRC is considered a fatal error. --
   5.343 +			if (storedBlockCRC != computedBlockCRC) {
   5.344 +				CrcError();
   5.345 +			}
   5.346 +			
   5.347 +			// 1528150659
   5.348 +			computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31);
   5.349 +			computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC;
   5.350 +		}
   5.351 +		
   5.352 +		void Complete() 
   5.353 +		{
   5.354 +			storedCombinedCRC = BsGetInt32();
   5.355 +			if (storedCombinedCRC != (int)computedCombinedCRC) {
   5.356 +				CrcError();
   5.357 +			}
   5.358 +			
   5.359 +			streamEnd = true;
   5.360 +		}
   5.361 +		
   5.362 +		void BsSetStream(Stream stream) 
   5.363 +		{
   5.364 +			baseStream = stream;
   5.365 +			bsLive = 0;
   5.366 +			bsBuff = 0;
   5.367 +		}
   5.368 +		
   5.369 +		void FillBuffer()
   5.370 +		{
   5.371 +			int thech = 0;
   5.372 +			
   5.373 +			try {
   5.374 +				thech = baseStream.ReadByte();
   5.375 +			} catch (Exception) {
   5.376 +				CompressedStreamEOF();
   5.377 +			}
   5.378 +			
   5.379 +			if (thech == -1) {
   5.380 +				CompressedStreamEOF();
   5.381 +			}
   5.382 +			
   5.383 +			bsBuff = (bsBuff << 8) | (thech & 0xFF);
   5.384 +			bsLive += 8;
   5.385 +		}
   5.386 +		
   5.387 +		int BsR(int n) 
   5.388 +		{
   5.389 +			while (bsLive < n) {
   5.390 +				FillBuffer();
   5.391 +			}
   5.392 +			
   5.393 +			int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
   5.394 +			bsLive -= n;
   5.395 +			return v;
   5.396 +		}
   5.397 +		
   5.398 +		char BsGetUChar() 
   5.399 +		{
   5.400 +			return (char)BsR(8);
   5.401 +		}
   5.402 +		
   5.403 +		int BsGetIntVS(int numBits) 
   5.404 +		{
   5.405 +			return BsR(numBits);
   5.406 +		}
   5.407 +		
   5.408 +		int BsGetInt32()
   5.409 +		{
   5.410 +			int result = BsR(8);
   5.411 +			result = (result << 8) | BsR(8);
   5.412 +			result = (result << 8) | BsR(8);
   5.413 +			result = (result << 8) | BsR(8);
   5.414 +			return result;
   5.415 +		}
   5.416 +		
   5.417 +		void RecvDecodingTables() 
   5.418 +		{
   5.419 +			char[][] len = new char[BZip2Constants.GroupCount][];
   5.420 +			for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
   5.421 +				len[i] = new char[BZip2Constants.MaximumAlphaSize];
   5.422 +			}
   5.423 +			
   5.424 +			bool[] inUse16 = new bool[16];
   5.425 +			
   5.426 +			//--- Receive the mapping table ---
   5.427 +			for (int i = 0; i < 16; i++) {
   5.428 +				inUse16[i] = (BsR(1) == 1);
   5.429 +			} 
   5.430 +			
   5.431 +			for (int i = 0; i < 16; i++) {
   5.432 +				if (inUse16[i]) {
   5.433 +					for (int j = 0; j < 16; j++) {
   5.434 +						inUse[i * 16 + j] = (BsR(1) == 1);
   5.435 +					}
   5.436 +				} else {
   5.437 +					for (int j = 0; j < 16; j++) {
   5.438 +						inUse[i * 16 + j] = false;
   5.439 +					}
   5.440 +				}
   5.441 +			}
   5.442 +			
   5.443 +			MakeMaps();
   5.444 +			int alphaSize = nInUse + 2;
   5.445 +			
   5.446 +			//--- Now the selectors ---
   5.447 +			int nGroups    = BsR(3);
   5.448 +			int nSelectors = BsR(15);
   5.449 +			
   5.450 +			for (int i = 0; i < nSelectors; i++) {
   5.451 +				int j = 0;
   5.452 +				while (BsR(1) == 1) {
   5.453 +					j++;
   5.454 +				}
   5.455 +				selectorMtf[i] = (byte)j;
   5.456 +			}
   5.457 +			
   5.458 +			//--- Undo the MTF values for the selectors. ---
   5.459 +			byte[] pos = new byte[BZip2Constants.GroupCount];
   5.460 +			for (int v = 0; v < nGroups; v++) {
   5.461 +				pos[v] = (byte)v;
   5.462 +			}
   5.463 +			
   5.464 +			for (int i = 0; i < nSelectors; i++) {
   5.465 +				int  v   = selectorMtf[i];
   5.466 +				byte tmp = pos[v];
   5.467 +				while (v > 0) {
   5.468 +					pos[v] = pos[v - 1];
   5.469 +					v--;
   5.470 +				}
   5.471 +				pos[0]      = tmp;
   5.472 +				selector[i] = tmp;
   5.473 +			}
   5.474 +			
   5.475 +			//--- Now the coding tables ---
   5.476 +			for (int t = 0; t < nGroups; t++) {
   5.477 +				int curr = BsR(5);
   5.478 +				for (int i = 0; i < alphaSize; i++) {
   5.479 +					while (BsR(1) == 1) {
   5.480 +						if (BsR(1) == 0) {
   5.481 +							curr++;
   5.482 +						} else {
   5.483 +							curr--;
   5.484 +						}
   5.485 +					}
   5.486 +					len[t][i] = (char)curr;
   5.487 +				}
   5.488 +			}
   5.489 +			
   5.490 +			//--- Create the Huffman decoding tables ---
   5.491 +			for (int t = 0; t < nGroups; t++) {
   5.492 +				int minLen = 32;
   5.493 +				int maxLen = 0;
   5.494 +				for (int i = 0; i < alphaSize; i++) {
   5.495 +					maxLen = Math.Max(maxLen, len[t][i]);
   5.496 +					minLen = Math.Min(minLen, len[t][i]);
   5.497 +				}
   5.498 +				HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize);
   5.499 +				minLens[t] = minLen;
   5.500 +			}
   5.501 +		}
   5.502 +		
   5.503 +		void GetAndMoveToFrontDecode() 
   5.504 +		{
   5.505 +			byte[] yy = new byte[256];
   5.506 +			int nextSym;
   5.507 +			
   5.508 +			int limitLast = BZip2Constants.BaseBlockSize * blockSize100k;
   5.509 +			origPtr = BsGetIntVS(24);
   5.510 +			
   5.511 +			RecvDecodingTables();
   5.512 +			int EOB = nInUse+1;
   5.513 +			int groupNo = -1;
   5.514 +			int groupPos = 0;
   5.515 +			
   5.516 +			/*--
   5.517 +			Setting up the unzftab entries here is not strictly
   5.518 +			necessary, but it does save having to do it later
   5.519 +			in a separate pass, and so saves a block's worth of
   5.520 +			cache misses.
   5.521 +			--*/
   5.522 +			for (int i = 0; i <= 255; i++) {
   5.523 +				unzftab[i] = 0;
   5.524 +			}
   5.525 +			
   5.526 +			for (int i = 0; i <= 255; i++) {
   5.527 +				yy[i] = (byte)i;
   5.528 +			}
   5.529 +			
   5.530 +			last = -1;
   5.531 +			
   5.532 +			if (groupPos == 0) {
   5.533 +				groupNo++;
   5.534 +				groupPos = BZip2Constants.GroupSize;
   5.535 +			}
   5.536 +			
   5.537 +			groupPos--;
   5.538 +			int zt = selector[groupNo];
   5.539 +			int zn = minLens[zt];
   5.540 +			int zvec = BsR(zn);
   5.541 +			int zj;
   5.542 +			
   5.543 +			while (zvec > limit[zt][zn]) {
   5.544 +				if (zn > 20) { // the longest code
   5.545 +					throw new BZip2Exception("Bzip data error");
   5.546 +				}
   5.547 +				zn++;
   5.548 +				while (bsLive < 1) {
   5.549 +					FillBuffer();
   5.550 +				}
   5.551 +				zj = (bsBuff >> (bsLive-1)) & 1;
   5.552 +				bsLive--;
   5.553 +				zvec = (zvec << 1) | zj;
   5.554 +			}
   5.555 +			if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) {
   5.556 +				throw new BZip2Exception("Bzip data error");
   5.557 +			}
   5.558 +			nextSym = perm[zt][zvec - baseArray[zt][zn]];
   5.559 +			
   5.560 +			while (true) {
   5.561 +				if (nextSym == EOB) {
   5.562 +					break;
   5.563 +				}
   5.564 +				
   5.565 +				if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) {
   5.566 +					int s = -1;
   5.567 +					int n = 1;
   5.568 +					do {
   5.569 +						if (nextSym == BZip2Constants.RunA) {
   5.570 +							s += (0 + 1) * n;
   5.571 +						} else if (nextSym == BZip2Constants.RunB) {
   5.572 +							s += (1 + 1) * n;
   5.573 +						}
   5.574 +
   5.575 +						n <<= 1;
   5.576 +						
   5.577 +						if (groupPos == 0) {
   5.578 +							groupNo++;
   5.579 +							groupPos = BZip2Constants.GroupSize;
   5.580 +						}
   5.581 +						
   5.582 +						groupPos--;
   5.583 +						
   5.584 +						zt = selector[groupNo];
   5.585 +						zn = minLens[zt];
   5.586 +						zvec = BsR(zn);
   5.587 +						
   5.588 +						while (zvec > limit[zt][zn]) {
   5.589 +							zn++;
   5.590 +							while (bsLive < 1) {
   5.591 +								FillBuffer();
   5.592 +							}
   5.593 +							zj = (bsBuff >> (bsLive - 1)) & 1;
   5.594 +							bsLive--;
   5.595 +							zvec = (zvec << 1) | zj;
   5.596 +						}
   5.597 +						nextSym = perm[zt][zvec - baseArray[zt][zn]];
   5.598 +					} while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB);
   5.599 +					
   5.600 +					s++;
   5.601 +					byte ch = seqToUnseq[yy[0]];
   5.602 +					unzftab[ch] += s;
   5.603 +					
   5.604 +					while (s > 0) {
   5.605 +						last++;
   5.606 +						ll8[last] = ch;
   5.607 +						s--;
   5.608 +					}
   5.609 +					
   5.610 +					if (last >= limitLast) {
   5.611 +						BlockOverrun();
   5.612 +					}
   5.613 +					continue;
   5.614 +				} else {
   5.615 +					last++;
   5.616 +					if (last >= limitLast) {
   5.617 +						BlockOverrun();
   5.618 +					}
   5.619 +					
   5.620 +					byte tmp = yy[nextSym - 1];
   5.621 +					unzftab[seqToUnseq[tmp]]++;
   5.622 +					ll8[last] = seqToUnseq[tmp];
   5.623 +					
   5.624 +					for (int j = nextSym-1; j > 0; --j) {
   5.625 +						yy[j] = yy[j - 1];
   5.626 +					}
   5.627 +					yy[0] = tmp;
   5.628 +					
   5.629 +					if (groupPos == 0) {
   5.630 +						groupNo++;
   5.631 +						groupPos = BZip2Constants.GroupSize;
   5.632 +					}
   5.633 +					
   5.634 +					groupPos--;
   5.635 +					zt = selector[groupNo];
   5.636 +					zn = minLens[zt];
   5.637 +					zvec = BsR(zn);
   5.638 +					while (zvec > limit[zt][zn]) {
   5.639 +						zn++;
   5.640 +						while (bsLive < 1) {
   5.641 +							FillBuffer();
   5.642 +						}
   5.643 +						zj = (bsBuff >> (bsLive-1)) & 1;
   5.644 +						bsLive--;
   5.645 +						zvec = (zvec << 1) | zj;
   5.646 +					}
   5.647 +					nextSym = perm[zt][zvec - baseArray[zt][zn]];
   5.648 +					continue;
   5.649 +				}
   5.650 +			}
   5.651 +		}
   5.652 +		
   5.653 +		void SetupBlock() 
   5.654 +		{
   5.655 +			int[] cftab = new int[257];
   5.656 +			
   5.657 +			cftab[0] = 0;
   5.658 +			Array.Copy(unzftab, 0, cftab, 1, 256);
   5.659 +			
   5.660 +			for (int i = 1; i <= 256; i++) {
   5.661 +				cftab[i] += cftab[i - 1];
   5.662 +			}
   5.663 +			
   5.664 +			for (int i = 0; i <= last; i++) {
   5.665 +				byte ch = ll8[i];
   5.666 +				tt[cftab[ch]] = i;
   5.667 +				cftab[ch]++;
   5.668 +			}
   5.669 +			
   5.670 +			cftab = null;
   5.671 +			
   5.672 +			tPos = tt[origPtr];
   5.673 +			
   5.674 +			count = 0;
   5.675 +			i2    = 0;
   5.676 +			ch2   = 256;   /*-- not a char and not EOF --*/
   5.677 +			
   5.678 +			if (blockRandomised) {
   5.679 +				rNToGo = 0;
   5.680 +				rTPos = 0;
   5.681 +				SetupRandPartA();
   5.682 +			} else {
   5.683 +				SetupNoRandPartA();
   5.684 +			}
   5.685 +		}
   5.686 +		
   5.687 +		void SetupRandPartA() 
   5.688 +		{
   5.689 +			if (i2 <= last) {
   5.690 +				chPrev = ch2;
   5.691 +				ch2  = ll8[tPos];
   5.692 +				tPos = tt[tPos];
   5.693 +				if (rNToGo == 0) {
   5.694 +					rNToGo = BZip2Constants.RandomNumbers[rTPos];
   5.695 +					rTPos++;
   5.696 +					if (rTPos == 512) {
   5.697 +						rTPos = 0;
   5.698 +					}
   5.699 +				}
   5.700 +				rNToGo--;
   5.701 +				ch2 ^= (int)((rNToGo == 1) ? 1 : 0);
   5.702 +				i2++;
   5.703 +				
   5.704 +				currentChar  = ch2;
   5.705 +				currentState = RAND_PART_B_STATE;
   5.706 +				mCrc.Update(ch2);
   5.707 +			} else {
   5.708 +				EndBlock();
   5.709 +				InitBlock();
   5.710 +				SetupBlock();
   5.711 +			}
   5.712 +		}
   5.713 +		
   5.714 +		void SetupNoRandPartA() 
   5.715 +		{
   5.716 +			if (i2 <= last) {
   5.717 +				chPrev = ch2;
   5.718 +				ch2  = ll8[tPos];
   5.719 +				tPos = tt[tPos];
   5.720 +				i2++;
   5.721 +				
   5.722 +				currentChar = ch2;
   5.723 +				currentState = NO_RAND_PART_B_STATE;
   5.724 +				mCrc.Update(ch2);
   5.725 +			} else {
   5.726 +				EndBlock();
   5.727 +				InitBlock();
   5.728 +				SetupBlock();
   5.729 +			}
   5.730 +		}
   5.731 +		
   5.732 +		void SetupRandPartB() 
   5.733 +		{
   5.734 +			if (ch2 != chPrev) {
   5.735 +				currentState = RAND_PART_A_STATE;
   5.736 +				count = 1;
   5.737 +				SetupRandPartA();
   5.738 +			} else {
   5.739 +				count++;
   5.740 +				if (count >= 4) {
   5.741 +					z = ll8[tPos];
   5.742 +					tPos = tt[tPos];
   5.743 +					if (rNToGo == 0) {
   5.744 +						rNToGo = BZip2Constants.RandomNumbers[rTPos];
   5.745 +						rTPos++;
   5.746 +						if (rTPos == 512) {
   5.747 +							rTPos = 0;
   5.748 +						}
   5.749 +					}
   5.750 +					rNToGo--;
   5.751 +					z ^= (byte)((rNToGo == 1) ? 1 : 0);
   5.752 +					j2 = 0;
   5.753 +					currentState = RAND_PART_C_STATE;
   5.754 +					SetupRandPartC();
   5.755 +				} else {
   5.756 +					currentState = RAND_PART_A_STATE;
   5.757 +					SetupRandPartA();
   5.758 +				}
   5.759 +			}
   5.760 +		}
   5.761 +		
   5.762 +		void SetupRandPartC() 
   5.763 +		{
   5.764 +			if (j2 < (int)z) {
   5.765 +				currentChar = ch2;
   5.766 +				mCrc.Update(ch2);
   5.767 +				j2++;
   5.768 +			} else {
   5.769 +				currentState = RAND_PART_A_STATE;
   5.770 +				i2++;
   5.771 +				count = 0;
   5.772 +				SetupRandPartA();
   5.773 +			}
   5.774 +		}
   5.775 +		
   5.776 +		void SetupNoRandPartB() 
   5.777 +		{
   5.778 +			if (ch2 != chPrev) {
   5.779 +				currentState = NO_RAND_PART_A_STATE;
   5.780 +				count = 1;
   5.781 +				SetupNoRandPartA();
   5.782 +			} else {
   5.783 +				count++;
   5.784 +				if (count >= 4) {
   5.785 +					z = ll8[tPos];
   5.786 +					tPos = tt[tPos];
   5.787 +					currentState = NO_RAND_PART_C_STATE;
   5.788 +					j2 = 0;
   5.789 +					SetupNoRandPartC();
   5.790 +				} else {
   5.791 +					currentState = NO_RAND_PART_A_STATE;
   5.792 +					SetupNoRandPartA();
   5.793 +				}
   5.794 +			}
   5.795 +		}
   5.796 +		
   5.797 +		void SetupNoRandPartC() 
   5.798 +		{
   5.799 +			if (j2 < (int)z) {
   5.800 +				currentChar = ch2;
   5.801 +				mCrc.Update(ch2);
   5.802 +				j2++;
   5.803 +			} else {
   5.804 +				currentState = NO_RAND_PART_A_STATE;
   5.805 +				i2++;
   5.806 +				count = 0;
   5.807 +				SetupNoRandPartA();
   5.808 +			}
   5.809 +		}
   5.810 +		
   5.811 +		void SetDecompressStructureSizes(int newSize100k) 
   5.812 +		{
   5.813 +			if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) {
   5.814 +				throw new BZip2Exception("Invalid block size");
   5.815 +			}
   5.816 +			
   5.817 +			blockSize100k = newSize100k;
   5.818 +			
   5.819 +			if (newSize100k == 0) {
   5.820 +				return;
   5.821 +			}
   5.822 +			
   5.823 +			int n = BZip2Constants.BaseBlockSize * newSize100k;
   5.824 +			ll8 = new byte[n];
   5.825 +			tt  = new int[n];
   5.826 +		}
   5.827 +
   5.828 +		static void CompressedStreamEOF() 
   5.829 +		{
   5.830 +			throw new EndOfStreamException("BZip2 input stream end of compressed stream");
   5.831 +		}
   5.832 +		
   5.833 +		static void BlockOverrun() 
   5.834 +		{
   5.835 +			throw new BZip2Exception("BZip2 input stream block overrun");
   5.836 +		}
   5.837 +		
   5.838 +		static void BadBlockHeader() 
   5.839 +		{
   5.840 +			throw new BZip2Exception("BZip2 input stream bad block header");
   5.841 +		}
   5.842 +		
   5.843 +		static void CrcError() 
   5.844 +		{
   5.845 +			throw new BZip2Exception("BZip2 input stream crc error");
   5.846 +		}
   5.847 +		
   5.848 +		static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize) 
   5.849 +		{
   5.850 +			int pp = 0;
   5.851 +			
   5.852 +			for (int i = minLen; i <= maxLen; ++i) 
   5.853 +			{
   5.854 +				for (int j = 0; j < alphaSize; ++j) 
   5.855 +				{
   5.856 +					if (length[j] == i) 
   5.857 +					{
   5.858 +						perm[pp] = j;
   5.859 +						++pp;
   5.860 +					}
   5.861 +				}
   5.862 +			}
   5.863 +			
   5.864 +			for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) 
   5.865 +			{
   5.866 +				baseArray[i] = 0;
   5.867 +			}
   5.868 +			
   5.869 +			for (int i = 0; i < alphaSize; i++) 
   5.870 +			{
   5.871 +				++baseArray[length[i] + 1];
   5.872 +			}
   5.873 +			
   5.874 +			for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++) 
   5.875 +			{
   5.876 +				baseArray[i] += baseArray[i - 1];
   5.877 +			}
   5.878 +			
   5.879 +			for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) 
   5.880 +			{
   5.881 +				limit[i] = 0;
   5.882 +			}
   5.883 +			
   5.884 +			int vec = 0;
   5.885 +			
   5.886 +			for (int i = minLen; i <= maxLen; i++) 
   5.887 +			{
   5.888 +				vec += (baseArray[i + 1] - baseArray[i]);
   5.889 +				limit[i] = vec - 1;
   5.890 +				vec <<= 1;
   5.891 +			}
   5.892 +			
   5.893 +			for (int i = minLen + 1; i <= maxLen; i++) 
   5.894 +			{
   5.895 +				baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i];
   5.896 +			}
   5.897 +		}
   5.898 +		
   5.899 +		#region Instance Fields
   5.900 +		/*--
   5.901 +		index of the last char in the block, so
   5.902 +		the block size == last + 1.
   5.903 +		--*/
   5.904 +		int last;
   5.905 +		
   5.906 +		/*--
   5.907 +		index in zptr[] of original string after sorting.
   5.908 +		--*/
   5.909 +		int origPtr;
   5.910 +		
   5.911 +		/*--
   5.912 +		always: in the range 0 .. 9.
   5.913 +		The current block size is 100000 * this number.
   5.914 +		--*/
   5.915 +		int blockSize100k;
   5.916 +		
   5.917 +		bool blockRandomised;
   5.918 +		
   5.919 +		int bsBuff;
   5.920 +		int bsLive;
   5.921 +		IChecksum mCrc = new StrangeCRC();
   5.922 +		
   5.923 +		bool[] inUse = new bool[256];
   5.924 +		int    nInUse;
   5.925 +		
   5.926 +		byte[] seqToUnseq = new byte[256];
   5.927 +		byte[] unseqToSeq = new byte[256];
   5.928 +		
   5.929 +		byte[] selector    = new byte[BZip2Constants.MaximumSelectors];
   5.930 +		byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors];
   5.931 +		
   5.932 +		int[] tt;
   5.933 +		byte[] ll8;
   5.934 +		
   5.935 +		/*--
   5.936 +		freq table collected to save a pass over the data
   5.937 +		during decompression.
   5.938 +		--*/
   5.939 +		int[] unzftab = new int[256];
   5.940 +		
   5.941 +		int[][] limit     = new int[BZip2Constants.GroupCount][];
   5.942 +		int[][] baseArray = new int[BZip2Constants.GroupCount][];
   5.943 +		int[][] perm      = new int[BZip2Constants.GroupCount][];
   5.944 +		int[] minLens     = new int[BZip2Constants.GroupCount];
   5.945 +		
   5.946 +		Stream baseStream;
   5.947 +		bool   streamEnd;
   5.948 +		
   5.949 +		int currentChar = -1;
   5.950 +	
   5.951 +		int currentState = START_BLOCK_STATE;
   5.952 +		
   5.953 +		int storedBlockCRC, storedCombinedCRC;
   5.954 +		int computedBlockCRC;
   5.955 +		uint computedCombinedCRC;
   5.956 +		
   5.957 +		int count, chPrev, ch2;
   5.958 +		int tPos;
   5.959 +		int rNToGo;
   5.960 +		int rTPos;
   5.961 +		int i2, j2;
   5.962 +		byte z;
   5.963 +		bool isStreamOwner = true;
   5.964 +		#endregion
   5.965 +	}
   5.966 +}
   5.967 +/* This file was derived from a file containing this license:
   5.968 + * 
   5.969 + * This file is a part of bzip2 and/or libbzip2, a program and
   5.970 + * library for lossless, block-sorting data compression.
   5.971 + * 
   5.972 + * Copyright (C) 1996-1998 Julian R Seward.  All rights reserved.
   5.973 + * 
   5.974 + * Redistribution and use in source and binary forms, with or without
   5.975 + * modification, are permitted provided that the following conditions
   5.976 + * are met:
   5.977 + * 
   5.978 + * 1. Redistributions of source code must retain the above copyright
   5.979 + * notice, this list of conditions and the following disclaimer.
   5.980 + * 
   5.981 + * 2. The origin of this software must not be misrepresented; you must 
   5.982 + * not claim that you wrote the original software.  If you use this 
   5.983 + * software in a product, an acknowledgment in the product 
   5.984 + * documentation would be appreciated but is not required.
   5.985 + * 
   5.986 + * 3. Altered source versions must be plainly marked as such, and must
   5.987 + * not be misrepresented as being the original software.
   5.988 + * 
   5.989 + * 4. The name of the author may not be used to endorse or promote 
   5.990 + * products derived from this software without specific prior written 
   5.991 + * permission.
   5.992 + * 
   5.993 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   5.994 + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   5.995 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   5.996 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
   5.997 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   5.998 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   5.999 + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  5.1000 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  5.1001 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  5.1002 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  5.1003 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  5.1004 + * 
  5.1005 + * Java version ported by Keiron Liddle, Aftex Software <keiron@aftexsw.com> 1999-2001
  5.1006 + */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/BZip2/BZip2OutputStream.cs	Sat Oct 30 14:03:17 2010 +0000
     6.3 @@ -0,0 +1,1916 @@
     6.4 +// BZip2OutputStream.cs
     6.5 +//
     6.6 +// Copyright (C) 2001 Mike Krueger
     6.7 +//
     6.8 +// This program is free software; you can redistribute it and/or
     6.9 +// modify it under the terms of the GNU General Public License
    6.10 +// as published by the Free Software Foundation; either version 2
    6.11 +// of the License, or (at your option) any later version.
    6.12 +//
    6.13 +// This program is distributed in the hope that it will be useful,
    6.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.16 +// GNU General Public License for more details.
    6.17 +//
    6.18 +// You should have received a copy of the GNU General Public License
    6.19 +// along with this program; if not, write to the Free Software
    6.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    6.21 +//
    6.22 +// Linking this library statically or dynamically with other modules is
    6.23 +// making a combined work based on this library.  Thus, the terms and
    6.24 +// conditions of the GNU General Public License cover the whole
    6.25 +// combination.
    6.26 +// 
    6.27 +// As a special exception, the copyright holders of this library give you
    6.28 +// permission to link this library with independent modules to produce an
    6.29 +// executable, regardless of the license terms of these independent
    6.30 +// modules, and to copy and distribute the resulting executable under
    6.31 +// terms of your choice, provided that you also meet, for each linked
    6.32 +// independent module, the terms and conditions of the license of that
    6.33 +// module.  An independent module is a module which is not derived from
    6.34 +// or based on this library.  If you modify this library, you may extend
    6.35 +// this exception to your version of the library, but you are not
    6.36 +// obligated to do so.  If you do not wish to do so, delete this
    6.37 +// exception statement from your version.
    6.38 +
    6.39 +using System;
    6.40 +using System.IO;
    6.41 +
    6.42 +using ICSharpCode.SharpZipLib.Checksums;
    6.43 +
    6.44 +namespace ICSharpCode.SharpZipLib.BZip2 
    6.45 +{
    6.46 +	
    6.47 +	// TODO: Update to BZip2 1.0.1, 1.0.2
    6.48 +	
    6.49 +	/// <summary>
    6.50 +	/// An output stream that compresses into the BZip2 format 
    6.51 +	/// including file header chars into another stream.
    6.52 +	/// </summary>
    6.53 +	public class BZip2OutputStream : Stream
    6.54 +	{
    6.55 +		#region Constants
    6.56 +		const int SETMASK       = (1 << 21);
    6.57 +		const int CLEARMASK     = (~SETMASK);
    6.58 +		const int GREATER_ICOST = 15;
    6.59 +		const int LESSER_ICOST = 0;
    6.60 +		const int SMALL_THRESH = 20;
    6.61 +		const int DEPTH_THRESH = 10;
    6.62 +		
    6.63 +		/*--
    6.64 +		If you are ever unlucky/improbable enough
    6.65 +		to get a stack overflow whilst sorting,
    6.66 +		increase the following constant and try
    6.67 +		again.  In practice I have never seen the
    6.68 +		stack go above 27 elems, so the following
    6.69 +		limit seems very generous.
    6.70 +		--*/
    6.71 +		const int QSORT_STACK_SIZE = 1000;
    6.72 +
    6.73 +		/*--
    6.74 +		Knuth's increments seem to work better
    6.75 +		than Incerpi-Sedgewick here.  Possibly
    6.76 +		because the number of elems to sort is
    6.77 +		usually small, typically <= 20.
    6.78 +		--*/
    6.79 +		readonly int[] increments = new int[] { 
    6.80 +												  1, 4, 13, 40, 121, 364, 1093, 3280,
    6.81 +												  9841, 29524, 88573, 265720,
    6.82 +												  797161, 2391484 
    6.83 +											  };
    6.84 +		#endregion
    6.85 +
    6.86 +		#region Constructors
    6.87 +		/// <summary>
    6.88 +		/// Construct a default output stream with maximum block size
    6.89 +		/// </summary>
    6.90 +		/// <param name="stream">The stream to write BZip data onto.</param>
    6.91 +		public BZip2OutputStream(Stream stream) : this(stream, 9)
    6.92 +		{
    6.93 +		}
    6.94 +		
    6.95 +		/// <summary>
    6.96 +		/// Initialise a new instance of the <see cref="BZip2OutputStream"></see> 
    6.97 +		/// for the specified stream, using the given blocksize.
    6.98 +		/// </summary>
    6.99 +		/// <param name="stream">The stream to write compressed data to.</param>
   6.100 +		/// <param name="blockSize">The block size to use.</param>
   6.101 +		/// <remarks>
   6.102 +		/// Valid block sizes are in the range 1..9, with 1 giving 
   6.103 +		/// the lowest compression and 9 the highest.
   6.104 +		/// </remarks>
   6.105 +		public BZip2OutputStream(Stream stream, int blockSize)
   6.106 +		{
   6.107 +			BsSetStream(stream);
   6.108 +			
   6.109 +			workFactor = 50;
   6.110 +			if (blockSize > 9) {
   6.111 +				blockSize = 9;
   6.112 +			}
   6.113 +			
   6.114 +			if (blockSize < 1) {
   6.115 +				blockSize = 1;
   6.116 +			}
   6.117 +			blockSize100k = blockSize;
   6.118 +			AllocateCompressStructures();
   6.119 +			Initialize();
   6.120 +			InitBlock();
   6.121 +		}
   6.122 +		#endregion
   6.123 +		
   6.124 +		#region Destructor
   6.125 +		/// <summary>
   6.126 +		/// Ensures that resources are freed and other cleanup operations 
   6.127 +		/// are performed when the garbage collector reclaims the BZip2OutputStream.
   6.128 +		/// </summary>
   6.129 +		~BZip2OutputStream()
   6.130 +		{
   6.131 +			Dispose(false);
   6.132 +		}
   6.133 +		#endregion
   6.134 +		
   6.135 +		/// <summary>
   6.136 +		/// Get/set flag indicating ownership of underlying stream.
   6.137 +		/// When the flag is true <see cref="Close"></see> will close the underlying stream also.
   6.138 +		/// </summary>
   6.139 +		public bool IsStreamOwner
   6.140 +		{
   6.141 +			get { return isStreamOwner; }
   6.142 +			set { isStreamOwner = value; }
   6.143 +		}
   6.144 +		
   6.145 +
   6.146 +		#region Stream overrides
   6.147 +		/// <summary>
   6.148 +		/// Gets a value indicating whether the current stream supports reading
   6.149 +		/// </summary>
   6.150 +		public override bool CanRead 
   6.151 +		{
   6.152 +			get {
   6.153 +				return false;
   6.154 +			}
   6.155 +		}
   6.156 +		
   6.157 +		/// <summary>
   6.158 +		/// Gets a value indicating whether the current stream supports seeking
   6.159 +		/// </summary>
   6.160 +		public override bool CanSeek {
   6.161 +			get {
   6.162 +				return false;
   6.163 +			}
   6.164 +		}
   6.165 +		
   6.166 +		/// <summary>
   6.167 +		/// Gets a value indicating whether the current stream supports writing
   6.168 +		/// </summary>
   6.169 +		public override bool CanWrite {
   6.170 +			get {
   6.171 +				return baseStream.CanWrite;
   6.172 +			}
   6.173 +		}
   6.174 +		
   6.175 +		/// <summary>
   6.176 +		/// Gets the length in bytes of the stream
   6.177 +		/// </summary>
   6.178 +		public override long Length {
   6.179 +			get {
   6.180 +				return baseStream.Length;
   6.181 +			}
   6.182 +		}
   6.183 +		
   6.184 +		/// <summary>
   6.185 +		/// Gets or sets the current position of this stream.
   6.186 +		/// </summary>
   6.187 +		public override long Position {
   6.188 +			get {
   6.189 +				return baseStream.Position;
   6.190 +			}
   6.191 +			set {
   6.192 +				throw new NotSupportedException("BZip2OutputStream position cannot be set");
   6.193 +			}
   6.194 +		}
   6.195 +		
   6.196 +		/// <summary>
   6.197 +		/// Sets the current position of this stream to the given value.
   6.198 +		/// </summary>
   6.199 +		/// <param name="offset">The point relative to the offset from which to being seeking.</param>
   6.200 +		/// <param name="origin">The reference point from which to begin seeking.</param>
   6.201 +		/// <returns>The new position in the stream.</returns>
   6.202 +		public override long Seek(long offset, SeekOrigin origin)
   6.203 +		{
   6.204 +			throw new NotSupportedException("BZip2OutputStream Seek not supported");
   6.205 +		}
   6.206 +		
   6.207 +		/// <summary>
   6.208 +		/// Sets the length of this stream to the given value.
   6.209 +		/// </summary>
   6.210 +		/// <param name="value">The new stream length.</param>
   6.211 +		public override void SetLength(long value)
   6.212 +		{
   6.213 +			throw new NotSupportedException("BZip2OutputStream SetLength not supported");
   6.214 +		}
   6.215 +		
   6.216 +		/// <summary>
   6.217 +		/// Read a byte from the stream advancing the position.
   6.218 +		/// </summary>
   6.219 +		/// <returns>The byte read cast to an int; -1 if end of stream.</returns>
   6.220 +		public override int ReadByte()
   6.221 +		{
   6.222 +			throw new NotSupportedException("BZip2OutputStream ReadByte not supported");
   6.223 +		}
   6.224 +		
   6.225 +		/// <summary>
   6.226 +		/// Read a block of bytes
   6.227 +		/// </summary>
   6.228 +		/// <param name="buffer">The buffer to read into.</param>
   6.229 +		/// <param name="offset">The offset in the buffer to start storing data at.</param>
   6.230 +		/// <param name="count">The maximum number of bytes to read.</param>
   6.231 +		/// <returns>The total number of bytes read. This might be less than the number of bytes
   6.232 +		/// requested if that number of bytes are not currently available, or zero 
   6.233 +		/// if the end of the stream is reached.</returns>
   6.234 +		public override int Read(byte[] buffer, int offset, int count)
   6.235 +		{
   6.236 +			throw new NotSupportedException("BZip2OutputStream Read not supported");
   6.237 +		}
   6.238 +		
   6.239 +		/// <summary>
   6.240 +		/// Write a block of bytes to the stream
   6.241 +		/// </summary>
   6.242 +		/// <param name="buffer">The buffer containing data to write.</param>
   6.243 +		/// <param name="offset">The offset of the first byte to write.</param>
   6.244 +		/// <param name="count">The number of bytes to write.</param>
   6.245 +		public override void Write(byte[] buffer, int offset, int count)
   6.246 +		{
   6.247 +			if ( buffer == null ) {
   6.248 +				throw new ArgumentNullException("buffer");
   6.249 +			}
   6.250 +
   6.251 +			if ( offset < 0 )
   6.252 +			{
   6.253 +				throw new ArgumentOutOfRangeException("offset");
   6.254 +			}
   6.255 +
   6.256 +			if ( count < 0 )
   6.257 +			{
   6.258 +				throw new ArgumentOutOfRangeException("count");
   6.259 +			}
   6.260 +
   6.261 +			if ( buffer.Length - offset < count )
   6.262 +			{
   6.263 +				throw new ArgumentException("Offset/count out of range");
   6.264 +			}
   6.265 +
   6.266 +			for (int i = 0; i < count; ++i) {
   6.267 +				WriteByte(buffer[offset + i]);
   6.268 +			}
   6.269 +		}
   6.270 +		
   6.271 +		/// <summary>
   6.272 +		/// Write a byte to the stream.
   6.273 +		/// </summary>
   6.274 +		/// <param name="value">The byte to write to the stream.</param>
   6.275 +		public override void WriteByte(byte value)
   6.276 +		{
   6.277 +			int b = (256 + value) % 256;
   6.278 +			if (currentChar != -1) {
   6.279 +				if (currentChar == b) {
   6.280 +					runLength++;
   6.281 +					if (runLength > 254) {
   6.282 +						WriteRun();
   6.283 +						currentChar = -1;
   6.284 +						runLength = 0;
   6.285 +					}
   6.286 +				} else {
   6.287 +					WriteRun();
   6.288 +					runLength = 1;
   6.289 +					currentChar = b;
   6.290 +				}
   6.291 +			} else {
   6.292 +				currentChar = b;
   6.293 +				runLength++;
   6.294 +			}
   6.295 +		}
   6.296 +		
   6.297 +		/// <summary>
   6.298 +		/// End the current block and end compression.
   6.299 +		/// Close the stream and free any resources
   6.300 +		/// </summary>
   6.301 +		public override void Close()
   6.302 +		{
   6.303 +			Dispose(true);
   6.304 +			GC.SuppressFinalize(this);
   6.305 +		}
   6.306 +
   6.307 +		#endregion
   6.308 +		void MakeMaps() 
   6.309 +		{
   6.310 +			nInUse = 0;
   6.311 +			for (int i = 0; i < 256; i++) {
   6.312 +				if (inUse[i]) {
   6.313 +					seqToUnseq[nInUse] = (char)i;
   6.314 +					unseqToSeq[i] = (char)nInUse;
   6.315 +					nInUse++;
   6.316 +				}
   6.317 +			}
   6.318 +		}
   6.319 +		
   6.320 +		/// <summary>
   6.321 +		/// Get the number of bytes written to output.
   6.322 +		/// </summary>
   6.323 +		void WriteRun()
   6.324 +		{
   6.325 +			if (last < allowableBlockSize) {
   6.326 +				inUse[currentChar] = true;
   6.327 +				for (int i = 0; i < runLength; i++) {
   6.328 +					mCrc.Update(currentChar);
   6.329 +				}
   6.330 +				
   6.331 +				switch (runLength) {
   6.332 +					case 1:
   6.333 +						last++;
   6.334 +						block[last + 1] = (byte)currentChar;
   6.335 +						break;
   6.336 +					case 2:
   6.337 +						last++;
   6.338 +						block[last + 1] = (byte)currentChar;
   6.339 +						last++;
   6.340 +						block[last + 1] = (byte)currentChar;
   6.341 +						break;
   6.342 +					case 3:
   6.343 +						last++;
   6.344 +						block[last + 1] = (byte)currentChar;
   6.345 +						last++;
   6.346 +						block[last + 1] = (byte)currentChar;
   6.347 +						last++;
   6.348 +						block[last + 1] = (byte)currentChar;
   6.349 +						break;
   6.350 +					default:
   6.351 +						inUse[runLength - 4] = true;
   6.352 +						last++;
   6.353 +						block[last + 1] = (byte)currentChar;
   6.354 +						last++;
   6.355 +						block[last + 1] = (byte)currentChar;
   6.356 +						last++;
   6.357 +						block[last + 1] = (byte)currentChar;
   6.358 +						last++;
   6.359 +						block[last + 1] = (byte)currentChar;
   6.360 +						last++;
   6.361 +						block[last + 1] = (byte)(runLength - 4);
   6.362 +						break;
   6.363 +				}
   6.364 +			} else {
   6.365 +				EndBlock();
   6.366 +				InitBlock();
   6.367 +				WriteRun();
   6.368 +			}
   6.369 +		}
   6.370 +		
   6.371 +		/// <summary>
   6.372 +		/// Get the number of bytes written to the output.
   6.373 +		/// </summary>
   6.374 +		public int BytesWritten
   6.375 +		{
   6.376 +			get { return bytesOut; }
   6.377 +		}
   6.378 +
   6.379 +		/// <summary>
   6.380 +		/// Releases the unmanaged resources used by the <see cref="BZip2OutputStream"/> and optionally releases the managed resources.
   6.381 +		/// </summary>
   6.382 +		/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
   6.383 +#if NET_1_0 || NET_1_1 || NETCF_1_0
   6.384 +		protected virtual void Dispose(bool disposing)
   6.385 +#else		
   6.386 +		override protected void Dispose(bool disposing)
   6.387 +#endif			
   6.388 +		{
   6.389 +			try {
   6.390 +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0
   6.391 +				base.Dispose(disposing);
   6.392 +#endif			
   6.393 +				if( !disposed_ ) {
   6.394 +					disposed_=true;
   6.395 +
   6.396 +					if( runLength>0 ) {
   6.397 +						WriteRun();
   6.398 +					}
   6.399 +
   6.400 +					currentChar=-1;
   6.401 +					EndBlock();
   6.402 +					EndCompression();
   6.403 +					Flush();
   6.404 +				}
   6.405 +			}
   6.406 +			finally {
   6.407 +				if ( disposing ) {
   6.408 +					if ( IsStreamOwner ) {
   6.409 +						baseStream.Close();
   6.410 +					}
   6.411 +				}
   6.412 +			}
   6.413 +		}
   6.414 +
   6.415 +		/// <summary>
   6.416 +		/// Flush output buffers
   6.417 +		/// </summary>		
   6.418 +		public override void Flush()
   6.419 +		{
   6.420 +			baseStream.Flush();
   6.421 +		}
   6.422 +				
   6.423 +		void Initialize()
   6.424 +		{
   6.425 +			bytesOut = 0;
   6.426 +			nBlocksRandomised = 0;
   6.427 +			
   6.428 +			/*--- Write header `magic' bytes indicating file-format == huffmanised,
   6.429 +			followed by a digit indicating blockSize100k.
   6.430 +			---*/
   6.431 +			
   6.432 +			BsPutUChar('B');
   6.433 +			BsPutUChar('Z');
   6.434 +			
   6.435 +			BsPutUChar('h');
   6.436 +			BsPutUChar('0' + blockSize100k);
   6.437 +			
   6.438 +			combinedCRC = 0;
   6.439 +		}
   6.440 +		
   6.441 +		void InitBlock() 
   6.442 +		{
   6.443 +			mCrc.Reset();
   6.444 +			last = -1;
   6.445 +			
   6.446 +			for (int i = 0; i < 256; i++) {
   6.447 +				inUse[i] = false;
   6.448 +			}
   6.449 +			
   6.450 +			/*--- 20 is just a paranoia constant ---*/
   6.451 +			allowableBlockSize = BZip2Constants.BaseBlockSize * blockSize100k - 20;
   6.452 +		}
   6.453 +		
   6.454 +		void EndBlock()
   6.455 +		{
   6.456 +			if (last < 0) {       // dont do anything for empty files, (makes empty files compatible with original Bzip)
   6.457 +				return;
   6.458 +			}
   6.459 +			
   6.460 +			blockCRC = unchecked((uint)mCrc.Value);
   6.461 +			combinedCRC = (combinedCRC << 1) | (combinedCRC >> 31);
   6.462 +			combinedCRC ^= blockCRC;
   6.463 +			
   6.464 +			/*-- sort the block and establish position of original string --*/
   6.465 +			DoReversibleTransformation();
   6.466 +			
   6.467 +			/*--
   6.468 +			A 6-byte block header, the value chosen arbitrarily
   6.469 +			as 0x314159265359 :-).  A 32 bit value does not really
   6.470 +			give a strong enough guarantee that the value will not
   6.471 +			appear by chance in the compressed datastream.  Worst-case
   6.472 +			probability of this event, for a 900k block, is about
   6.473 +			2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits.
   6.474 +			For a compressed file of size 100Gb -- about 100000 blocks --
   6.475 +			only a 48-bit marker will do.  NB: normal compression/
   6.476 +			decompression do *not* rely on these statistical properties.
   6.477 +			They are only important when trying to recover blocks from
   6.478 +			damaged files.
   6.479 +			--*/
   6.480 +			BsPutUChar(0x31);
   6.481 +			BsPutUChar(0x41);
   6.482 +			BsPutUChar(0x59);
   6.483 +			BsPutUChar(0x26);
   6.484 +			BsPutUChar(0x53);
   6.485 +			BsPutUChar(0x59);
   6.486 +			
   6.487 +			/*-- Now the block's CRC, so it is in a known place. --*/
   6.488 +			unchecked {
   6.489 +				BsPutint((int)blockCRC);
   6.490 +			}
   6.491 +			
   6.492 +			/*-- Now a single bit indicating randomisation. --*/
   6.493 +			if (blockRandomised) {
   6.494 +				BsW(1,1);
   6.495 +				nBlocksRandomised++;
   6.496 +			} else {
   6.497 +				BsW(1,0);
   6.498 +			}
   6.499 +			
   6.500 +			/*-- Finally, block's contents proper. --*/
   6.501 +			MoveToFrontCodeAndSend();
   6.502 +		}
   6.503 +		
   6.504 +		void EndCompression()
   6.505 +		{
   6.506 +			/*--
   6.507 +			Now another magic 48-bit number, 0x177245385090, to
   6.508 +			indicate the end of the last block.  (sqrt(pi), if
   6.509 +			you want to know.  I did want to use e, but it contains
   6.510 +			too much repetition -- 27 18 28 18 28 46 -- for me
   6.511 +			to feel statistically comfortable.  Call me paranoid.)
   6.512 +			--*/
   6.513 +			BsPutUChar(0x17);
   6.514 +			BsPutUChar(0x72);
   6.515 +			BsPutUChar(0x45);
   6.516 +			BsPutUChar(0x38);
   6.517 +			BsPutUChar(0x50);
   6.518 +			BsPutUChar(0x90);
   6.519 +			
   6.520 +			unchecked {
   6.521 +				BsPutint((int)combinedCRC);
   6.522 +			}
   6.523 +			
   6.524 +			BsFinishedWithStream();
   6.525 +		}
   6.526 +		
   6.527 +		void BsSetStream(Stream stream) 
   6.528 +		{
   6.529 +			baseStream = stream;
   6.530 +			bsLive = 0;
   6.531 +			bsBuff = 0;
   6.532 +			bytesOut = 0;
   6.533 +		}
   6.534 +		
   6.535 +		void BsFinishedWithStream()
   6.536 +		{
   6.537 +			while (bsLive > 0) 
   6.538 +			{
   6.539 +				int ch = (bsBuff >> 24);
   6.540 +				baseStream.WriteByte((byte)ch); // write 8-bit
   6.541 +				bsBuff <<= 8;
   6.542 +				bsLive -= 8;
   6.543 +				bytesOut++;
   6.544 +			}
   6.545 +		}
   6.546 +		
   6.547 +		void BsW(int n, int v)
   6.548 +		{
   6.549 +			while (bsLive >= 8) {
   6.550 +				int ch = (bsBuff >> 24);
   6.551 +				unchecked{baseStream.WriteByte((byte)ch);} // write 8-bit
   6.552 +				bsBuff <<= 8;
   6.553 +				bsLive -= 8;
   6.554 +				++bytesOut;
   6.555 +			}
   6.556 +			bsBuff |= (v << (32 - bsLive - n));
   6.557 +			bsLive += n;
   6.558 +		}
   6.559 +		
   6.560 +		void BsPutUChar(int c)
   6.561 +		{
   6.562 +			BsW(8, c);
   6.563 +		}
   6.564 +		
   6.565 +		void BsPutint(int u)
   6.566 +		{
   6.567 +			BsW(8, (u >> 24) & 0xFF);
   6.568 +			BsW(8, (u >> 16) & 0xFF);
   6.569 +			BsW(8, (u >>  8) & 0xFF);
   6.570 +			BsW(8,  u        & 0xFF);
   6.571 +		}
   6.572 +		
   6.573 +		void BsPutIntVS(int numBits, int c)
   6.574 +		{
   6.575 +			BsW(numBits, c);
   6.576 +		}
   6.577 +		
   6.578 +		void SendMTFValues()
   6.579 +		{
   6.580 +			char[][] len = new char[BZip2Constants.GroupCount][];
   6.581 +			for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
   6.582 +				len[i] = new char[BZip2Constants.MaximumAlphaSize];
   6.583 +			}
   6.584 +			
   6.585 +			int gs, ge, totc, bt, bc, iter;
   6.586 +			int nSelectors = 0, alphaSize, minLen, maxLen, selCtr;
   6.587 +			int nGroups;
   6.588 +			
   6.589 +			alphaSize = nInUse + 2;
   6.590 +			for (int t = 0; t < BZip2Constants.GroupCount; t++) {
   6.591 +				for (int v = 0; v < alphaSize; v++) {
   6.592 +					len[t][v] = (char)GREATER_ICOST;
   6.593 +				}
   6.594 +			}
   6.595 +			
   6.596 +			/*--- Decide how many coding tables to use ---*/
   6.597 +			if (nMTF <= 0) {
   6.598 +				Panic();
   6.599 +			}
   6.600 +			
   6.601 +			if (nMTF < 200) {
   6.602 +				nGroups = 2;
   6.603 +			} else if (nMTF < 600) {
   6.604 +				nGroups = 3;
   6.605 +			} else if (nMTF < 1200) {
   6.606 +				nGroups = 4;
   6.607 +			} else if (nMTF < 2400) {
   6.608 +				nGroups = 5;
   6.609 +			} else {
   6.610 +				nGroups = 6;
   6.611 +			}
   6.612 +			
   6.613 +			/*--- Generate an initial set of coding tables ---*/ 
   6.614 +			int nPart = nGroups;
   6.615 +			int remF  = nMTF;
   6.616 +			gs = 0;
   6.617 +			while (nPart > 0) {
   6.618 +				int tFreq = remF / nPart;
   6.619 +				int aFreq = 0;
   6.620 +				ge = gs - 1;
   6.621 +				while (aFreq < tFreq && ge < alphaSize - 1) {
   6.622 +					ge++;
   6.623 +					aFreq += mtfFreq[ge];
   6.624 +				}
   6.625 +				
   6.626 +				if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups - nPart) % 2 == 1)) {
   6.627 +					aFreq -= mtfFreq[ge];
   6.628 +					ge--;
   6.629 +				}
   6.630 +				
   6.631 +				for (int v = 0; v < alphaSize; v++) {
   6.632 +					if (v >= gs && v <= ge) {
   6.633 +						len[nPart - 1][v] = (char)LESSER_ICOST;
   6.634 +					} else {
   6.635 +						len[nPart - 1][v] = (char)GREATER_ICOST;
   6.636 +					}
   6.637 +				}
   6.638 +				
   6.639 +				nPart--;
   6.640 +				gs = ge + 1;
   6.641 +				remF -= aFreq;
   6.642 +			}
   6.643 +			
   6.644 +			int[][] rfreq = new int[BZip2Constants.GroupCount][];
   6.645 +			for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
   6.646 +				rfreq[i] = new int[BZip2Constants.MaximumAlphaSize];
   6.647 +			}
   6.648 +			
   6.649 +			int[] fave = new int[BZip2Constants.GroupCount];
   6.650 +			short[] cost = new short[BZip2Constants.GroupCount];
   6.651 +			/*---
   6.652 +			Iterate up to N_ITERS times to improve the tables.
   6.653 +			---*/
   6.654 +			for (iter = 0; iter < BZip2Constants.NumberOfIterations; ++iter) {
   6.655 +				for (int t = 0; t < nGroups; ++t) {
   6.656 +					fave[t] = 0;
   6.657 +				}
   6.658 +				
   6.659 +				for (int t = 0; t < nGroups; ++t) {
   6.660 +					for (int v = 0; v < alphaSize; ++v) {
   6.661 +						rfreq[t][v] = 0;
   6.662 +					}
   6.663 +				}
   6.664 +				
   6.665 +				nSelectors = 0;
   6.666 +				totc = 0;
   6.667 +				gs   = 0;
   6.668 +				while (true) {
   6.669 +					/*--- Set group start & end marks. --*/
   6.670 +					if (gs >= nMTF) {
   6.671 +						break;
   6.672 +					}
   6.673 +					ge = gs + BZip2Constants.GroupSize - 1;
   6.674 +					if (ge >= nMTF) {
   6.675 +						ge = nMTF - 1;
   6.676 +					}
   6.677 +					
   6.678 +					/*--
   6.679 +					Calculate the cost of this group as coded
   6.680 +					by each of the coding tables.
   6.681 +					--*/
   6.682 +					for (int t = 0; t < nGroups; t++) {
   6.683 +						cost[t] = 0;
   6.684 +					}
   6.685 +					
   6.686 +					if (nGroups == 6) {
   6.687 +						short cost0, cost1, cost2, cost3, cost4, cost5;
   6.688 +						cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0;
   6.689 +						for (int i = gs; i <= ge; ++i) {
   6.690 +							short icv = szptr[i];
   6.691 +							cost0 += (short)len[0][icv];
   6.692 +							cost1 += (short)len[1][icv];
   6.693 +							cost2 += (short)len[2][icv];
   6.694 +							cost3 += (short)len[3][icv];
   6.695 +							cost4 += (short)len[4][icv];
   6.696 +							cost5 += (short)len[5][icv];
   6.697 +						}
   6.698 +						cost[0] = cost0;
   6.699 +						cost[1] = cost1;
   6.700 +						cost[2] = cost2;
   6.701 +						cost[3] = cost3;
   6.702 +						cost[4] = cost4;
   6.703 +						cost[5] = cost5;
   6.704 +					} else {
   6.705 +						for (int i = gs; i <= ge; ++i) {
   6.706 +							short icv = szptr[i];
   6.707 +							for (int t = 0; t < nGroups; t++) {
   6.708 +								cost[t] += (short)len[t][icv];
   6.709 +							}
   6.710 +						}
   6.711 +					}
   6.712 +					
   6.713 +					/*--
   6.714 +					Find the coding table which is best for this group,
   6.715 +					and record its identity in the selector table.
   6.716 +					--*/
   6.717 +					bc = 999999999;
   6.718 +					bt = -1;
   6.719 +					for (int t = 0; t < nGroups; ++t) {
   6.720 +						if (cost[t] < bc) {
   6.721 +							bc = cost[t];
   6.722 +							bt = t;
   6.723 +						}
   6.724 +					}
   6.725 +					totc += bc;
   6.726 +					fave[bt]++;
   6.727 +					selector[nSelectors] = (char)bt;
   6.728 +					nSelectors++;
   6.729 +					
   6.730 +					/*--
   6.731 +					Increment the symbol frequencies for the selected table.
   6.732 +					--*/
   6.733 +					for (int i = gs; i <= ge; ++i) {
   6.734 +						++rfreq[bt][szptr[i]];
   6.735 +					}
   6.736 +					
   6.737 +					gs = ge+1;
   6.738 +				}
   6.739 +				
   6.740 +				/*--
   6.741 +				Recompute the tables based on the accumulated frequencies.
   6.742 +				--*/
   6.743 +				for (int t = 0; t < nGroups; ++t) {
   6.744 +					HbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20);
   6.745 +				}
   6.746 +			}
   6.747 +			
   6.748 +			rfreq = null;
   6.749 +			fave = null;
   6.750 +			cost = null;
   6.751 +			
   6.752 +			if (!(nGroups < 8)) {
   6.753 +				Panic();
   6.754 +			}
   6.755 +			
   6.756 +			if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZip2Constants.GroupSize)))) {
   6.757 +				Panic();
   6.758 +			}
   6.759 +			
   6.760 +			/*--- Compute MTF values for the selectors. ---*/
   6.761 +			char[] pos = new char[BZip2Constants.GroupCount];
   6.762 +			char ll_i, tmp2, tmp;
   6.763 +			
   6.764 +			for (int i = 0; i < nGroups; i++) {
   6.765 +				pos[i] = (char)i;
   6.766 +			}
   6.767 +			
   6.768 +			for (int i = 0; i < nSelectors; i++) {
   6.769 +				ll_i = selector[i];
   6.770 +				int j = 0;
   6.771 +				tmp = pos[j];
   6.772 +				while (ll_i != tmp) {
   6.773 +					j++;
   6.774 +					tmp2 = tmp;
   6.775 +					tmp = pos[j];
   6.776 +					pos[j] = tmp2;
   6.777 +				}
   6.778 +				pos[0] = tmp;
   6.779 +				selectorMtf[i] = (char)j;
   6.780 +			}
   6.781 +			
   6.782 +			int[][] code = new int[BZip2Constants.GroupCount][];
   6.783 +			
   6.784 +			for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
   6.785 +				code[i] = new int[BZip2Constants.MaximumAlphaSize];
   6.786 +			}
   6.787 +			
   6.788 +			/*--- Assign actual codes for the tables. --*/
   6.789 +			for (int t = 0; t < nGroups; t++) {
   6.790 +				minLen = 32;
   6.791 +				maxLen = 0;
   6.792 +				for (int i = 0; i < alphaSize; i++) {
   6.793 +					if (len[t][i] > maxLen) {
   6.794 +						maxLen = len[t][i];
   6.795 +					}
   6.796 +					if (len[t][i] < minLen) {
   6.797 +						minLen = len[t][i];
   6.798 +					}
   6.799 +				}
   6.800 +				if (maxLen > 20) {
   6.801 +					Panic();
   6.802 +				}
   6.803 +				if (minLen < 1) {
   6.804 +					Panic();
   6.805 +				}
   6.806 +				HbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize);
   6.807 +			}
   6.808 +			
   6.809 +			/*--- Transmit the mapping table. ---*/
   6.810 +			bool[] inUse16 = new bool[16];
   6.811 +			for (int i = 0; i < 16; ++i) {
   6.812 +				inUse16[i] = false;
   6.813 +				for (int j = 0; j < 16; ++j) {
   6.814 +					if (inUse[i * 16 + j]) {
   6.815 +						inUse16[i] = true; 
   6.816 +					}
   6.817 +				}
   6.818 +			}
   6.819 +			
   6.820 +			for (int i = 0; i < 16; ++i) {
   6.821 +				if (inUse16[i]) {
   6.822 +					BsW(1,1);
   6.823 +				} else {
   6.824 +					BsW(1,0);
   6.825 +				}
   6.826 +			}
   6.827 +			
   6.828 +			for (int i = 0; i < 16; ++i) {
   6.829 +				if (inUse16[i]) {
   6.830 +					for (int j = 0; j < 16; ++j) {
   6.831 +						if (inUse[i * 16 + j]) {
   6.832 +							BsW(1,1);
   6.833 +						} else {
   6.834 +							BsW(1,0);
   6.835 +						}
   6.836 +					}
   6.837 +				}
   6.838 +			}
   6.839 +			
   6.840 +			/*--- Now the selectors. ---*/
   6.841 +			BsW(3, nGroups);
   6.842 +			BsW(15, nSelectors);
   6.843 +			for (int i = 0; i < nSelectors; ++i) {
   6.844 +				for (int j = 0; j < selectorMtf[i]; ++j) {
   6.845 +					BsW(1,1);
   6.846 +				}
   6.847 +				BsW(1,0);
   6.848 +			}
   6.849 +			
   6.850 +			/*--- Now the coding tables. ---*/
   6.851 +			for (int t = 0; t < nGroups; ++t) {
   6.852 +				int curr = len[t][0];
   6.853 +				BsW(5, curr);
   6.854 +				for (int i = 0; i < alphaSize; ++i) {
   6.855 +					while (curr < len[t][i]) {
   6.856 +						BsW(2, 2);
   6.857 +						curr++; /* 10 */
   6.858 +					}
   6.859 +					while (curr > len[t][i]) {
   6.860 +						BsW(2, 3);
   6.861 +						curr--; /* 11 */
   6.862 +					}
   6.863 +					BsW (1, 0);
   6.864 +				}
   6.865 +			}
   6.866 +			
   6.867 +			/*--- And finally, the block data proper ---*/
   6.868 +			selCtr = 0;
   6.869 +			gs = 0;
   6.870 +			while (true) {
   6.871 +				if (gs >= nMTF) {
   6.872 +					break;
   6.873 +				}
   6.874 +				ge = gs + BZip2Constants.GroupSize - 1;
   6.875 +				if (ge >= nMTF) {
   6.876 +					ge = nMTF - 1;
   6.877 +				}
   6.878 +				
   6.879 +				for (int i = gs; i <= ge; i++) {
   6.880 +					BsW(len[selector[selCtr]][szptr[i]], code[selector[selCtr]][szptr[i]]);
   6.881 +				}
   6.882 +				
   6.883 +				gs = ge + 1;
   6.884 +				++selCtr;
   6.885 +			}
   6.886 +			if (!(selCtr == nSelectors)) {
   6.887 +				Panic();
   6.888 +			}
   6.889 +		}
   6.890 +		
   6.891 +		void MoveToFrontCodeAndSend () 
   6.892 +		{
   6.893 +			BsPutIntVS(24, origPtr);
   6.894 +			GenerateMTFValues();
   6.895 +			SendMTFValues();
   6.896 +		}	
   6.897 +		
   6.898 +		void SimpleSort(int lo, int hi, int d) 
   6.899 +		{
   6.900 +			int i, j, h, bigN, hp;
   6.901 +			int v;
   6.902 +			
   6.903 +			bigN = hi - lo + 1;
   6.904 +			if (bigN < 2) {
   6.905 +				return;
   6.906 +			}
   6.907 +			
   6.908 +			hp = 0;
   6.909 +			while (increments[hp] < bigN) {
   6.910 +				hp++;
   6.911 +			}
   6.912 +			hp--;
   6.913 +			
   6.914 +			for (; hp >= 0; hp--) {
   6.915 +				h = increments[hp];
   6.916 +				
   6.917 +				i = lo + h;
   6.918 +				while (true) {
   6.919 +					/*-- copy 1 --*/
   6.920 +					if (i > hi)
   6.921 +						break;
   6.922 +					v = zptr[i];
   6.923 +					j = i;
   6.924 +					while (FullGtU(zptr[j-h]+d, v+d)) {
   6.925 +						zptr[j] = zptr[j-h];
   6.926 +						j = j - h;
   6.927 +						if (j <= (lo + h - 1))
   6.928 +							break;
   6.929 +					}
   6.930 +					zptr[j] = v;
   6.931 +					i++;
   6.932 +					
   6.933 +					/*-- copy 2 --*/
   6.934 +					if (i > hi) {
   6.935 +						break;
   6.936 +					}
   6.937 +					v = zptr[i];
   6.938 +					j = i;
   6.939 +					while (FullGtU ( zptr[j-h]+d, v+d )) {
   6.940 +						zptr[j] = zptr[j-h];
   6.941 +						j = j - h;
   6.942 +						if (j <= (lo + h - 1)) {
   6.943 +							break;
   6.944 +						}
   6.945 +					}
   6.946 +					zptr[j] = v;
   6.947 +					i++;
   6.948 +					
   6.949 +					/*-- copy 3 --*/
   6.950 +					if (i > hi) {
   6.951 +						break;
   6.952 +					}
   6.953 +					v = zptr[i];
   6.954 +					j = i;
   6.955 +					while (FullGtU ( zptr[j-h]+d, v+d)) {
   6.956 +						zptr[j] = zptr[j-h];
   6.957 +						j = j - h;
   6.958 +						if (j <= (lo + h - 1)) {
   6.959 +							break;
   6.960 +						}
   6.961 +					}
   6.962 +					zptr[j] = v;
   6.963 +					i++;
   6.964 +					
   6.965 +					if (workDone > workLimit && firstAttempt) {
   6.966 +						return;
   6.967 +					}
   6.968 +				}
   6.969 +			}
   6.970 +		}
   6.971 +		
   6.972 +		void Vswap(int p1, int p2, int n ) 
   6.973 +		{
   6.974 +			int temp = 0;
   6.975 +			while (n > 0) {
   6.976 +				temp = zptr[p1];
   6.977 +				zptr[p1] = zptr[p2];
   6.978 +				zptr[p2] = temp;
   6.979 +				p1++;
   6.980 +				p2++;
   6.981 +				n--;
   6.982 +			}
   6.983 +		}
   6.984 +		
   6.985 +		void QSort3(int loSt, int hiSt, int dSt) 
   6.986 +		{
   6.987 +			int unLo, unHi, ltLo, gtHi, med, n, m;
   6.988 +			int lo, hi, d;
   6.989 +			
   6.990 +			StackElement[] stack = new StackElement[QSORT_STACK_SIZE];
   6.991 +
   6.992 +			int sp = 0;
   6.993 +			
   6.994 +			stack[sp].ll = loSt;
   6.995 +			stack[sp].hh = hiSt;
   6.996 +			stack[sp].dd = dSt;
   6.997 +			sp++;
   6.998 +			
   6.999 +			while (sp > 0) {
  6.1000 +				if (sp >= QSORT_STACK_SIZE) {
  6.1001 +					Panic();
  6.1002 +				}
  6.1003 +				
  6.1004 +				sp--;
  6.1005 +				lo = stack[sp].ll;
  6.1006 +				hi = stack[sp].hh;
  6.1007 +				d = stack[sp].dd;
  6.1008 +				
  6.1009 +				if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) {
  6.1010 +					SimpleSort(lo, hi, d);
  6.1011 +					if (workDone > workLimit && firstAttempt) {
  6.1012 +						return;
  6.1013 +					}
  6.1014 +					continue;
  6.1015 +				}
  6.1016 +				
  6.1017 +				med = Med3(block[zptr[lo] + d + 1],
  6.1018 +						   block[zptr[hi            ] + d + 1],
  6.1019 +						   block[zptr[(lo + hi) >> 1] + d + 1]);
  6.1020 +				
  6.1021 +				unLo = ltLo = lo;
  6.1022 +				unHi = gtHi = hi;
  6.1023 +				
  6.1024 +				while (true) {
  6.1025 +					while (true) {
  6.1026 +						if (unLo > unHi) {
  6.1027 +							break;
  6.1028 +						}
  6.1029 +						n = ((int)block[zptr[unLo]+d + 1]) - med;
  6.1030 +						if (n == 0) {
  6.1031 +							int temp = zptr[unLo];
  6.1032 +							zptr[unLo] = zptr[ltLo];
  6.1033 +							zptr[ltLo] = temp;
  6.1034 +							ltLo++;
  6.1035 +							unLo++;
  6.1036 +							continue;
  6.1037 +						}
  6.1038 +						if (n >  0) {
  6.1039 +							break;
  6.1040 +						}
  6.1041 +						unLo++;
  6.1042 +					}
  6.1043 +
  6.1044 +					while (true) {
  6.1045 +						if (unLo > unHi) {
  6.1046 +							break;
  6.1047 +						}
  6.1048 +						n = ((int)block[zptr[unHi]+d + 1]) - med;
  6.1049 +						if (n == 0) {
  6.1050 +							int temp = zptr[unHi];
  6.1051 +							zptr[unHi] = zptr[gtHi];
  6.1052 +							zptr[gtHi] = temp;
  6.1053 +							gtHi--;
  6.1054 +							unHi--;
  6.1055 +							continue;
  6.1056 +						}
  6.1057 +						if (n <  0) {
  6.1058 +							break;
  6.1059 +						}
  6.1060 +						unHi--;
  6.1061 +					}
  6.1062 +
  6.1063 +					if (unLo > unHi) {
  6.1064 +						break;
  6.1065 +					}
  6.1066 +
  6.1067 +					{
  6.1068 +						int temp = zptr[unLo];
  6.1069 +						zptr[unLo] = zptr[unHi];
  6.1070 +						zptr[unHi] = temp;
  6.1071 +						unLo++;
  6.1072 +						unHi--;
  6.1073 +					}
  6.1074 +				}
  6.1075 +				
  6.1076 +				if (gtHi < ltLo) {
  6.1077 +					stack[sp].ll = lo;
  6.1078 +					stack[sp].hh = hi;
  6.1079 +					stack[sp].dd = d+1;
  6.1080 +					sp++;
  6.1081 +					continue;
  6.1082 +				}
  6.1083 +				
  6.1084 +				n = ((ltLo-lo) < (unLo-ltLo)) ? (ltLo-lo) : (unLo-ltLo);
  6.1085 +				Vswap(lo, unLo-n, n);
  6.1086 +				m = ((hi-gtHi) < (gtHi-unHi)) ? (hi-gtHi) : (gtHi-unHi);
  6.1087 +				Vswap(unLo, hi-m+1, m);
  6.1088 +				
  6.1089 +				n = lo + unLo - ltLo - 1;
  6.1090 +				m = hi - (gtHi - unHi) + 1;
  6.1091 +				
  6.1092 +				stack[sp].ll = lo;
  6.1093 +				stack[sp].hh = n;
  6.1094 +				stack[sp].dd = d;
  6.1095 +				sp++;
  6.1096 +				
  6.1097 +				stack[sp].ll = n + 1;
  6.1098 +				stack[sp].hh = m - 1;
  6.1099 +				stack[sp].dd = d+1;
  6.1100 +				sp++;
  6.1101 +				
  6.1102 +				stack[sp].ll = m;
  6.1103 +				stack[sp].hh = hi;
  6.1104 +				stack[sp].dd = d;
  6.1105 +				sp++;
  6.1106 +			}
  6.1107 +		}
  6.1108 +		
  6.1109 +		void MainSort() 
  6.1110 +		{
  6.1111 +			int i, j, ss, sb;
  6.1112 +			int[] runningOrder = new int[256];
  6.1113 +			int[] copy = new int[256];
  6.1114 +			bool[] bigDone = new bool[256];
  6.1115 +			int c1, c2;
  6.1116 +			int numQSorted;
  6.1117 +			
  6.1118 +			/*--
  6.1119 +			In the various block-sized structures, live data runs
  6.1120 +			from 0 to last+NUM_OVERSHOOT_BYTES inclusive.  First,
  6.1121 +			set up the overshoot area for block.
  6.1122 +			--*/
  6.1123 +			
  6.1124 +			//   if (verbosity >= 4) fprintf ( stderr, "        sort initialise ...\n" );
  6.1125 +			for (i = 0; i < BZip2Constants.OvershootBytes; i++) {
  6.1126 +				block[last + i + 2] = block[(i % (last + 1)) + 1];
  6.1127 +			}
  6.1128 +			for (i = 0; i <= last + BZip2Constants.OvershootBytes; i++) {
  6.1129 +				quadrant[i] = 0;
  6.1130 +			}
  6.1131 +			
  6.1132 +			block[0] = (byte)(block[last + 1]);
  6.1133 +			
  6.1134 +			if (last < 4000) {
  6.1135 +				/*--
  6.1136 +				Use simpleSort(), since the full sorting mechanism
  6.1137 +				has quite a large constant overhead.
  6.1138 +				--*/
  6.1139 +				for (i = 0; i <= last; i++) {
  6.1140 +					zptr[i] = i;
  6.1141 +				}
  6.1142 +				firstAttempt = false;
  6.1143 +				workDone = workLimit = 0;
  6.1144 +				SimpleSort(0, last, 0);
  6.1145 +			} else {
  6.1146 +				numQSorted = 0;
  6.1147 +				for (i = 0; i <= 255; i++) {
  6.1148 +					bigDone[i] = false;
  6.1149 +				}
  6.1150 +				for (i = 0; i <= 65536; i++) {
  6.1151 +					ftab[i] = 0;
  6.1152 +				}
  6.1153 +				
  6.1154 +				c1 = block[0];
  6.1155 +				for (i = 0; i <= last; i++) {
  6.1156 +					c2 = block[i + 1];
  6.1157 +					ftab[(c1 << 8) + c2]++;
  6.1158 +					c1 = c2;
  6.1159 +				}
  6.1160 +				
  6.1161 +				for (i = 1; i <= 65536; i++) {
  6.1162 +					ftab[i] += ftab[i - 1];
  6.1163 +				}
  6.1164 +				
  6.1165 +				c1 = block[1];
  6.1166 +				for (i = 0; i < last; i++) {
  6.1167 +					c2 = block[i + 2];
  6.1168 +					j = (c1 << 8) + c2;
  6.1169 +					c1 = c2;
  6.1170 +					ftab[j]--;
  6.1171 +					zptr[ftab[j]] = i;
  6.1172 +				}
  6.1173 +				
  6.1174 +				j = ((block[last + 1]) << 8) + (block[1]);
  6.1175 +				ftab[j]--;
  6.1176 +				zptr[ftab[j]] = last;
  6.1177 +				
  6.1178 +				/*--
  6.1179 +				Now ftab contains the first loc of every small bucket.
  6.1180 +				Calculate the running order, from smallest to largest
  6.1181 +				big bucket.
  6.1182 +				--*/
  6.1183 +				
  6.1184 +				for (i = 0; i <= 255; i++) {
  6.1185 +					runningOrder[i] = i;
  6.1186 +				}
  6.1187 +				
  6.1188 +				int vv;
  6.1189 +				int h = 1;
  6.1190 +				do {
  6.1191 +					h = 3 * h + 1;
  6.1192 +				} while (h <= 256);
  6.1193 +				do {
  6.1194 +					h = h / 3;
  6.1195 +					for (i = h; i <= 255; i++) {
  6.1196 +						vv = runningOrder[i];
  6.1197 +						j = i;
  6.1198 +						while ((ftab[((runningOrder[j-h])+1) << 8] - ftab[(runningOrder[j-h]) << 8]) > (ftab[((vv)+1) << 8] - ftab[(vv) << 8])) {
  6.1199 +							runningOrder[j] = runningOrder[j-h];
  6.1200 +							j = j - h;
  6.1201 +							if (j <= (h - 1)) {
  6.1202 +								break;
  6.1203 +							}
  6.1204 +						}
  6.1205 +						runningOrder[j] = vv;
  6.1206 +					}
  6.1207 +				} while (h != 1);
  6.1208 +				
  6.1209 +				/*--
  6.1210 +				The main sorting loop.
  6.1211 +				--*/
  6.1212 +				for (i = 0; i <= 255; i++) {
  6.1213 +					
  6.1214 +					/*--
  6.1215 +					Process big buckets, starting with the least full.
  6.1216 +					--*/
  6.1217 +					ss = runningOrder[i];
  6.1218 +					
  6.1219 +					/*--
  6.1220 +					Complete the big bucket [ss] by quicksorting
  6.1221 +					any unsorted small buckets [ss, j].  Hopefully
  6.1222 +					previous pointer-scanning phases have already
  6.1223 +					completed many of the small buckets [ss, j], so
  6.1224 +					we don't have to sort them at all.
  6.1225 +					--*/
  6.1226 +					for (j = 0; j <= 255; j++) {
  6.1227 +						sb = (ss << 8) + j;
  6.1228 +						if(!((ftab[sb] & SETMASK) == SETMASK)) {
  6.1229 +							int lo = ftab[sb] & CLEARMASK;
  6.1230 +							int hi = (ftab[sb+1] & CLEARMASK) - 1;
  6.1231 +							if (hi > lo) {
  6.1232 +								QSort3(lo, hi, 2);
  6.1233 +								numQSorted += (hi - lo + 1);
  6.1234 +								if (workDone > workLimit && firstAttempt) {
  6.1235 +									return;
  6.1236 +								}
  6.1237 +							}
  6.1238 +							ftab[sb] |= SETMASK;
  6.1239 +						}
  6.1240 +					}
  6.1241 +					
  6.1242 +					/*--
  6.1243 +					The ss big bucket is now done.  Record this fact,
  6.1244 +					and update the quadrant descriptors.  Remember to
  6.1245 +					update quadrants in the overshoot area too, if
  6.1246 +					necessary.  The "if (i < 255)" test merely skips
  6.1247 +					this updating for the last bucket processed, since
  6.1248 +					updating for the last bucket is pointless.
  6.1249 +					--*/
  6.1250 +					bigDone[ss] = true;
  6.1251 +					
  6.1252 +					if (i < 255) {
  6.1253 +						int bbStart  = ftab[ss << 8] & CLEARMASK;
  6.1254 +						int bbSize   = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
  6.1255 +						int shifts   = 0;
  6.1256 +						
  6.1257 +						while ((bbSize >> shifts) > 65534) {
  6.1258 +							shifts++;
  6.1259 +						}
  6.1260 +						
  6.1261 +						for (j = 0; j < bbSize; j++) {
  6.1262 +							int a2update = zptr[bbStart + j];
  6.1263 +							int qVal = (j >> shifts);
  6.1264 +							quadrant[a2update] = qVal;
  6.1265 +							if (a2update < BZip2Constants.OvershootBytes) {
  6.1266 +								quadrant[a2update + last + 1] = qVal;
  6.1267 +							}
  6.1268 +						}
  6.1269 +						
  6.1270 +						if (!(((bbSize-1) >> shifts) <= 65535)) {
  6.1271 +							Panic();
  6.1272 +						}
  6.1273 +					}
  6.1274 +					
  6.1275 +					/*--
  6.1276 +					Now scan this big bucket so as to synthesise the
  6.1277 +					sorted order for small buckets [t, ss] for all t != ss.
  6.1278 +					--*/
  6.1279 +					for (j = 0; j <= 255; j++) {
  6.1280 +						copy[j] = ftab[(j << 8) + ss] & CLEARMASK;
  6.1281 +					}
  6.1282 +					
  6.1283 +					for (j = ftab[ss << 8] & CLEARMASK; j < (ftab[(ss+1) << 8] & CLEARMASK); j++) {
  6.1284 +						c1 = block[zptr[j]];
  6.1285 +						if (!bigDone[c1]) {
  6.1286 +							zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1;
  6.1287 +							copy[c1] ++;
  6.1288 +						}
  6.1289 +					}
  6.1290 +					
  6.1291 +					for (j = 0; j <= 255; j++) {
  6.1292 +						ftab[(j << 8) + ss] |= SETMASK;
  6.1293 +					}
  6.1294 +				}
  6.1295 +			}
  6.1296 +		}
  6.1297 +		
  6.1298 +		void RandomiseBlock() 
  6.1299 +		{
  6.1300 +			int i;
  6.1301 +			int rNToGo = 0;
  6.1302 +			int rTPos  = 0;
  6.1303 +			for (i = 0; i < 256; i++) {
  6.1304 +				inUse[i] = false;
  6.1305 +			}
  6.1306 +			
  6.1307 +			for (i = 0; i <= last; i++) {
  6.1308 +				if (rNToGo == 0) {
  6.1309 +					rNToGo = (int)BZip2Constants.RandomNumbers[rTPos];
  6.1310 +					rTPos++;
  6.1311 +					if (rTPos == 512) {
  6.1312 +						rTPos = 0;
  6.1313 +					}
  6.1314 +				}
  6.1315 +				rNToGo--;
  6.1316 +				block[i + 1] ^= (byte)((rNToGo == 1) ? 1 : 0);
  6.1317 +				// handle 16 bit signed numbers
  6.1318 +				block[i + 1] &= 0xFF;
  6.1319 +				
  6.1320 +				inUse[block[i + 1]] = true;
  6.1321 +			}
  6.1322 +		}
  6.1323 +		
  6.1324 +		void DoReversibleTransformation() 
  6.1325 +		{
  6.1326 +			workLimit = workFactor * last;
  6.1327 +			workDone = 0;
  6.1328 +			blockRandomised = false;
  6.1329 +			firstAttempt = true;
  6.1330 +			
  6.1331 +			MainSort();
  6.1332 +			
  6.1333 +			if (workDone > workLimit && firstAttempt) {
  6.1334 +				RandomiseBlock();
  6.1335 +				workLimit = workDone = 0;
  6.1336 +				blockRandomised = true;
  6.1337 +				firstAttempt = false;
  6.1338 +				MainSort();
  6.1339 +			}
  6.1340 +			
  6.1341 +			origPtr = -1;
  6.1342 +			for (int i = 0; i <= last; i++) {
  6.1343 +				if (zptr[i] == 0) {
  6.1344 +					origPtr = i;
  6.1345 +					break;
  6.1346 +				}
  6.1347 +			}
  6.1348 +			
  6.1349 +			if (origPtr == -1) {
  6.1350 +				Panic();
  6.1351 +			}
  6.1352 +		}
  6.1353 +		
  6.1354 +		bool FullGtU(int i1, int i2) 
  6.1355 +		{
  6.1356 +			int k;
  6.1357 +			byte c1, c2;
  6.1358 +			int s1, s2;
  6.1359 +			
  6.1360 +			c1 = block[i1 + 1];
  6.1361 +			c2 = block[i2 + 1];
  6.1362 +			if (c1 != c2) {
  6.1363 +				return c1 > c2;
  6.1364 +			}
  6.1365 +			i1++;
  6.1366 +			i2++;
  6.1367 +			
  6.1368 +			c1 = block[i1 + 1];
  6.1369 +			c2 = block[i2 + 1];
  6.1370 +			if (c1 != c2) {
  6.1371 +				return c1 > c2;
  6.1372 +			}
  6.1373 +			i1++;
  6.1374 +			i2++;
  6.1375 +			
  6.1376 +			c1 = block[i1 + 1];
  6.1377 +			c2 = block[i2 + 1];
  6.1378 +			if (c1 != c2) {
  6.1379 +				return c1 > c2;
  6.1380 +			}
  6.1381 +			i1++;
  6.1382 +			i2++;
  6.1383 +			
  6.1384 +			c1 = block[i1 + 1];
  6.1385 +			c2 = block[i2 + 1];
  6.1386 +			if (c1 != c2) {
  6.1387 +				return c1 > c2;
  6.1388 +			}
  6.1389 +			i1++;
  6.1390 +			i2++;
  6.1391 +			
  6.1392 +			c1 = block[i1 + 1];
  6.1393 +			c2 = block[i2 + 1];
  6.1394 +			if (c1 != c2) {
  6.1395 +				return c1 > c2;
  6.1396 +			}
  6.1397 +			i1++;
  6.1398 +			i2++;
  6.1399 +			
  6.1400 +			c1 = block[i1 + 1];
  6.1401 +			c2 = block[i2 + 1];
  6.1402 +			if (c1 != c2) {
  6.1403 +				return c1 > c2;
  6.1404 +			}
  6.1405 +			i1++;
  6.1406 +			i2++;
  6.1407 +			
  6.1408 +			k = last + 1;
  6.1409 +			
  6.1410 +			do {
  6.1411 +				c1 = block[i1 + 1];
  6.1412 +				c2 = block[i2 + 1];
  6.1413 +				if (c1 != c2) {
  6.1414 +					return c1 > c2;
  6.1415 +				}
  6.1416 +				s1 = quadrant[i1];
  6.1417 +				s2 = quadrant[i2];
  6.1418 +				if (s1 != s2) {
  6.1419 +					return s1 > s2;
  6.1420 +				}
  6.1421 +				i1++;
  6.1422 +				i2++;
  6.1423 +				
  6.1424 +				c1 = block[i1 + 1];
  6.1425 +				c2 = block[i2 + 1];
  6.1426 +				if (c1 != c2) {
  6.1427 +					return c1 > c2;
  6.1428 +				}
  6.1429 +				s1 = quadrant[i1];
  6.1430 +				s2 = quadrant[i2];
  6.1431 +				if (s1 != s2) {
  6.1432 +					return s1 > s2;
  6.1433 +				}
  6.1434 +				i1++;
  6.1435 +				i2++;
  6.1436 +				
  6.1437 +				c1 = block[i1 + 1];
  6.1438 +				c2 = block[i2 + 1];
  6.1439 +				if (c1 != c2) {
  6.1440 +					return c1 > c2;
  6.1441 +				}
  6.1442 +				s1 = quadrant[i1];
  6.1443 +				s2 = quadrant[i2];
  6.1444 +				if (s1 != s2) {
  6.1445 +					return s1 > s2;
  6.1446 +				}
  6.1447 +				i1++;
  6.1448 +				i2++;
  6.1449 +				
  6.1450 +				c1 = block[i1 + 1];
  6.1451 +				c2 = block[i2 + 1];
  6.1452 +				if (c1 != c2) {
  6.1453 +					return c1 > c2;
  6.1454 +				}
  6.1455 +				s1 = quadrant[i1];
  6.1456 +				s2 = quadrant[i2];
  6.1457 +				if (s1 != s2) {
  6.1458 +					return s1 > s2;
  6.1459 +				}
  6.1460 +				i1++;
  6.1461 +				i2++;
  6.1462 +				
  6.1463 +				if (i1 > last) {
  6.1464 +					i1 -= last;
  6.1465 +					i1--;
  6.1466 +				}
  6.1467 +				if (i2 > last) {
  6.1468 +					i2 -= last;
  6.1469 +					i2--;
  6.1470 +				}
  6.1471 +				
  6.1472 +				k -= 4;
  6.1473 +				++workDone;
  6.1474 +			} while (k >= 0);
  6.1475 +			
  6.1476 +			return false;
  6.1477 +		}
  6.1478 +		
  6.1479 +		void AllocateCompressStructures() 
  6.1480 +		{
  6.1481 +			int n = BZip2Constants.BaseBlockSize * blockSize100k;
  6.1482 +			block = new byte[(n + 1 + BZip2Constants.OvershootBytes)];
  6.1483 +			quadrant = new int[(n + BZip2Constants.OvershootBytes)];
  6.1484 +			zptr = new int[n];
  6.1485 +			ftab = new int[65537];
  6.1486 +			
  6.1487 +			if (block == null || quadrant == null || zptr == null  || ftab == null) {
  6.1488 +				//		int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537;
  6.1489 +				//		compressOutOfMemory ( totalDraw, n );
  6.1490 +			}
  6.1491 +			
  6.1492 +			/*
  6.1493 +			The back end needs a place to store the MTF values
  6.1494 +			whilst it calculates the coding tables.  We could
  6.1495 +			put them in the zptr array.  However, these values
  6.1496 +			will fit in a short, so we overlay szptr at the
  6.1497 +			start of zptr, in the hope of reducing the number
  6.1498 +			of cache misses induced by the multiple traversals
  6.1499 +			of the MTF values when calculating coding tables.
  6.1500 +			Seems to improve compression speed by about 1%.
  6.1501 +			*/
  6.1502 +			//	szptr = zptr;
  6.1503 +			
  6.1504 +			
  6.1505 +			szptr = new short[2 * n];
  6.1506 +		}
  6.1507 +		
  6.1508 +		void GenerateMTFValues() 
  6.1509 +		{
  6.1510 +			char[] yy = new char[256];
  6.1511 +			int  i, j;
  6.1512 +			char tmp;
  6.1513 +			char tmp2;
  6.1514 +			int zPend;
  6.1515 +			int wr;
  6.1516 +			int EOB;
  6.1517 +			
  6.1518 +			MakeMaps();
  6.1519 +			EOB = nInUse+1;
  6.1520 +			
  6.1521 +			for (i = 0; i <= EOB; i++) {
  6.1522 +				mtfFreq[i] = 0;
  6.1523 +			}
  6.1524 +			
  6.1525 +			wr = 0;
  6.1526 +			zPend = 0;
  6.1527 +			for (i = 0; i < nInUse; i++) {
  6.1528 +				yy[i] = (char) i;
  6.1529 +			}
  6.1530 +			
  6.1531 +			
  6.1532 +			for (i = 0; i <= last; i++) {
  6.1533 +				char ll_i;
  6.1534 +				
  6.1535 +				ll_i = unseqToSeq[block[zptr[i]]];
  6.1536 +				
  6.1537 +				j = 0;
  6.1538 +				tmp = yy[j];
  6.1539 +				while (ll_i != tmp) {
  6.1540 +					j++;
  6.1541 +					tmp2 = tmp;
  6.1542 +					tmp = yy[j];
  6.1543 +					yy[j] = tmp2;
  6.1544 +				}
  6.1545 +				yy[0] = tmp;
  6.1546 +				
  6.1547 +				if (j == 0) {
  6.1548 +					zPend++;
  6.1549 +				} else {
  6.1550 +					if (zPend > 0) {
  6.1551 +						zPend--;
  6.1552 +						while (true) {
  6.1553 +							switch (zPend % 2) {
  6.1554 +								case 0:
  6.1555 +									szptr[wr] = (short)BZip2Constants.RunA;
  6.1556 +									wr++;
  6.1557 +									mtfFreq[BZip2Constants.RunA]++;
  6.1558 +									break;
  6.1559 +								case 1:
  6.1560 +									szptr[wr] = (short)BZip2Constants.RunB;
  6.1561 +									wr++;
  6.1562 +									mtfFreq[BZip2Constants.RunB]++;
  6.1563 +									break;
  6.1564 +							}
  6.1565 +							if (zPend < 2) {
  6.1566 +								break;
  6.1567 +							}
  6.1568 +							zPend = (zPend - 2) / 2;
  6.1569 +						}
  6.1570 +						zPend = 0;
  6.1571 +					}
  6.1572 +					szptr[wr] = (short)(j + 1);
  6.1573 +					wr++;
  6.1574 +					mtfFreq[j + 1]++;
  6.1575 +				}
  6.1576 +			}
  6.1577 +			
  6.1578 +			if (zPend > 0) {
  6.1579 +				zPend--;
  6.1580 +				while (true) {
  6.1581 +					switch (zPend % 2) {
  6.1582 +						case 0:
  6.1583 +							szptr[wr] = (short)BZip2Constants.RunA;
  6.1584 +							wr++;
  6.1585 +							mtfFreq[BZip2Constants.RunA]++;
  6.1586 +							break;
  6.1587 +						case 1:
  6.1588 +							szptr[wr] = (short)BZip2Constants.RunB;
  6.1589 +							wr++;
  6.1590 +							mtfFreq[BZip2Constants.RunB]++;
  6.1591 +							break;
  6.1592 +					}
  6.1593 +					if (zPend < 2) {
  6.1594 +						break;
  6.1595 +					}
  6.1596 +					zPend = (zPend - 2) / 2;
  6.1597 +				}
  6.1598 +			}
  6.1599 +			
  6.1600 +			szptr[wr] = (short)EOB;
  6.1601 +			wr++;
  6.1602 +			mtfFreq[EOB]++;
  6.1603 +			
  6.1604 +			nMTF = wr;
  6.1605 +		}
  6.1606 +
  6.1607 +		static void Panic() 
  6.1608 +		{
  6.1609 +			throw new BZip2Exception("BZip2 output stream panic");
  6.1610 +		}
  6.1611 +		
  6.1612 +		static void HbMakeCodeLengths(char[] len, int[] freq, int alphaSize, int maxLen) 
  6.1613 +		{
  6.1614 +			/*--
  6.1615 +			Nodes and heap entries run from 1.  Entry 0
  6.1616 +			for both the heap and nodes is a sentinel.
  6.1617 +			--*/
  6.1618 +			int nNodes, nHeap, n1, n2, j, k;
  6.1619 +			bool  tooLong;
  6.1620 +			
  6.1621 +			int[] heap   = new int[BZip2Constants.MaximumAlphaSize + 2];
  6.1622 +			int[] weight = new int[BZip2Constants.MaximumAlphaSize * 2];
  6.1623 +			int[] parent = new int[BZip2Constants.MaximumAlphaSize * 2];
  6.1624 +			
  6.1625 +			for (int i = 0; i < alphaSize; ++i) 
  6.1626 +			{
  6.1627 +				weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
  6.1628 +			}
  6.1629 +			
  6.1630 +			while (true) 
  6.1631 +			{
  6.1632 +				nNodes = alphaSize;
  6.1633 +				nHeap = 0;
  6.1634 +				
  6.1635 +				heap[0] = 0;
  6.1636 +				weight[0] = 0;
  6.1637 +				parent[0] = -2;
  6.1638 +				
  6.1639 +				for (int i = 1; i <= alphaSize; ++i) 
  6.1640 +				{
  6.1641 +					parent[i] = -1;
  6.1642 +					nHeap++;
  6.1643 +					heap[nHeap] = i;
  6.1644 +					int zz = nHeap;
  6.1645 +					int tmp = heap[zz];
  6.1646 +					while (weight[tmp] < weight[heap[zz >> 1]]) 
  6.1647 +					{
  6.1648 +						heap[zz] = heap[zz >> 1];
  6.1649 +						zz >>= 1;
  6.1650 +					}
  6.1651 +					heap[zz] = tmp;
  6.1652 +				}
  6.1653 +				if (!(nHeap < (BZip2Constants.MaximumAlphaSize+2))) 
  6.1654 +				{
  6.1655 +					Panic();
  6.1656 +				}
  6.1657 +				
  6.1658 +				while (nHeap > 1) 
  6.1659 +				{
  6.1660 +					n1 = heap[1];
  6.1661 +					heap[1] = heap[nHeap];
  6.1662 +					nHeap--;
  6.1663 +					int zz = 1;
  6.1664 +					int yy = 0;
  6.1665 +					int tmp = heap[zz];
  6.1666 +					while (true) 
  6.1667 +					{
  6.1668 +						yy = zz << 1;
  6.1669 +						if (yy > nHeap) 
  6.1670 +						{
  6.1671 +							break;
  6.1672 +						}
  6.1673 +						if (yy < nHeap &&  weight[heap[yy+1]] < weight[heap[yy]]) 
  6.1674 +						{
  6.1675 +							yy++;
  6.1676 +						}
  6.1677 +						if (weight[tmp] < weight[heap[yy]]) 
  6.1678 +						{
  6.1679 +							break;
  6.1680 +						}
  6.1681 +						
  6.1682 +						heap[zz] = heap[yy];
  6.1683 +						zz = yy;
  6.1684 +					}
  6.1685 +					heap[zz] = tmp;
  6.1686 +					n2 = heap[1];
  6.1687 +					heap[1] = heap[nHeap];
  6.1688 +					nHeap--;
  6.1689 +					
  6.1690 +					zz = 1;
  6.1691 +					yy = 0;
  6.1692 +					tmp = heap[zz];
  6.1693 +					while (true) 
  6.1694 +					{
  6.1695 +						yy = zz << 1;
  6.1696 +						if (yy > nHeap) 
  6.1697 +						{
  6.1698 +							break;
  6.1699 +						}
  6.1700 +						if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) 
  6.1701 +						{
  6.1702 +							yy++;
  6.1703 +						}
  6.1704 +						if (weight[tmp] < weight[heap[yy]]) 
  6.1705 +						{
  6.1706 +							break;
  6.1707 +						}
  6.1708 +						heap[zz] = heap[yy];
  6.1709 +						zz = yy;
  6.1710 +					}
  6.1711 +					heap[zz] = tmp;
  6.1712 +					nNodes++;
  6.1713 +					parent[n1] = parent[n2] = nNodes;
  6.1714 +					
  6.1715 +					weight[nNodes] = (int)((weight[n1] & 0xffffff00) + (weight[n2] & 0xffffff00)) | 
  6.1716 +						(int)(1 + (((weight[n1] & 0x000000ff) > (weight[n2] & 0x000000ff)) ? (weight[n1] & 0x000000ff) : (weight[n2] & 0x000000ff)));
  6.1717 +					
  6.1718 +					parent[nNodes] = -1;
  6.1719 +					nHeap++;
  6.1720 +					heap[nHeap] = nNodes;
  6.1721 +					
  6.1722 +					zz  = nHeap;
  6.1723 +					tmp = heap[zz];
  6.1724 +					while (weight[tmp] < weight[heap[zz >> 1]]) 
  6.1725 +					{
  6.1726 +						heap[zz] = heap[zz >> 1];
  6.1727 +						zz >>= 1;
  6.1728 +					}
  6.1729 +					heap[zz] = tmp;
  6.1730 +				}
  6.1731 +				if (!(nNodes < (BZip2Constants.MaximumAlphaSize * 2))) 
  6.1732 +				{
  6.1733 +					Panic();
  6.1734 +				}
  6.1735 +				
  6.1736 +				tooLong = false;
  6.1737 +				for (int i = 1; i <= alphaSize; ++i) 
  6.1738 +				{
  6.1739 +					j = 0;
  6.1740 +					k = i;
  6.1741 +					while (parent[k] >= 0) 
  6.1742 +					{
  6.1743 +						k = parent[k];
  6.1744 +						j++;
  6.1745 +					}
  6.1746 +					len[i - 1] = (char)j;
  6.1747 +					if (j > maxLen) 
  6.1748 +					{
  6.1749 +						tooLong = true;
  6.1750 +					}
  6.1751 +				}
  6.1752 +				
  6.1753 +				if (!tooLong) 
  6.1754 +				{
  6.1755 +					break;
  6.1756 +				}
  6.1757 +				
  6.1758 +				for (int i = 1; i < alphaSize; ++i) 
  6.1759 +				{
  6.1760 +					j = weight[i] >> 8;
  6.1761 +					j = 1 + (j / 2);
  6.1762 +					weight[i] = j << 8;
  6.1763 +				}
  6.1764 +			}
  6.1765 +		}
  6.1766 +		
  6.1767 +		static void HbAssignCodes (int[] code, char[] length, int minLen, int maxLen, int alphaSize) 
  6.1768 +		{
  6.1769 +			int vec = 0;
  6.1770 +			for (int n = minLen; n <= maxLen; ++n) 
  6.1771 +			{
  6.1772 +				for (int i = 0; i < alphaSize; ++i) 
  6.1773 +				{
  6.1774 +					if (length[i] == n) 
  6.1775 +					{
  6.1776 +						code[i] = vec;
  6.1777 +						++vec;
  6.1778 +					}
  6.1779 +				}
  6.1780 +				vec <<= 1;
  6.1781 +			}
  6.1782 +		}
  6.1783 +		
  6.1784 +		static byte Med3(byte a, byte b, byte c ) 
  6.1785 +		{
  6.1786 +			byte t;
  6.1787 +			if (a > b) 
  6.1788 +			{
  6.1789 +				t = a;
  6.1790 +				a = b;
  6.1791 +				b = t;
  6.1792 +			}
  6.1793 +			if (b > c) 
  6.1794 +			{
  6.1795 +				t = b;
  6.1796 +				b = c;
  6.1797 +				c = t;
  6.1798 +			}
  6.1799 +			if (a > b) 
  6.1800 +			{
  6.1801 +				b = a;
  6.1802 +			}
  6.1803 +			return b;
  6.1804 +		}
  6.1805 +
  6.1806 +		struct StackElement
  6.1807 +		{
  6.1808 +			public int ll;
  6.1809 +			public int hh;
  6.1810 +			public int dd;
  6.1811 +		}
  6.1812 +		
  6.1813 +		#region Instance Fields
  6.1814 +		bool isStreamOwner = true;
  6.1815 +		
  6.1816 +		/*--
  6.1817 +		index of the last char in the block, so
  6.1818 +		the block size == last + 1.
  6.1819 +		--*/
  6.1820 +		int last;
  6.1821 +		
  6.1822 +		/*--
  6.1823 +		index in zptr[] of original string after sorting.
  6.1824 +		--*/
  6.1825 +		int origPtr;
  6.1826 +		
  6.1827 +		/*--
  6.1828 +		always: in the range 0 .. 9.
  6.1829 +		The current block size is 100000 * this number.
  6.1830 +		--*/
  6.1831 +		int blockSize100k;
  6.1832 +		
  6.1833 +		bool blockRandomised;
  6.1834 +		
  6.1835 +		int bytesOut;
  6.1836 +		int bsBuff;
  6.1837 +		int bsLive;
  6.1838 +		IChecksum mCrc = new StrangeCRC();
  6.1839 +		
  6.1840 +		bool[] inUse = new bool[256];
  6.1841 +		int nInUse;
  6.1842 +		
  6.1843 +		char[] seqToUnseq = new char[256];
  6.1844 +		char[] unseqToSeq = new char[256];
  6.1845 +		
  6.1846 +		char[] selector = new char[BZip2Constants.MaximumSelectors];
  6.1847 +		char[] selectorMtf = new char[BZip2Constants.MaximumSelectors];
  6.1848 +		
  6.1849 +		byte[]  block;
  6.1850 +		int[]   quadrant;
  6.1851 +		int[]   zptr;
  6.1852 +		short[] szptr;
  6.1853 +		int[]   ftab;
  6.1854 +		
  6.1855 +		int nMTF;
  6.1856 +		
  6.1857 +		int[] mtfFreq = new int[BZip2Constants.MaximumAlphaSize];
  6.1858 +		
  6.1859 +		/*
  6.1860 +		* Used when sorting.  If too many long comparisons
  6.1861 +		* happen, we stop sorting, randomise the block
  6.1862 +		* slightly, and try again.
  6.1863 +		*/
  6.1864 +		int workFactor;
  6.1865 +		int workDone;
  6.1866 +		int workLimit;
  6.1867 +		bool firstAttempt;
  6.1868 +		int nBlocksRandomised;
  6.1869 +		
  6.1870 +		int currentChar = -1;
  6.1871 +		int runLength;
  6.1872 +		uint blockCRC, combinedCRC;
  6.1873 +		int allowableBlockSize;
  6.1874 +		Stream baseStream;
  6.1875 +		bool disposed_;
  6.1876 +		#endregion
  6.1877 +	}
  6.1878 +}
  6.1879 +
  6.1880 +/* This file was derived from a file containing this license:
  6.1881 + * 
  6.1882 + * This file is a part of bzip2 and/or libbzip2, a program and
  6.1883 + * library for lossless, block-sorting data compression.
  6.1884 + * 
  6.1885 + * Copyright (C) 1996-1998 Julian R Seward.  All rights reserved.
  6.1886 + * 
  6.1887 + * Redistribution and use in source and binary forms, with or without
  6.1888 + * modification, are permitted provided that the following conditions
  6.1889 + * are met:
  6.1890 + * 
  6.1891 + * 1. Redistributions of source code must retain the above copyright
  6.1892 + * notice, this list of conditions and the following disclaimer.
  6.1893 + * 
  6.1894 + * 2. The origin of this software must not be misrepresented; you must 
  6.1895 + * not claim that you wrote the original software.  If you use this 
  6.1896 + * software in a product, an acknowledgment in the product 
  6.1897 + * documentation would be appreciated but is not required.
  6.1898 + * 
  6.1899 + * 3. Altered source versions must be plainly marked as such, and must
  6.1900 + * not be misrepresented as being the original software.
  6.1901 + * 
  6.1902 + * 4. The name of the author may not be used to endorse or promote 
  6.1903 + * products derived from this software without specific prior written 
  6.1904 + * permission.
  6.1905 + * 
  6.1906 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  6.1907 + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  6.1908 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  6.1909 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  6.1910 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  6.1911 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  6.1912 + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  6.1913 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  6.1914 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  6.1915 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  6.1916 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  6.1917 + * 
  6.1918 + * Java version ported by Keiron Liddle, Aftex Software <keiron@aftexsw.com> 1999-2001
  6.1919 + */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/Checksums/Adler32.cs	Sat Oct 30 14:03:17 2010 +0000
     7.3 @@ -0,0 +1,237 @@
     7.4 +// Adler32.cs - Computes Adler32 data checksum of a data stream
     7.5 +// Copyright (C) 2001 Mike Krueger
     7.6 +//
     7.7 +// This file was translated from java, it was part of the GNU Classpath
     7.8 +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
     7.9 +//
    7.10 +// This program is free software; you can redistribute it and/or
    7.11 +// modify it under the terms of the GNU General Public License
    7.12 +// as published by the Free Software Foundation; either version 2
    7.13 +// of the License, or (at your option) any later version.
    7.14 +//
    7.15 +// This program is distributed in the hope that it will be useful,
    7.16 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.17 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.18 +// GNU General Public License for more details.
    7.19 +//
    7.20 +// You should have received a copy of the GNU General Public License
    7.21 +// along with this program; if not, write to the Free Software
    7.22 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    7.23 +//
    7.24 +// Linking this library statically or dynamically with other modules is
    7.25 +// making a combined work based on this library.  Thus, the terms and
    7.26 +// conditions of the GNU General Public License cover the whole
    7.27 +// combination.
    7.28 +// 
    7.29 +// As a special exception, the copyright holders of this library give you
    7.30 +// permission to link this library with independent modules to produce an
    7.31 +// executable, regardless of the license terms of these independent
    7.32 +// modules, and to copy and distribute the resulting executable under
    7.33 +// terms of your choice, provided that you also meet, for each linked
    7.34 +// independent module, the terms and conditions of the license of that
    7.35 +// module.  An independent module is a module which is not derived from
    7.36 +// or based on this library.  If you modify this library, you may extend
    7.37 +// this exception to your version of the library, but you are not
    7.38 +// obligated to do so.  If you do not wish to do so, delete this
    7.39 +// exception statement from your version.
    7.40 +
    7.41 +using System;
    7.42 +
    7.43 +namespace ICSharpCode.SharpZipLib.Checksums 
    7.44 +{
    7.45 +	
    7.46 +	/// <summary>
    7.47 +	/// Computes Adler32 checksum for a stream of data. An Adler32
    7.48 +	/// checksum is not as reliable as a CRC32 checksum, but a lot faster to
    7.49 +	/// compute.
    7.50 +	/// 
    7.51 +	/// The specification for Adler32 may be found in RFC 1950.
    7.52 +	/// ZLIB Compressed Data Format Specification version 3.3)
    7.53 +	/// 
    7.54 +	/// 
    7.55 +	/// From that document:
    7.56 +	/// 
    7.57 +	///      "ADLER32 (Adler-32 checksum)
    7.58 +	///       This contains a checksum value of the uncompressed data
    7.59 +	///       (excluding any dictionary data) computed according to Adler-32
    7.60 +	///       algorithm. This algorithm is a 32-bit extension and improvement
    7.61 +	///       of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
    7.62 +	///       standard.
    7.63 +	/// 
    7.64 +	///       Adler-32 is composed of two sums accumulated per byte: s1 is
    7.65 +	///       the sum of all bytes, s2 is the sum of all s1 values. Both sums
    7.66 +	///       are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
    7.67 +	///       Adler-32 checksum is stored as s2*65536 + s1 in most-
    7.68 +	///       significant-byte first (network) order."
    7.69 +	/// 
    7.70 +	///  "8.2. The Adler-32 algorithm
    7.71 +	/// 
    7.72 +	///    The Adler-32 algorithm is much faster than the CRC32 algorithm yet
    7.73 +	///    still provides an extremely low probability of undetected errors.
    7.74 +	/// 
    7.75 +	///    The modulo on unsigned long accumulators can be delayed for 5552
    7.76 +	///    bytes, so the modulo operation time is negligible.  If the bytes
    7.77 +	///    are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
    7.78 +	///    and order sensitive, unlike the first sum, which is just a
    7.79 +	///    checksum.  That 65521 is prime is important to avoid a possible
    7.80 +	///    large class of two-byte errors that leave the check unchanged.
    7.81 +	///    (The Fletcher checksum uses 255, which is not prime and which also
    7.82 +	///    makes the Fletcher check insensitive to single byte changes 0 -
    7.83 +	///    255.)
    7.84 +	/// 
    7.85 +	///    The sum s1 is initialized to 1 instead of zero to make the length
    7.86 +	///    of the sequence part of s2, so that the length does not have to be
    7.87 +	///    checked separately. (Any sequence of zeroes has a Fletcher
    7.88 +	///    checksum of zero.)"
    7.89 +	/// </summary>
    7.90 +	/// <see cref="ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream"/>
    7.91 +	/// <see cref="ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream"/>
    7.92 +	public sealed class Adler32 : IChecksum
    7.93 +	{
    7.94 +		/// <summary>
    7.95 +		/// largest prime smaller than 65536
    7.96 +		/// </summary>
    7.97 +		const uint BASE = 65521;
    7.98 +		
    7.99 +		/// <summary>
   7.100 +		/// Returns the Adler32 data checksum computed so far.
   7.101 +		/// </summary>
   7.102 +		public long Value {
   7.103 +			get {
   7.104 +				return checksum;
   7.105 +			}
   7.106 +		}
   7.107 +		
   7.108 +		/// <summary>
   7.109 +		/// Creates a new instance of the Adler32 class.
   7.110 +		/// The checksum starts off with a value of 1.
   7.111 +		/// </summary>
   7.112 +		public Adler32()
   7.113 +		{
   7.114 +			Reset();
   7.115 +		}
   7.116 +		
   7.117 +		/// <summary>
   7.118 +		/// Resets the Adler32 checksum to the initial value.
   7.119 +		/// </summary>
   7.120 +		public void Reset()
   7.121 +		{
   7.122 +			checksum = 1;
   7.123 +		}
   7.124 +		
   7.125 +		/// <summary>
   7.126 +		/// Updates the checksum with a byte value.
   7.127 +		/// </summary>
   7.128 +		/// <param name="value">
   7.129 +		/// The data value to add. The high byte of the int is ignored.
   7.130 +		/// </param>
   7.131 +		public void Update(int value)
   7.132 +		{
   7.133 +			// We could make a length 1 byte array and call update again, but I
   7.134 +			// would rather not have that overhead
   7.135 +			uint s1 = checksum & 0xFFFF;
   7.136 +			uint s2 = checksum >> 16;
   7.137 +			
   7.138 +			s1 = (s1 + ((uint)value & 0xFF)) % BASE;
   7.139 +			s2 = (s1 + s2) % BASE;
   7.140 +			
   7.141 +			checksum = (s2 << 16) + s1;
   7.142 +		}
   7.143 +		
   7.144 +		/// <summary>
   7.145 +		/// Updates the checksum with an array of bytes.
   7.146 +		/// </summary>
   7.147 +		/// <param name="buffer">
   7.148 +		/// The source of the data to update with.
   7.149 +		/// </param>
   7.150 +		public void Update(byte[] buffer)
   7.151 +		{
   7.152 +			if ( buffer == null ) {
   7.153 +				throw new ArgumentNullException("buffer");
   7.154 +			}
   7.155 +
   7.156 +			Update(buffer, 0, buffer.Length);
   7.157 +		}
   7.158 +		
   7.159 +		/// <summary>
   7.160 +		/// Updates the checksum with the bytes taken from the array.
   7.161 +		/// </summary>
   7.162 +		/// <param name="buffer">
   7.163 +		/// an array of bytes
   7.164 +		/// </param>
   7.165 +		/// <param name="offset">
   7.166 +		/// the start of the data used for this update
   7.167 +		/// </param>
   7.168 +		/// <param name="count">
   7.169 +		/// the number of bytes to use for this update
   7.170 +		/// </param>
   7.171 +		public void Update(byte[] buffer, int offset, int count)
   7.172 +		{
   7.173 +			if (buffer == null) {
   7.174 +				throw new ArgumentNullException("buffer");
   7.175 +			}
   7.176 +			
   7.177 +			if (offset < 0) {
   7.178 +#if NETCF_1_0
   7.179 +				throw new ArgumentOutOfRangeException("offset");
   7.180 +#else
   7.181 +				throw new ArgumentOutOfRangeException("offset", "cannot be negative");
   7.182 +#endif				
   7.183 +			}
   7.184 +
   7.185 +			if ( count < 0 ) 
   7.186 +			{
   7.187 +#if NETCF_1_0
   7.188 +				throw new ArgumentOutOfRangeException("count");
   7.189 +#else
   7.190 +				throw new ArgumentOutOfRangeException("count", "cannot be negative");
   7.191 +#endif				
   7.192 +			}
   7.193 +
   7.194 +			if (offset >= buffer.Length) 
   7.195 +			{
   7.196 +#if NETCF_1_0
   7.197 +				throw new ArgumentOutOfRangeException("offset");
   7.198 +#else
   7.199 +				throw new ArgumentOutOfRangeException("offset", "not a valid index into buffer");
   7.200 +#endif				
   7.201 +			}
   7.202 +			
   7.203 +			if (offset + count > buffer.Length) 
   7.204 +			{
   7.205 +#if NETCF_1_0
   7.206 +				throw new ArgumentOutOfRangeException("count");
   7.207 +#else
   7.208 +				throw new ArgumentOutOfRangeException("count", "exceeds buffer size");
   7.209 +#endif				
   7.210 +			}
   7.211 +
   7.212 +			//(By Per Bothner)
   7.213 +			uint s1 = checksum & 0xFFFF;
   7.214 +			uint s2 = checksum >> 16;
   7.215 +			
   7.216 +			while (count > 0) {
   7.217 +				// We can defer the modulo operation:
   7.218 +				// s1 maximally grows from 65521 to 65521 + 255 * 3800
   7.219 +				// s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
   7.220 +				int n = 3800;
   7.221 +				if (n > count) {
   7.222 +					n = count;
   7.223 +				}
   7.224 +				count -= n;
   7.225 +				while (--n >= 0) {
   7.226 +					s1 = s1 + (uint)(buffer[offset++] & 0xff);
   7.227 +					s2 = s2 + s1;
   7.228 +				}
   7.229 +				s1 %= BASE;
   7.230 +				s2 %= BASE;
   7.231 +			}
   7.232 +			
   7.233 +			checksum = (s2 << 16) | s1;
   7.234 +		}
   7.235 +		
   7.236 +		#region Instance Fields
   7.237 +		uint checksum;
   7.238 +		#endregion
   7.239 +	}
   7.240 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/Checksums/CRC32.cs	Sat Oct 30 14:03:17 2010 +0000
     8.3 @@ -0,0 +1,223 @@
     8.4 +// CRC32.cs - Computes CRC32 data checksum of a data stream
     8.5 +// Copyright (C) 2001 Mike Krueger
     8.6 +//
     8.7 +// This file was translated from java, it was part of the GNU Classpath
     8.8 +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
     8.9 +//
    8.10 +// This program is free software; you can redistribute it and/or
    8.11 +// modify it under the terms of the GNU General Public License
    8.12 +// as published by the Free Software Foundation; either version 2
    8.13 +// of the License, or (at your option) any later version.
    8.14 +//
    8.15 +// This program is distributed in the hope that it will be useful,
    8.16 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.17 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.18 +// GNU General Public License for more details.
    8.19 +//
    8.20 +// You should have received a copy of the GNU General Public License
    8.21 +// along with this program; if not, write to the Free Software
    8.22 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    8.23 +//
    8.24 +// Linking this library statically or dynamically with other modules is
    8.25 +// making a combined work based on this library.  Thus, the terms and
    8.26 +// conditions of the GNU General Public License cover the whole
    8.27 +// combination.
    8.28 +// 
    8.29 +// As a special exception, the copyright holders of this library give you
    8.30 +// permission to link this library with independent modules to produce an
    8.31 +// executable, regardless of the license terms of these independent
    8.32 +// modules, and to copy and distribute the resulting executable under
    8.33 +// terms of your choice, provided that you also meet, for each linked
    8.34 +// independent module, the terms and conditions of the license of that
    8.35 +// module.  An independent module is a module which is not derived from
    8.36 +// or based on this library.  If you modify this library, you may extend
    8.37 +// this exception to your version of the library, but you are not
    8.38 +// obligated to do so.  If you do not wish to do so, delete this
    8.39 +// exception statement from your version.
    8.40 +
    8.41 +using System;
    8.42 +
    8.43 +namespace ICSharpCode.SharpZipLib.Checksums 
    8.44 +{
    8.45 +	
    8.46 +	/// <summary>
    8.47 +	/// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
    8.48 +	/// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
    8.49 +	///
    8.50 +	/// Polynomials over GF(2) are represented in binary, one bit per coefficient,
    8.51 +	/// with the lowest powers in the most significant bit.  Then adding polynomials
    8.52 +	/// is just exclusive-or, and multiplying a polynomial by x is a right shift by
    8.53 +	/// one.  If we call the above polynomial p, and represent a byte as the
    8.54 +	/// polynomial q, also with the lowest power in the most significant bit (so the
    8.55 +	/// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
    8.56 +	/// where a mod b means the remainder after dividing a by b.
    8.57 +	///
    8.58 +	/// This calculation is done using the shift-register method of multiplying and
    8.59 +	/// taking the remainder.  The register is initialized to zero, and for each
    8.60 +	/// incoming bit, x^32 is added mod p to the register if the bit is a one (where
    8.61 +	/// x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
    8.62 +	/// x (which is shifting right by one and adding x^32 mod p if the bit shifted
    8.63 +	/// out is a one).  We start with the highest power (least significant bit) of
    8.64 +	/// q and repeat for all eight bits of q.
    8.65 +	///
    8.66 +	/// The table is simply the CRC of all possible eight bit values.  This is all
    8.67 +	/// the information needed to generate CRC's on data a byte at a time for all
    8.68 +	/// combinations of CRC register values and incoming bytes.
    8.69 +	/// </summary>
    8.70 +	public sealed class Crc32 : IChecksum
    8.71 +	{
    8.72 +		const uint CrcSeed = 0xFFFFFFFF;
    8.73 +		
    8.74 +		readonly static uint[] CrcTable = new uint[] {
    8.75 +			0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419,
    8.76 +			0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4,
    8.77 +			0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07,
    8.78 +			0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
    8.79 +			0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856,
    8.80 +			0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
    8.81 +			0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
    8.82 +			0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
    8.83 +			0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
    8.84 +			0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A,
    8.85 +			0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599,
    8.86 +			0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
    8.87 +			0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190,
    8.88 +			0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
    8.89 +			0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E,
    8.90 +			0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
    8.91 +			0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
    8.92 +			0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
    8.93 +			0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3,
    8.94 +			0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
    8.95 +			0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
    8.96 +			0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
    8.97 +			0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010,
    8.98 +			0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
    8.99 +			0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17,
   8.100 +			0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6,
   8.101 +			0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
   8.102 +			0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
   8.103 +			0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344,
   8.104 +			0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
   8.105 +			0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A,
   8.106 +			0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
   8.107 +			0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1,
   8.108 +			0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
   8.109 +			0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
   8.110 +			0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
   8.111 +			0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE,
   8.112 +			0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
   8.113 +			0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C,
   8.114 +			0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
   8.115 +			0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B,
   8.116 +			0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
   8.117 +			0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1,
   8.118 +			0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
   8.119 +			0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
   8.120 +			0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
   8.121 +			0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66,
   8.122 +			0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
   8.123 +			0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
   8.124 +			0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8,
   8.125 +			0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
   8.126 +			0x2D02EF8D
   8.127 +		};
   8.128 +		
   8.129 +		internal static uint ComputeCrc32(uint oldCrc, byte value)
   8.130 +		{
   8.131 +			return (uint)(Crc32.CrcTable[(oldCrc ^ value) & 0xFF] ^ (oldCrc >> 8));
   8.132 +		}
   8.133 +		
   8.134 +		/// <summary>
   8.135 +		/// The crc data checksum so far.
   8.136 +		/// </summary>
   8.137 +		uint crc;
   8.138 +		
   8.139 +		/// <summary>
   8.140 +		/// Returns the CRC32 data checksum computed so far.
   8.141 +		/// </summary>
   8.142 +		public long Value {
   8.143 +			get {
   8.144 +				return (long)crc;
   8.145 +			}
   8.146 +			set {
   8.147 +				crc = (uint)value;
   8.148 +			}
   8.149 +		}
   8.150 +		
   8.151 +		/// <summary>
   8.152 +		/// Resets the CRC32 data checksum as if no update was ever called.
   8.153 +		/// </summary>
   8.154 +		public void Reset() 
   8.155 +		{ 
   8.156 +			crc = 0; 
   8.157 +		}
   8.158 +		
   8.159 +		/// <summary>
   8.160 +		/// Updates the checksum with the int bval.
   8.161 +		/// </summary>
   8.162 +		/// <param name = "value">
   8.163 +		/// the byte is taken as the lower 8 bits of value
   8.164 +		/// </param>
   8.165 +		public void Update(int value)
   8.166 +		{
   8.167 +			crc ^= CrcSeed;
   8.168 +			crc  = CrcTable[(crc ^ value) & 0xFF] ^ (crc >> 8);
   8.169 +			crc ^= CrcSeed;
   8.170 +		}
   8.171 +		
   8.172 +		/// <summary>
   8.173 +		/// Updates the checksum with the bytes taken from the array.
   8.174 +		/// </summary>
   8.175 +		/// <param name="buffer">
   8.176 +		/// buffer an array of bytes
   8.177 +		/// </param>
   8.178 +		public void Update(byte[] buffer)
   8.179 +		{
   8.180 +			if (buffer == null) {
   8.181 +				throw new ArgumentNullException("buffer");
   8.182 +			}
   8.183 +			
   8.184 +			Update(buffer, 0, buffer.Length);
   8.185 +		}
   8.186 +		
   8.187 +		/// <summary>
   8.188 +		/// Adds the byte array to the data checksum.
   8.189 +		/// </summary>
   8.190 +		/// <param name = "buffer">
   8.191 +		/// The buffer which contains the data
   8.192 +		/// </param>
   8.193 +		/// <param name = "offset">
   8.194 +		/// The offset in the buffer where the data starts
   8.195 +		/// </param>
   8.196 +		/// <param name = "count">
   8.197 +		/// The number of data bytes to update the CRC with.
   8.198 +		/// </param>
   8.199 +		public void Update(byte[] buffer, int offset, int count)
   8.200 +		{
   8.201 +			if (buffer == null) {
   8.202 +				throw new ArgumentNullException("buffer");
   8.203 +			}
   8.204 +			
   8.205 +			if ( count < 0 ) {
   8.206 +#if NETCF_1_0
   8.207 +				throw new ArgumentOutOfRangeException("count");
   8.208 +#else
   8.209 +				throw new ArgumentOutOfRangeException("count", "Count cannot be less than zero");
   8.210 +#endif				
   8.211 +			}
   8.212 +			
   8.213 +			if (offset < 0 || offset + count > buffer.Length) {
   8.214 +				throw new ArgumentOutOfRangeException("offset");
   8.215 +			}
   8.216 +			
   8.217 +			crc ^= CrcSeed;
   8.218 +			
   8.219 +			while (--count >= 0) {
   8.220 +				crc = CrcTable[(crc ^ buffer[offset++]) & 0xFF] ^ (crc >> 8);
   8.221 +			}
   8.222 +			
   8.223 +			crc ^= CrcSeed;
   8.224 +		}
   8.225 +	}
   8.226 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/Checksums/IChecksum.cs	Sat Oct 30 14:03:17 2010 +0000
     9.3 @@ -0,0 +1,93 @@
     9.4 +// IChecksum.cs - Interface to compute a data checksum
     9.5 +// Copyright (C) 2001 Mike Krueger
     9.6 +//
     9.7 +// This file was translated from java, it was part of the GNU Classpath
     9.8 +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
     9.9 +//
    9.10 +// This program is free software; you can redistribute it and/or
    9.11 +// modify it under the terms of the GNU General Public License
    9.12 +// as published by the Free Software Foundation; either version 2
    9.13 +// of the License, or (at your option) any later version.
    9.14 +//
    9.15 +// This program is distributed in the hope that it will be useful,
    9.16 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.17 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.18 +// GNU General Public License for more details.
    9.19 +//
    9.20 +// You should have received a copy of the GNU General Public License
    9.21 +// along with this program; if not, write to the Free Software
    9.22 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    9.23 +//
    9.24 +// Linking this library statically or dynamically with other modules is
    9.25 +// making a combined work based on this library.  Thus, the terms and
    9.26 +// conditions of the GNU General Public License cover the whole
    9.27 +// combination.
    9.28 +// 
    9.29 +// As a special exception, the copyright holders of this library give you
    9.30 +// permission to link this library with independent modules to produce an
    9.31 +// executable, regardless of the license terms of these independent
    9.32 +// modules, and to copy and distribute the resulting executable under
    9.33 +// terms of your choice, provided that you also meet, for each linked
    9.34 +// independent module, the terms and conditions of the license of that
    9.35 +// module.  An independent module is a module which is not derived from
    9.36 +// or based on this library.  If you modify this library, you may extend
    9.37 +// this exception to your version of the library, but you are not
    9.38 +// obligated to do so.  If you do not wish to do so, delete this
    9.39 +// exception statement from your version.
    9.40 +
    9.41 +namespace ICSharpCode.SharpZipLib.Checksums 
    9.42 +{
    9.43 +	
    9.44 +	/// <summary>
    9.45 +	/// Interface to compute a data checksum used by checked input/output streams.
    9.46 +	/// A data checksum can be updated by one byte or with a byte array. After each
    9.47 +	/// update the value of the current checksum can be returned by calling
    9.48 +	/// <code>getValue</code>. The complete checksum object can also be reset
    9.49 +	/// so it can be used again with new data.
    9.50 +	/// </summary>
    9.51 +	public interface IChecksum
    9.52 +	{
    9.53 +		/// <summary>
    9.54 +		/// Returns the data checksum computed so far.
    9.55 +		/// </summary>
    9.56 +		long Value 
    9.57 +		{
    9.58 +			get;
    9.59 +		}
    9.60 +		
    9.61 +		/// <summary>
    9.62 +		/// Resets the data checksum as if no update was ever called.
    9.63 +		/// </summary>
    9.64 +		void Reset();
    9.65 +		
    9.66 +		/// <summary>
    9.67 +		/// Adds one byte to the data checksum.
    9.68 +		/// </summary>
    9.69 +		/// <param name = "value">
    9.70 +		/// the data value to add. The high byte of the int is ignored.
    9.71 +		/// </param>
    9.72 +		void Update(int value);
    9.73 +		
    9.74 +		/// <summary>
    9.75 +		/// Updates the data checksum with the bytes taken from the array.
    9.76 +		/// </summary>
    9.77 +		/// <param name="buffer">
    9.78 +		/// buffer an array of bytes
    9.79 +		/// </param>
    9.80 +		void Update(byte[] buffer);
    9.81 +		
    9.82 +		/// <summary>
    9.83 +		/// Adds the byte array to the data checksum.
    9.84 +		/// </summary>
    9.85 +		/// <param name = "buffer">
    9.86 +		/// The buffer which contains the data
    9.87 +		/// </param>
    9.88 +		/// <param name = "offset">
    9.89 +		/// The offset in the buffer where the data starts
    9.90 +		/// </param>
    9.91 +		/// <param name = "count">
    9.92 +		/// the number of data bytes to add.
    9.93 +		/// </param>
    9.94 +		void Update(byte[] buffer, int offset, int count);
    9.95 +	}
    9.96 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/Checksums/StrangeCRC.cs	Sat Oct 30 14:03:17 2010 +0000
    10.3 @@ -0,0 +1,208 @@
    10.4 +// StrangeCRC.cs - computes a crc used in the bziplib
    10.5 +//
    10.6 +// Copyright (C) 2001 Mike Krueger
    10.7 +//
    10.8 +// This file was translated from java, it was part of the GNU Classpath
    10.9 +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
   10.10 +//
   10.11 +// This program is free software; you can redistribute it and/or
   10.12 +// modify it under the terms of the GNU General Public License
   10.13 +// as published by the Free Software Foundation; either version 2
   10.14 +// of the License, or (at your option) any later version.
   10.15 +//
   10.16 +// This program is distributed in the hope that it will be useful,
   10.17 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.18 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.19 +// GNU General Public License for more details.
   10.20 +//
   10.21 +// You should have received a copy of the GNU General Public License
   10.22 +// along with this program; if not, write to the Free Software
   10.23 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   10.24 +//
   10.25 +// Linking this library statically or dynamically with other modules is
   10.26 +// making a combined work based on this library.  Thus, the terms and
   10.27 +// conditions of the GNU General Public License cover the whole
   10.28 +// combination.
   10.29 +// 
   10.30 +// As a special exception, the copyright holders of this library give you
   10.31 +// permission to link this library with independent modules to produce an
   10.32 +// executable, regardless of the license terms of these independent
   10.33 +// modules, and to copy and distribute the resulting executable under
   10.34 +// terms of your choice, provided that you also meet, for each linked
   10.35 +// independent module, the terms and conditions of the license of that
   10.36 +// module.  An independent module is a module which is not derived from
   10.37 +// or based on this library.  If you modify this library, you may extend
   10.38 +// this exception to your version of the library, but you are not
   10.39 +// obligated to do so.  If you do not wish to do so, delete this
   10.40 +// exception statement from your version.
   10.41 +
   10.42 +using System;
   10.43 +
   10.44 +namespace ICSharpCode.SharpZipLib.Checksums 
   10.45 +{
   10.46 +	/// <summary>
   10.47 +	/// Bzip2 checksum algorithm
   10.48 +	/// </summary>
   10.49 +	public class StrangeCRC : IChecksum
   10.50 +	{
   10.51 +		readonly static uint[] crc32Table = {
   10.52 +			0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
   10.53 +			0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
   10.54 +			0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
   10.55 +			0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
   10.56 +			0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
   10.57 +			0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
   10.58 +			0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
   10.59 +			0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
   10.60 +			0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
   10.61 +			0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
   10.62 +			0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
   10.63 +			0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
   10.64 +			0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
   10.65 +			0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
   10.66 +			0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
   10.67 +			0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
   10.68 +			0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
   10.69 +			0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
   10.70 +			0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
   10.71 +			0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
   10.72 +			0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
   10.73 +			0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
   10.74 +			0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
   10.75 +			0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
   10.76 +			0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
   10.77 +			0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
   10.78 +			0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
   10.79 +			0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
   10.80 +			0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
   10.81 +			0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
   10.82 +			0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
   10.83 +			0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
   10.84 +			0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
   10.85 +			0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
   10.86 +			0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
   10.87 +			0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
   10.88 +			0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
   10.89 +			0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
   10.90 +			0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
   10.91 +			0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
   10.92 +			0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
   10.93 +			0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
   10.94 +			0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
   10.95 +			0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
   10.96 +			0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
   10.97 +			0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
   10.98 +			0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
   10.99 +			0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
  10.100 +			0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
  10.101 +			0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
  10.102 +			0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
  10.103 +			0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
  10.104 +			0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
  10.105 +			0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
  10.106 +			0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
  10.107 +			0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
  10.108 +			0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
  10.109 +			0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
  10.110 +			0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
  10.111 +			0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
  10.112 +			0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
  10.113 +			0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
  10.114 +			0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
  10.115 +			0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
  10.116 +		};
  10.117 +		
  10.118 +		int globalCrc;
  10.119 +
  10.120 +		/// <summary>
  10.121 +		/// Initialise a default instance of <see cref="StrangeCRC"></see>
  10.122 +		/// </summary>	
  10.123 +		public StrangeCRC() 
  10.124 +		{
  10.125 +			Reset();
  10.126 +		}
  10.127 +
  10.128 +		/// <summary>
  10.129 +		/// Reset the state of Crc.
  10.130 +		/// </summary>
  10.131 +		public void Reset()
  10.132 +		{
  10.133 +			globalCrc = -1;
  10.134 +		}
  10.135 +
  10.136 +		/// <summary>
  10.137 +		/// Get the current Crc value.
  10.138 +		/// </summary>
  10.139 +		public long Value {
  10.140 +			get {
  10.141 +				return ~globalCrc;
  10.142 +			}
  10.143 +		}
  10.144 +		
  10.145 +		/// <summary>
  10.146 +		/// Update the Crc value.
  10.147 +		/// </summary>
  10.148 +		/// <param name="value">data update is based on</param>
  10.149 +		public void Update(int value)
  10.150 +		{
  10.151 +			int temp = (globalCrc >> 24) ^ value;
  10.152 +			if (temp < 0) {
  10.153 +				temp = 256 + temp;
  10.154 +			}
  10.155 +			globalCrc = unchecked((int)((globalCrc << 8) ^ crc32Table[temp]));
  10.156 +		}
  10.157 +
  10.158 +		/// <summary>
  10.159 +		/// Update Crc based on a block of data
  10.160 +		/// </summary>
  10.161 +		/// <param name="buffer">The buffer containing data to update the crc with.</param>
  10.162 +		public void Update(byte[] buffer)
  10.163 +		{
  10.164 +			if (buffer == null) {
  10.165 +				throw new ArgumentNullException("buffer");
  10.166 +			}
  10.167 +			
  10.168 +			Update(buffer, 0, buffer.Length);
  10.169 +		}
  10.170 +		
  10.171 +		/// <summary>
  10.172 +		/// Update Crc based on a portion of a block of data
  10.173 +		/// </summary>
  10.174 +		/// <param name="buffer">block of data</param>
  10.175 +		/// <param name="offset">index of first byte to use</param>
  10.176 +		/// <param name="count">number of bytes to use</param>
  10.177 +		public void Update(byte[] buffer, int offset, int count)
  10.178 +		{
  10.179 +			if (buffer == null) {
  10.180 +				throw new ArgumentNullException("buffer");
  10.181 +			}
  10.182 +			
  10.183 +			if ( offset < 0 )
  10.184 +			{
  10.185 +#if NETCF_1_0
  10.186 +				throw new ArgumentOutOfRangeException("offset");
  10.187 +#else
  10.188 +				throw new ArgumentOutOfRangeException("offset", "cannot be less than zero");
  10.189 +#endif				
  10.190 +			}
  10.191 +
  10.192 +			if ( count < 0 )
  10.193 +			{
  10.194 +#if NETCF_1_0
  10.195 +				throw new ArgumentOutOfRangeException("count");
  10.196 +#else
  10.197 +				throw new ArgumentOutOfRangeException("count", "cannot be less than zero");
  10.198 +#endif
  10.199 +			}
  10.200 +
  10.201 +			if ( offset + count > buffer.Length )
  10.202 +			{
  10.203 +				throw new ArgumentOutOfRangeException("count");
  10.204 +			}
  10.205 +			
  10.206 +			for (int i = 0; i < count; ++i) {
  10.207 +				Update(buffer[offset++]);
  10.208 +			}
  10.209 +		}
  10.210 +	}
  10.211 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/Core/FileSystemScanner.cs	Sat Oct 30 14:03:17 2010 +0000
    11.3 @@ -0,0 +1,533 @@
    11.4 +// FileSystemScanner.cs
    11.5 +//
    11.6 +// Copyright 2005 John Reilly
    11.7 +//
    11.8 +// This program is free software; you can redistribute it and/or
    11.9 +// modify it under the terms of the GNU General Public License
   11.10 +// as published by the Free Software Foundation; either version 2
   11.11 +// of the License, or (at your option) any later version.
   11.12 +//
   11.13 +// This program is distributed in the hope that it will be useful,
   11.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.16 +// GNU General Public License for more details.
   11.17 +//
   11.18 +// You should have received a copy of the GNU General Public License
   11.19 +// along with this program; if not, write to the Free Software
   11.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   11.21 +//
   11.22 +// Linking this library statically or dynamically with other modules is
   11.23 +// making a combined work based on this library.  Thus, the terms and
   11.24 +// conditions of the GNU General Public License cover the whole
   11.25 +// combination.
   11.26 +// 
   11.27 +// As a special exception, the copyright holders of this library give you
   11.28 +// permission to link this library with independent modules to produce an
   11.29 +// executable, regardless of the license terms of these independent
   11.30 +// modules, and to copy and distribute the resulting executable under
   11.31 +// terms of your choice, provided that you also meet, for each linked
   11.32 +// independent module, the terms and conditions of the license of that
   11.33 +// module.  An independent module is a module which is not derived from
   11.34 +// or based on this library.  If you modify this library, you may extend
   11.35 +// this exception to your version of the library, but you are not
   11.36 +// obligated to do so.  If you do not wish to do so, delete this
   11.37 +// exception statement from your version.
   11.38 +
   11.39 +
   11.40 +using System;
   11.41 +
   11.42 +namespace ICSharpCode.SharpZipLib.Core
   11.43 +{
   11.44 +	#region EventArgs
   11.45 +	/// <summary>
   11.46 +	/// Event arguments for scanning.
   11.47 +	/// </summary>
   11.48 +	public class ScanEventArgs : EventArgs
   11.49 +	{
   11.50 +		#region Constructors
   11.51 +		/// <summary>
   11.52 +		/// Initialise a new instance of <see cref="ScanEventArgs"/>
   11.53 +		/// </summary>
   11.54 +		/// <param name="name">The file or directory name.</param>
   11.55 +		public ScanEventArgs(string name)
   11.56 +		{
   11.57 +			name_ = name;
   11.58 +		}
   11.59 +		#endregion
   11.60 +		
   11.61 +		/// <summary>
   11.62 +		/// The file or directory name for this event.
   11.63 +		/// </summary>
   11.64 +		public string Name
   11.65 +		{
   11.66 +			get { return name_; }
   11.67 +		}
   11.68 +		
   11.69 +		/// <summary>
   11.70 +		/// Get set a value indicating if scanning should continue or not.
   11.71 +		/// </summary>
   11.72 +		public bool ContinueRunning
   11.73 +		{
   11.74 +			get { return continueRunning_; }
   11.75 +			set { continueRunning_ = value; }
   11.76 +		}
   11.77 +		
   11.78 +		#region Instance Fields
   11.79 +		string name_;
   11.80 +		bool continueRunning_ = true;
   11.81 +		#endregion
   11.82 +	}
   11.83 +
   11.84 +	/// <summary>
   11.85 +	/// Event arguments during processing of a single file or directory.
   11.86 +	/// </summary>
   11.87 +	public class ProgressEventArgs : EventArgs
   11.88 +	{
   11.89 +		#region Constructors
   11.90 +		/// <summary>
   11.91 +		/// Initialise a new instance of <see cref="ScanEventArgs"/>
   11.92 +		/// </summary>
   11.93 +		/// <param name="name">The file or directory name if known.</param>
   11.94 +		/// <param name="processed">The number of bytes processed so far</param>
   11.95 +		/// <param name="target">The total number of bytes to process, 0 if not known</param>
   11.96 +		public ProgressEventArgs(string name, long processed, long target)
   11.97 +		{
   11.98 +			name_ = name;
   11.99 +			processed_ = processed;
  11.100 +			target_ = target;
  11.101 +		}
  11.102 +		#endregion
  11.103 +		
  11.104 +		/// <summary>
  11.105 +		/// The name for this event if known.
  11.106 +		/// </summary>
  11.107 +		public string Name
  11.108 +		{
  11.109 +			get { return name_; }
  11.110 +		}
  11.111 +		
  11.112 +		/// <summary>
  11.113 +		/// Get set a value indicating wether scanning should continue or not.
  11.114 +		/// </summary>
  11.115 +		public bool ContinueRunning
  11.116 +		{
  11.117 +			get { return continueRunning_; }
  11.118 +			set { continueRunning_ = value; }
  11.119 +		}
  11.120 +
  11.121 +		/// <summary>
  11.122 +		/// Get a percentage representing how much of the <see cref="Target"></see> has been processed
  11.123 +		/// </summary>
  11.124 +		/// <value>0.0 to 100.0 percent; 0 if target is not known.</value>
  11.125 +		public float PercentComplete
  11.126 +		{
  11.127 +			get
  11.128 +			{
  11.129 +			    float result;
  11.130 +				if (target_ <= 0)
  11.131 +				{
  11.132 +					result = 0;
  11.133 +				}
  11.134 +				else
  11.135 +				{
  11.136 +					result = ((float)processed_ / (float)target_) * 100.0f;
  11.137 +				}
  11.138 +			    return result;
  11.139 +			}
  11.140 +		}
  11.141 +		
  11.142 +		/// <summary>
  11.143 +		/// The number of bytes processed so far
  11.144 +		/// </summary>
  11.145 +		public long Processed
  11.146 +		{
  11.147 +			get { return processed_; }
  11.148 +		}
  11.149 +
  11.150 +		/// <summary>
  11.151 +		/// The number of bytes to process.
  11.152 +		/// </summary>
  11.153 +		/// <remarks>Target may be 0 or negative if the value isnt known.</remarks>
  11.154 +		public long Target
  11.155 +		{
  11.156 +			get { return target_; }
  11.157 +		}
  11.158 +		
  11.159 +		#region Instance Fields
  11.160 +		string name_;
  11.161 +		long processed_;
  11.162 +		long target_;
  11.163 +		bool continueRunning_ = true;
  11.164 +		#endregion
  11.165 +	}
  11.166 +
  11.167 +	/// <summary>
  11.168 +	/// Event arguments for directories.
  11.169 +	/// </summary>
  11.170 +	public class DirectoryEventArgs : ScanEventArgs
  11.171 +	{
  11.172 +		#region Constructors
  11.173 +		/// <summary>
  11.174 +		/// Initialize an instance of <see cref="DirectoryEventArgs"></see>.
  11.175 +		/// </summary>
  11.176 +		/// <param name="name">The name for this directory.</param>
  11.177 +		/// <param name="hasMatchingFiles">Flag value indicating if any matching files are contained in this directory.</param>
  11.178 +		public DirectoryEventArgs(string name, bool hasMatchingFiles)
  11.179 +			: base (name)
  11.180 +		{
  11.181 +			hasMatchingFiles_ = hasMatchingFiles;
  11.182 +		}
  11.183 +		#endregion
  11.184 +		
  11.185 +		/// <summary>
  11.186 +		/// Get a value indicating if the directory contains any matching files or not.
  11.187 +		/// </summary>
  11.188 +		public bool HasMatchingFiles
  11.189 +		{
  11.190 +			get { return hasMatchingFiles_; }
  11.191 +		}
  11.192 +		
  11.193 +		#region Instance Fields
  11.194 +		bool hasMatchingFiles_;
  11.195 +		#endregion
  11.196 +	}
  11.197 +	
  11.198 +	/// <summary>
  11.199 +	/// Arguments passed when scan failures are detected.
  11.200 +	/// </summary>
  11.201 +	public class ScanFailureEventArgs : EventArgs
  11.202 +	{
  11.203 +		#region Constructors
  11.204 +		/// <summary>
  11.205 +		/// Initialise a new instance of <see cref="ScanFailureEventArgs"></see>
  11.206 +		/// </summary>
  11.207 +		/// <param name="name">The name to apply.</param>
  11.208 +		/// <param name="e">The exception to use.</param>
  11.209 +		public ScanFailureEventArgs(string name, Exception e)
  11.210 +		{
  11.211 +			name_ = name;
  11.212 +			exception_ = e;
  11.213 +			continueRunning_ = true;
  11.214 +		}
  11.215 +		#endregion
  11.216 +		
  11.217 +		/// <summary>
  11.218 +		/// The applicable name.
  11.219 +		/// </summary>
  11.220 +		public string Name
  11.221 +		{
  11.222 +			get { return name_; }
  11.223 +		}
  11.224 +		
  11.225 +		/// <summary>
  11.226 +		/// The applicable exception.
  11.227 +		/// </summary>
  11.228 +		public Exception Exception
  11.229 +		{
  11.230 +			get { return exception_; }
  11.231 +		}
  11.232 +		
  11.233 +		/// <summary>
  11.234 +		/// Get / set a value indicating wether scanning should continue.
  11.235 +		/// </summary>
  11.236 +		public bool ContinueRunning
  11.237 +		{
  11.238 +			get { return continueRunning_; }
  11.239 +			set { continueRunning_ = value; }
  11.240 +		}
  11.241 +		
  11.242 +		#region Instance Fields
  11.243 +		string name_;
  11.244 +		Exception exception_;
  11.245 +		bool continueRunning_;
  11.246 +		#endregion
  11.247 +	}
  11.248 +	
  11.249 +	#endregion
  11.250 +	
  11.251 +	#region Delegates
  11.252 +	/// <summary>
  11.253 +	/// Delegate invoked before starting to process a directory.
  11.254 +	/// </summary>
  11.255 +	public delegate void ProcessDirectoryHandler(object sender, DirectoryEventArgs e);
  11.256 +	
  11.257 +	/// <summary>
  11.258 +	/// Delegate invoked before starting to process a file.
  11.259 +	/// </summary>
  11.260 +	/// <param name="sender">The source of the event</param>
  11.261 +	/// <param name="e">The event arguments.</param>
  11.262 +	public delegate void ProcessFileHandler(object sender, ScanEventArgs e);
  11.263 +
  11.264 +	/// <summary>
  11.265 +	/// Delegate invoked during processing of a file or directory
  11.266 +	/// </summary>
  11.267 +	/// <param name="sender">The source of the event</param>
  11.268 +	/// <param name="e">The event arguments.</param>
  11.269 +	public delegate void ProgressHandler(object sender, ProgressEventArgs e);
  11.270 +
  11.271 +	/// <summary>
  11.272 +	/// Delegate invoked when a file has been completely processed.
  11.273 +	/// </summary>
  11.274 +	/// <param name="sender">The source of the event</param>
  11.275 +	/// <param name="e">The event arguments.</param>
  11.276 +	public delegate void CompletedFileHandler(object sender, ScanEventArgs e);
  11.277 +	
  11.278 +	/// <summary>
  11.279 +	/// Delegate invoked when a directory failure is detected.
  11.280 +	/// </summary>
  11.281 +	/// <param name="sender">The source of the event</param>
  11.282 +	/// <param name="e">The event arguments.</param>
  11.283 +	public delegate void DirectoryFailureHandler(object sender, ScanFailureEventArgs e);
  11.284 +	
  11.285 +	/// <summary>
  11.286 +	/// Delegate invoked when a file failure is detected.
  11.287 +	/// </summary>
  11.288 +	/// <param name="sender">The source of the event</param>
  11.289 +	/// <param name="e">The event arguments.</param>
  11.290 +	public delegate void FileFailureHandler(object sender, ScanFailureEventArgs e);
  11.291 +	#endregion
  11.292 +
  11.293 +	/// <summary>
  11.294 +	/// FileSystemScanner provides facilities scanning of files and directories.
  11.295 +	/// </summary>
  11.296 +	public class FileSystemScanner
  11.297 +	{
  11.298 +		#region Constructors
  11.299 +		/// <summary>
  11.300 +		/// Initialise a new instance of <see cref="FileSystemScanner"></see>
  11.301 +		/// </summary>
  11.302 +		/// <param name="filter">The <see cref="PathFilter">file filter</see> to apply when scanning.</param>
  11.303 +		public FileSystemScanner(string filter)
  11.304 +		{
  11.305 +			fileFilter_ = new PathFilter(filter);
  11.306 +		}
  11.307 +		
  11.308 +		/// <summary>
  11.309 +		/// Initialise a new instance of <see cref="FileSystemScanner"></see>
  11.310 +		/// </summary>
  11.311 +		/// <param name="fileFilter">The <see cref="PathFilter">file filter</see> to apply.</param>
  11.312 +		/// <param name="directoryFilter">The <see cref="PathFilter"> directory filter</see> to apply.</param>
  11.313 +		public FileSystemScanner(string fileFilter, string directoryFilter)
  11.314 +		{
  11.315 +			fileFilter_ = new PathFilter(fileFilter);
  11.316 +			directoryFilter_ = new PathFilter(directoryFilter);
  11.317 +		}
  11.318 +		
  11.319 +		/// <summary>
  11.320 +		/// Initialise a new instance of <see cref="FileSystemScanner"></see>
  11.321 +		/// </summary>
  11.322 +		/// <param name="fileFilter">The file <see cref="IScanFilter">filter</see> to apply.</param>
  11.323 +		public FileSystemScanner(IScanFilter fileFilter)
  11.324 +		{
  11.325 +			fileFilter_ = fileFilter;
  11.326 +		}
  11.327 +		
  11.328 +		/// <summary>
  11.329 +		/// Initialise a new instance of <see cref="FileSystemScanner"></see>
  11.330 +		/// </summary>
  11.331 +		/// <param name="fileFilter">The file <see cref="IScanFilter">filter</see>  to apply.</param>
  11.332 +		/// <param name="directoryFilter">The directory <see cref="IScanFilter">filter</see>  to apply.</param>
  11.333 +		public FileSystemScanner(IScanFilter fileFilter, IScanFilter directoryFilter)
  11.334 +		{
  11.335 +			fileFilter_ = fileFilter;
  11.336 +			directoryFilter_ = directoryFilter;
  11.337 +		}
  11.338 +		#endregion
  11.339 +
  11.340 +		#region Delegates
  11.341 +		/// <summary>
  11.342 +		/// Delegate to invoke when a directory is processed.
  11.343 +		/// </summary>
  11.344 +		public ProcessDirectoryHandler ProcessDirectory;
  11.345 +		
  11.346 +		/// <summary>
  11.347 +		/// Delegate to invoke when a file is processed.
  11.348 +		/// </summary>
  11.349 +		public ProcessFileHandler ProcessFile;
  11.350 +
  11.351 +		/// <summary>
  11.352 +		/// Delegate to invoke when processing for a file has finished.
  11.353 +		/// </summary>
  11.354 +		public CompletedFileHandler CompletedFile;
  11.355 +
  11.356 +		/// <summary>
  11.357 +		/// Delegate to invoke when a directory failure is detected.
  11.358 +		/// </summary>
  11.359 +		public DirectoryFailureHandler DirectoryFailure;
  11.360 +		
  11.361 +		/// <summary>
  11.362 +		/// Delegate to invoke when a file failure is detected.
  11.363 +		/// </summary>
  11.364 +		public FileFailureHandler FileFailure;
  11.365 +		#endregion
  11.366 +
  11.367 +		/// <summary>
  11.368 +		/// Raise the DirectoryFailure event.
  11.369 +		/// </summary>
  11.370 +		/// <param name="directory">The directory name.</param>
  11.371 +		/// <param name="e">The exception detected.</param>
  11.372 +		bool OnDirectoryFailure(string directory, Exception e)
  11.373 +		{
  11.374 +            DirectoryFailureHandler handler = DirectoryFailure;
  11.375 +            bool result = (handler != null);
  11.376 +            if ( result ) {
  11.377 +				ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e);
  11.378 +				handler(this, args);
  11.379 +				alive_ = args.ContinueRunning;
  11.380 +			}
  11.381 +            return result;
  11.382 +		}
  11.383 +		
  11.384 +		/// <summary>
  11.385 +		/// Raise the FileFailure event.
  11.386 +		/// </summary>
  11.387 +		/// <param name="file">The file name.</param>
  11.388 +		/// <param name="e">The exception detected.</param>
  11.389 +		bool OnFileFailure(string file, Exception e)
  11.390 +		{
  11.391 +            FileFailureHandler handler = FileFailure;
  11.392 +
  11.393 +            bool result = (handler != null);
  11.394 +
  11.395 +			if ( result ){
  11.396 +				ScanFailureEventArgs args = new ScanFailureEventArgs(file, e);
  11.397 +				FileFailure(this, args);
  11.398 +				alive_ = args.ContinueRunning;
  11.399 +			}
  11.400 +            return result;
  11.401 +		}
  11.402 +
  11.403 +		/// <summary>
  11.404 +		/// Raise the ProcessFile event.
  11.405 +		/// </summary>
  11.406 +		/// <param name="file">The file name.</param>
  11.407 +		void OnProcessFile(string file)
  11.408 +		{
  11.409 +			ProcessFileHandler handler = ProcessFile;
  11.410 +
  11.411 +			if ( handler!= null ) {
  11.412 +				ScanEventArgs args = new ScanEventArgs(file);
  11.413 +				handler(this, args);
  11.414 +				alive_ = args.ContinueRunning;
  11.415 +			}
  11.416 +		}
  11.417 +
  11.418 +		/// <summary>
  11.419 +		/// Raise the complete file event
  11.420 +		/// </summary>
  11.421 +		/// <param name="file">The file name</param>
  11.422 +		void OnCompleteFile(string file)
  11.423 +		{
  11.424 +			CompletedFileHandler handler = CompletedFile;
  11.425 +
  11.426 +			if (handler != null)
  11.427 +			{
  11.428 +				ScanEventArgs args = new ScanEventArgs(file);
  11.429 +				handler(this, args);
  11.430 +				alive_ = args.ContinueRunning;
  11.431 +			}
  11.432 +		}
  11.433 +
  11.434 +		/// <summary>
  11.435 +		/// Raise the ProcessDirectory event.
  11.436 +		/// </summary>
  11.437 +		/// <param name="directory">The directory name.</param>
  11.438 +		/// <param name="hasMatchingFiles">Flag indicating if the directory has matching files.</param>
  11.439 +		void OnProcessDirectory(string directory, bool hasMatchingFiles)
  11.440 +		{
  11.441 +			ProcessDirectoryHandler handler = ProcessDirectory;
  11.442 +
  11.443 +			if ( handler != null ) {
  11.444 +				DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles);
  11.445 +				handler(this, args);
  11.446 +				alive_ = args.ContinueRunning;
  11.447 +			}
  11.448 +		}
  11.449 +
  11.450 +		/// <summary>
  11.451 +		/// Scan a directory.
  11.452 +		/// </summary>
  11.453 +		/// <param name="directory">The base directory to scan.</param>
  11.454 +		/// <param name="recurse">True to recurse subdirectories, false to scan a single directory.</param>
  11.455 +		public void Scan(string directory, bool recurse)
  11.456 +		{
  11.457 +			alive_ = true;
  11.458 +			ScanDir(directory, recurse);
  11.459 +		}
  11.460 +		
  11.461 +		void ScanDir(string directory, bool recurse)
  11.462 +		{
  11.463 +
  11.464 +			try {
  11.465 +				string[] names = System.IO.Directory.GetFiles(directory);
  11.466 +				bool hasMatch = false;
  11.467 +				for (int fileIndex = 0; fileIndex < names.Length; ++fileIndex) {
  11.468 +					if ( !fileFilter_.IsMatch(names[fileIndex]) ) {
  11.469 +						names[fileIndex] = null;
  11.470 +					} else {
  11.471 +						hasMatch = true;
  11.472 +					}
  11.473 +				}
  11.474 +				
  11.475 +				OnProcessDirectory(directory, hasMatch);
  11.476 +				
  11.477 +				if ( alive_ && hasMatch ) {
  11.478 +					foreach (string fileName in names) {
  11.479 +						try {
  11.480 +							if ( fileName != null ) {
  11.481 +								OnProcessFile(fileName);
  11.482 +								if ( !alive_ ) {
  11.483 +									break;
  11.484 +								}
  11.485 +							}
  11.486 +						}
  11.487 +						catch (Exception e) {
  11.488 +                            if (!OnFileFailure(fileName, e)) {
  11.489 +                                throw;
  11.490 +                            }
  11.491 +						}
  11.492 +					}
  11.493 +				}
  11.494 +			}
  11.495 +			catch (Exception e) {
  11.496 +                if (!OnDirectoryFailure(directory, e)) {
  11.497 +                    throw;
  11.498 +                }
  11.499 +			}
  11.500 +
  11.501 +			if ( alive_ && recurse ) {
  11.502 +				try {
  11.503 +					string[] names = System.IO.Directory.GetDirectories(directory);
  11.504 +					foreach (string fulldir in names) {
  11.505 +						if ((directoryFilter_ == null) || (directoryFilter_.IsMatch(fulldir))) {
  11.506 +							ScanDir(fulldir, true);
  11.507 +							if ( !alive_ ) {
  11.508 +								break;
  11.509 +							}
  11.510 +						}
  11.511 +					}
  11.512 +				}
  11.513 +				catch (Exception e) {
  11.514 +                    if (!OnDirectoryFailure(directory, e)) {
  11.515 +                        throw;
  11.516 +                    }
  11.517 +				}
  11.518 +			}
  11.519 +		}
  11.520 +		
  11.521 +		#region Instance Fields
  11.522 +		/// <summary>
  11.523 +		/// The file filter currently in use.
  11.524 +		/// </summary>
  11.525 +		IScanFilter fileFilter_;
  11.526 +		/// <summary>
  11.527 +		/// The directory filter currently in use.
  11.528 +		/// </summary>
  11.529 +		IScanFilter directoryFilter_;
  11.530 +		/// <summary>
  11.531 +		/// Flag indicating if scanning should continue running.
  11.532 +		/// </summary>
  11.533 +		bool alive_;
  11.534 +		#endregion
  11.535 +	}
  11.536 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/Core/INameTransform.cs	Sat Oct 30 14:03:17 2010 +0000
    12.3 @@ -0,0 +1,57 @@
    12.4 +// INameTransform.cs
    12.5 +//
    12.6 +// Copyright 2005 John Reilly
    12.7 +//
    12.8 +// This program is free software; you can redistribute it and/or
    12.9 +// modify it under the terms of the GNU General Public License
   12.10 +// as published by the Free Software Foundation; either version 2
   12.11 +// of the License, or (at your option) any later version.
   12.12 +//
   12.13 +// This program is distributed in the hope that it will be useful,
   12.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.16 +// GNU General Public License for more details.
   12.17 +//
   12.18 +// You should have received a copy of the GNU General Public License
   12.19 +// along with this program; if not, write to the Free Software
   12.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   12.21 +//
   12.22 +// Linking this library statically or dynamically with other modules is
   12.23 +// making a combined work based on this library.  Thus, the terms and
   12.24 +// conditions of the GNU General Public License cover the whole
   12.25 +// combination.
   12.26 +// 
   12.27 +// As a special exception, the copyright holders of this library give you
   12.28 +// permission to link this library with independent modules to produce an
   12.29 +// executable, regardless of the license terms of these independent
   12.30 +// modules, and to copy and distribute the resulting executable under
   12.31 +// terms of your choice, provided that you also meet, for each linked
   12.32 +// independent module, the terms and conditions of the license of that
   12.33 +// module.  An independent module is a module which is not derived from
   12.34 +// or based on this library.  If you modify this library, you may extend
   12.35 +// this exception to your version of the library, but you are not
   12.36 +// obligated to do so.  If you do not wish to do so, delete this
   12.37 +// exception statement from your version.
   12.38 +
   12.39 +namespace ICSharpCode.SharpZipLib.Core
   12.40 +{
   12.41 +	/// <summary>
   12.42 +	/// INameTransform defines how file system names are transformed for use with archives, or vice versa.
   12.43 +	/// </summary>
   12.44 +	public interface INameTransform
   12.45 +	{
   12.46 +		/// <summary>
   12.47 +		/// Given a file name determine the transformed value.
   12.48 +		/// </summary>
   12.49 +		/// <param name="name">The name to transform.</param>
   12.50 +		/// <returns>The transformed file name.</returns>
   12.51 +		string TransformFile(string name);
   12.52 +		
   12.53 +		/// <summary>
   12.54 +		/// Given a directory name determine the transformed value.
   12.55 +		/// </summary>
   12.56 +		/// <param name="name">The name to transform.</param>
   12.57 +		/// <returns>The transformed directory name</returns>
   12.58 +		string TransformDirectory(string name);
   12.59 +	}
   12.60 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/Core/IScanFilter.cs	Sat Oct 30 14:03:17 2010 +0000
    13.3 @@ -0,0 +1,50 @@
    13.4 +// IScanFilter.cs
    13.5 +//
    13.6 +// Copyright 2006 John Reilly
    13.7 +//
    13.8 +// This program is free software; you can redistribute it and/or
    13.9 +// modify it under the terms of the GNU General Public License
   13.10 +// as published by the Free Software Foundation; either version 2
   13.11 +// of the License, or (at your option) any later version.
   13.12 +//
   13.13 +// This program is distributed in the hope that it will be useful,
   13.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.16 +// GNU General Public License for more details.
   13.17 +//
   13.18 +// You should have received a copy of the GNU General Public License
   13.19 +// along with this program; if not, write to the Free Software
   13.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   13.21 +//
   13.22 +// Linking this library statically or dynamically with other modules is
   13.23 +// making a combined work based on this library.  Thus, the terms and
   13.24 +// conditions of the GNU General Public License cover the whole
   13.25 +// combination.
   13.26 +// 
   13.27 +// As a special exception, the copyright holders of this library give you
   13.28 +// permission to link this library with independent modules to produce an
   13.29 +// executable, regardless of the license terms of these independent
   13.30 +// modules, and to copy and distribute the resulting executable under
   13.31 +// terms of your choice, provided that you also meet, for each linked
   13.32 +// independent module, the terms and conditions of the license of that
   13.33 +// module.  An independent module is a module which is not derived from
   13.34 +// or based on this library.  If you modify this library, you may extend
   13.35 +// this exception to your version of the library, but you are not
   13.36 +// obligated to do so.  If you do not wish to do so, delete this
   13.37 +// exception statement from your version.
   13.38 +
   13.39 +namespace ICSharpCode.SharpZipLib.Core
   13.40 +{
   13.41 +	/// <summary>
   13.42 +	/// Scanning filters support filtering of names.
   13.43 +	/// </summary>
   13.44 +	public interface IScanFilter
   13.45 +	{
   13.46 +		/// <summary>
   13.47 +		/// Test a name to see if it 'matches' the filter.
   13.48 +		/// </summary>
   13.49 +		/// <param name="name">The name to test.</param>
   13.50 +		/// <returns>Returns true if the name matches the filter, false if it does not match.</returns>
   13.51 +		bool IsMatch(string name);
   13.52 +	}
   13.53 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/Core/NameFilter.cs	Sat Oct 30 14:03:17 2010 +0000
    14.3 @@ -0,0 +1,290 @@
    14.4 +// NameFilter.cs
    14.5 +//
    14.6 +// Copyright 2005 John Reilly
    14.7 +//
    14.8 +// This program is free software; you can redistribute it and/or
    14.9 +// modify it under the terms of the GNU General Public License
   14.10 +// as published by the Free Software Foundation; either version 2
   14.11 +// of the License, or (at your option) any later version.
   14.12 +//
   14.13 +// This program is distributed in the hope that it will be useful,
   14.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.16 +// GNU General Public License for more details.
   14.17 +//
   14.18 +// You should have received a copy of the GNU General Public License
   14.19 +// along with this program; if not, write to the Free Software
   14.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   14.21 +//
   14.22 +// Linking this library statically or dynamically with other modules is
   14.23 +// making a combined work based on this library.  Thus, the terms and
   14.24 +// conditions of the GNU General Public License cover the whole
   14.25 +// combination.
   14.26 +// 
   14.27 +// As a special exception, the copyright holders of this library give you
   14.28 +// permission to link this library with independent modules to produce an
   14.29 +// executable, regardless of the license terms of these independent
   14.30 +// modules, and to copy and distribute the resulting executable under
   14.31 +// terms of your choice, provided that you also meet, for each linked
   14.32 +// independent module, the terms and conditions of the license of that
   14.33 +// module.  An independent module is a module which is not derived from
   14.34 +// or based on this library.  If you modify this library, you may extend
   14.35 +// this exception to your version of the library, but you are not
   14.36 +// obligated to do so.  If you do not wish to do so, delete this
   14.37 +// exception statement from your version.
   14.38 +
   14.39 +// HISTORY
   14.40 +//	2010-03-03	Z-1654	Fixed bug where escape characters were excluded in SplitQuoted()
   14.41 +
   14.42 +using System;
   14.43 +using System.Collections;
   14.44 +using System.Text;
   14.45 +using System.Text.RegularExpressions;
   14.46 +
   14.47 +namespace ICSharpCode.SharpZipLib.Core
   14.48 +{
   14.49 +	/// <summary>
   14.50 +	/// NameFilter is a string matching class which allows for both positive and negative
   14.51 +	/// matching.
   14.52 +	/// A filter is a sequence of independant <see cref="Regex">regular expressions</see> separated by semi-colons ';'.
   14.53 +	/// To include a semi-colon it may be quoted as in \;. Each expression can be prefixed by a plus '+' sign or
   14.54 +	/// a minus '-' sign to denote the expression is intended to include or exclude names.
   14.55 +	/// If neither a plus or minus sign is found include is the default.
   14.56 +	/// A given name is tested for inclusion before checking exclusions.  Only names matching an include spec 
   14.57 +	/// and not matching an exclude spec are deemed to match the filter.
   14.58 +	/// An empty filter matches any name.
   14.59 +	/// </summary>
   14.60 +	/// <example>The following expression includes all name ending in '.dat' with the exception of 'dummy.dat'
   14.61 +	/// "+\.dat$;-^dummy\.dat$"
   14.62 +	/// </example>
   14.63 +	public class NameFilter : IScanFilter
   14.64 +	{
   14.65 +		#region Constructors
   14.66 +		/// <summary>
   14.67 +		/// Construct an instance based on the filter expression passed
   14.68 +		/// </summary>
   14.69 +		/// <param name="filter">The filter expression.</param>
   14.70 +		public NameFilter(string filter)
   14.71 +		{
   14.72 +			filter_ = filter;
   14.73 +			inclusions_ = new ArrayList();
   14.74 +			exclusions_ = new ArrayList();
   14.75 +			Compile();
   14.76 +		}
   14.77 +		#endregion
   14.78 +
   14.79 +		/// <summary>
   14.80 +		/// Test a string to see if it is a valid regular expression.
   14.81 +		/// </summary>
   14.82 +		/// <param name="expression">The expression to test.</param>
   14.83 +		/// <returns>True if expression is a valid <see cref="System.Text.RegularExpressions.Regex"/> false otherwise.</returns>
   14.84 +		public static bool IsValidExpression(string expression)
   14.85 +		{
   14.86 +			bool result = true;
   14.87 +			try {
   14.88 +				Regex exp = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline);
   14.89 +			}
   14.90 +			catch (ArgumentException) {
   14.91 +				result = false;
   14.92 +			}
   14.93 +			return result;
   14.94 +		}
   14.95 +
   14.96 +		/// <summary>
   14.97 +		/// Test an expression to see if it is valid as a filter.
   14.98 +		/// </summary>
   14.99 +		/// <param name="toTest">The filter expression to test.</param>
  14.100 +		/// <returns>True if the expression is valid, false otherwise.</returns>
  14.101 +		public static bool IsValidFilterExpression(string toTest)
  14.102 +		{
  14.103 +			if ( toTest == null ) {
  14.104 +				throw new ArgumentNullException("toTest");
  14.105 +			}
  14.106 +
  14.107 +			bool result = true;
  14.108 +
  14.109 +			try {
  14.110 +				string[] items = SplitQuoted(toTest);
  14.111 +				for (int i = 0; i < items.Length; ++i) {
  14.112 +					if ((items[i] != null) && (items[i].Length > 0)) {
  14.113 +						string toCompile;
  14.114 +
  14.115 +						if (items[i][0] == '+') {
  14.116 +							toCompile = items[i].Substring(1, items[i].Length - 1);
  14.117 +						}
  14.118 +						else if (items[i][0] == '-') {
  14.119 +							toCompile = items[i].Substring(1, items[i].Length - 1);
  14.120 +						}
  14.121 +						else {
  14.122 +							toCompile = items[i];
  14.123 +						}
  14.124 +
  14.125 +						Regex testRegex = new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Singleline);
  14.126 +					}
  14.127 +				}
  14.128 +			}
  14.129 +			catch (ArgumentException) {
  14.130 +				result = false;
  14.131 +			}
  14.132 +
  14.133 +			return result;
  14.134 +		}
  14.135 +
  14.136 +		/// <summary>
  14.137 +		/// Split a string into its component pieces
  14.138 +		/// </summary>
  14.139 +		/// <param name="original">The original string</param>
  14.140 +		/// <returns>Returns an array of <see cref="T:System.String"/> values containing the individual filter elements.</returns>
  14.141 +		public static string[] SplitQuoted(string original)
  14.142 +		{
  14.143 +			char escape = '\\';
  14.144 +			char[] separators = { ';' };
  14.145 +
  14.146 +			ArrayList result = new ArrayList();
  14.147 +
  14.148 +			if ((original != null) && (original.Length > 0)) {
  14.149 +				int endIndex = -1;
  14.150 +				StringBuilder b = new StringBuilder();
  14.151 +
  14.152 +				while (endIndex < original.Length) {
  14.153 +					endIndex += 1;
  14.154 +					if (endIndex >= original.Length) {
  14.155 +						result.Add(b.ToString());
  14.156 +					}
  14.157 +					else if (original[endIndex] == escape) {
  14.158 +						endIndex += 1;
  14.159 +						if (endIndex >= original.Length) {
  14.160 +#if NETCF_1_0
  14.161 +							throw new ArgumentException("Missing terminating escape character");
  14.162 +#else
  14.163 +							throw new ArgumentException("Missing terminating escape character", "original");
  14.164 +#endif
  14.165 +						}
  14.166 +						// include escape if this is not an escaped separator
  14.167 +						if (Array.IndexOf(separators, original[endIndex]) < 0)
  14.168 +							b.Append(escape);
  14.169 +
  14.170 +						b.Append(original[endIndex]);
  14.171 +					}
  14.172 +					else {
  14.173 +						if (Array.IndexOf(separators, original[endIndex]) >= 0) {
  14.174 +							result.Add(b.ToString());
  14.175 +							b.Length = 0;
  14.176 +						}
  14.177 +						else {
  14.178 +							b.Append(original[endIndex]);
  14.179 +						}
  14.180 +					}
  14.181 +				}
  14.182 +			}
  14.183 +
  14.184 +			return (string[])result.ToArray(typeof(string));
  14.185 +		}
  14.186 +
  14.187 +		/// <summary>
  14.188 +		/// Convert this filter to its string equivalent.
  14.189 +		/// </summary>
  14.190 +		/// <returns>The string equivalent for this filter.</returns>
  14.191 +		public override string ToString()
  14.192 +		{
  14.193 +			return filter_;
  14.194 +		}
  14.195 +
  14.196 +		/// <summary>
  14.197 +		/// Test a value to see if it is included by the filter.
  14.198 +		/// </summary>
  14.199 +		/// <param name="name">The value to test.</param>
  14.200 +		/// <returns>True if the value is included, false otherwise.</returns>
  14.201 +		public bool IsIncluded(string name)
  14.202 +		{
  14.203 +			bool result = false;
  14.204 +			if ( inclusions_.Count == 0 ) {
  14.205 +				result = true;
  14.206 +			}
  14.207 +			else {
  14.208 +				foreach ( Regex r in inclusions_ ) {
  14.209 +					if ( r.IsMatch(name) ) {
  14.210 +						result = true;
  14.211 +						break;
  14.212 +					}
  14.213 +				}
  14.214 +			}
  14.215 +			return result;
  14.216 +		}
  14.217 +
  14.218 +		/// <summary>
  14.219 +		/// Test a value to see if it is excluded by the filter.
  14.220 +		/// </summary>
  14.221 +		/// <param name="name">The value to test.</param>
  14.222 +		/// <returns>True if the value is excluded, false otherwise.</returns>
  14.223 +		public bool IsExcluded(string name)
  14.224 +		{
  14.225 +			bool result = false;
  14.226 +			foreach ( Regex r in exclusions_ ) {
  14.227 +				if ( r.IsMatch(name) ) {
  14.228 +					result = true;
  14.229 +					break;
  14.230 +				}
  14.231 +			}
  14.232 +			return result;
  14.233 +		}
  14.234 +
  14.235 +		#region IScanFilter Members
  14.236 +		/// <summary>
  14.237 +		/// Test a value to see if it matches the filter.
  14.238 +		/// </summary>
  14.239 +		/// <param name="name">The value to test.</param>
  14.240 +		/// <returns>True if the value matches, false otherwise.</returns>
  14.241 +		public bool IsMatch(string name)
  14.242 +		{
  14.243 +			return (IsIncluded(name) && !IsExcluded(name));
  14.244 +		}
  14.245 +		#endregion
  14.246 +
  14.247 +		/// <summary>
  14.248 +		/// Compile this filter.
  14.249 +		/// </summary>
  14.250 +		void Compile()
  14.251 +		{
  14.252 +			// TODO: Check to see if combining RE's makes it faster/smaller.
  14.253 +			// simple scheme would be to have one RE for inclusion and one for exclusion.
  14.254 +			if ( filter_ == null ) {
  14.255 +				return;
  14.256 +			}
  14.257 +
  14.258 +			string[] items = SplitQuoted(filter_);
  14.259 +			for ( int i = 0; i < items.Length; ++i ) {
  14.260 +				if ( (items[i] != null) && (items[i].Length > 0) ) {
  14.261 +					bool include = (items[i][0] != '-');
  14.262 +					string toCompile;
  14.263 +
  14.264 +					if ( items[i][0] == '+' ) {
  14.265 +						toCompile = items[i].Substring(1, items[i].Length - 1);
  14.266 +					}
  14.267 +					else if ( items[i][0] == '-' ) {
  14.268 +						toCompile = items[i].Substring(1, items[i].Length - 1);
  14.269 +					}
  14.270 +					else {
  14.271 +						toCompile = items[i];
  14.272 +					}
  14.273 +
  14.274 +					// NOTE: Regular expressions can fail to compile here for a number of reasons that cause an exception
  14.275 +					// these are left unhandled here as the caller is responsible for ensuring all is valid.
  14.276 +					// several functions IsValidFilterExpression and IsValidExpression are provided for such checking
  14.277 +					if ( include ) {
  14.278 +						inclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline));
  14.279 +					}
  14.280 +					else {
  14.281 +						exclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline));
  14.282 +					}
  14.283 +				}
  14.284 +			}
  14.285 +		}
  14.286 +
  14.287 +		#region Instance Fields
  14.288 +		string filter_;
  14.289 +		ArrayList inclusions_;
  14.290 +		ArrayList exclusions_;
  14.291 +		#endregion
  14.292 +	}
  14.293 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/Core/PathFilter.cs	Sat Oct 30 14:03:17 2010 +0000
    15.3 @@ -0,0 +1,334 @@
    15.4 +// PathFilter.cs
    15.5 +//
    15.6 +// Copyright 2005 John Reilly
    15.7 +//
    15.8 +// This program is free software; you can redistribute it and/or
    15.9 +// modify it under the terms of the GNU General Public License
   15.10 +// as published by the Free Software Foundation; either version 2
   15.11 +// of the License, or (at your option) any later version.
   15.12 +//
   15.13 +// This program is distributed in the hope that it will be useful,
   15.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.16 +// GNU General Public License for more details.
   15.17 +//
   15.18 +// You should have received a copy of the GNU General Public License
   15.19 +// along with this program; if not, write to the Free Software
   15.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   15.21 +//
   15.22 +// Linking this library statically or dynamically with other modules is
   15.23 +// making a combined work based on this library.  Thus, the terms and
   15.24 +// conditions of the GNU General Public License cover the whole
   15.25 +// combination.
   15.26 +// 
   15.27 +// As a special exception, the copyright holders of this library give you
   15.28 +// permission to link this library with independent modules to produce an
   15.29 +// executable, regardless of the license terms of these independent
   15.30 +// modules, and to copy and distribute the resulting executable under
   15.31 +// terms of your choice, provided that you also meet, for each linked
   15.32 +// independent module, the terms and conditions of the license of that
   15.33 +// module.  An independent module is a module which is not derived from
   15.34 +// or based on this library.  If you modify this library, you may extend
   15.35 +// this exception to your version of the library, but you are not
   15.36 +// obligated to do so.  If you do not wish to do so, delete this
   15.37 +// exception statement from your version.
   15.38 +
   15.39 +using System;
   15.40 +using System.IO;
   15.41 +
   15.42 +namespace ICSharpCode.SharpZipLib.Core
   15.43 +{
   15.44 +	/// <summary>
   15.45 +	/// PathFilter filters directories and files using a form of <see cref="System.Text.RegularExpressions.Regex">regular expressions</see>
   15.46 +	/// by full path name.
   15.47 +	/// See <see cref="NameFilter">NameFilter</see> for more detail on filtering.
   15.48 +	/// </summary>
   15.49 +	public class PathFilter : IScanFilter
   15.50 +	{
   15.51 +		#region Constructors
   15.52 +		/// <summary>
   15.53 +		/// Initialise a new instance of <see cref="PathFilter"></see>.
   15.54 +		/// </summary>
   15.55 +		/// <param name="filter">The <see cref="NameFilter">filter</see> expression to apply.</param>
   15.56 +		public PathFilter(string filter)
   15.57 +		{
   15.58 +			nameFilter_ = new NameFilter(filter);
   15.59 +		}
   15.60 +		#endregion
   15.61 +
   15.62 +		#region IScanFilter Members
   15.63 +		/// <summary>
   15.64 +		/// Test a name to see if it matches the filter.
   15.65 +		/// </summary>
   15.66 +		/// <param name="name">The name to test.</param>
   15.67 +		/// <returns>True if the name matches, false otherwise.</returns>
   15.68 +		/// <remarks><see cref="Path.GetFullPath(string)"/> is used to get the full path before matching.</remarks>
   15.69 +		public virtual bool IsMatch(string name)
   15.70 +		{
   15.71 +			bool result = false;
   15.72 +
   15.73 +			if ( name != null ) {
   15.74 +				string cooked = (name.Length > 0) ? Path.GetFullPath(name) : "";
   15.75 +				result = nameFilter_.IsMatch(cooked);
   15.76 +			}
   15.77 +			return result;
   15.78 +		}
   15.79 +		#endregion
   15.80 +
   15.81 +		#region Instance Fields
   15.82 +		NameFilter nameFilter_;
   15.83 +		#endregion
   15.84 +	}
   15.85 +
   15.86 +	/// <summary>
   15.87 +	/// ExtendedPathFilter filters based on name, file size, and the last write time of the file.
   15.88 +	/// </summary>
   15.89 +	/// <remarks>Provides an example of how to customise filtering.</remarks>
   15.90 +	public class ExtendedPathFilter : PathFilter
   15.91 +	{
   15.92 +		#region Constructors
   15.93 +		/// <summary>
   15.94 +		/// Initialise a new instance of ExtendedPathFilter.
   15.95 +		/// </summary>
   15.96 +		/// <param name="filter">The filter to apply.</param>
   15.97 +		/// <param name="minSize">The minimum file size to include.</param>
   15.98 +		/// <param name="maxSize">The maximum file size to include.</param>
   15.99 +		public ExtendedPathFilter(string filter,
  15.100 +			long minSize, long maxSize)
  15.101 +			: base(filter)
  15.102 +		{
  15.103 +			MinSize = minSize;
  15.104 +			MaxSize = maxSize;
  15.105 +		}
  15.106 +
  15.107 +		/// <summary>
  15.108 +		/// Initialise a new instance of ExtendedPathFilter.
  15.109 +		/// </summary>
  15.110 +		/// <param name="filter">The filter to apply.</param>
  15.111 +		/// <param name="minDate">The minimum <see cref="DateTime"/> to include.</param>
  15.112 +		/// <param name="maxDate">The maximum <see cref="DateTime"/> to include.</param>
  15.113 +		public ExtendedPathFilter(string filter,
  15.114 +			DateTime minDate, DateTime maxDate)
  15.115 +			: base(filter)
  15.116 +		{
  15.117 +			MinDate = minDate;
  15.118 +			MaxDate = maxDate;
  15.119 +		}
  15.120 +
  15.121 +		/// <summary>
  15.122 +		/// Initialise a new instance of ExtendedPathFilter.
  15.123 +		/// </summary>
  15.124 +		/// <param name="filter">The filter to apply.</param>
  15.125 +		/// <param name="minSize">The minimum file size to include.</param>
  15.126 +		/// <param name="maxSize">The maximum file size to include.</param>
  15.127 +		/// <param name="minDate">The minimum <see cref="DateTime"/> to include.</param>
  15.128 +		/// <param name="maxDate">The maximum <see cref="DateTime"/> to include.</param>
  15.129 +		public ExtendedPathFilter(string filter,
  15.130 +			long minSize, long maxSize,
  15.131 +			DateTime minDate, DateTime maxDate)
  15.132 +			: base(filter)
  15.133 +		{
  15.134 +			MinSize = minSize;
  15.135 +			MaxSize = maxSize;
  15.136 +			MinDate = minDate;
  15.137 +			MaxDate = maxDate;
  15.138 +		}
  15.139 +		#endregion
  15.140 +
  15.141 +		#region IScanFilter Members
  15.142 +		/// <summary>
  15.143 +		/// Test a filename to see if it matches the filter.
  15.144 +		/// </summary>
  15.145 +		/// <param name="name">The filename to test.</param>
  15.146 +		/// <returns>True if the filter matches, false otherwise.</returns>
  15.147 +		/// <exception cref="System.IO.FileNotFoundException">The <see paramref="fileName"/> doesnt exist</exception>
  15.148 +		public override bool IsMatch(string name)
  15.149 +		{
  15.150 +			bool result = base.IsMatch(name);
  15.151 +
  15.152 +			if ( result ) {
  15.153 +				FileInfo fileInfo = new FileInfo(name);
  15.154 +				result = 
  15.155 +					(MinSize <= fileInfo.Length) &&
  15.156 +					(MaxSize >= fileInfo.Length) &&
  15.157 +					(MinDate <= fileInfo.LastWriteTime) &&
  15.158 +					(MaxDate >= fileInfo.LastWriteTime)
  15.159 +					;
  15.160 +			}
  15.161 +			return result;
  15.162 +		}
  15.163 +		#endregion
  15.164 +
  15.165 +		#region Properties
  15.166 +		/// <summary>
  15.167 +		/// Get/set the minimum size/length for a file that will match this filter.
  15.168 +		/// </summary>
  15.169 +		/// <remarks>The default value is zero.</remarks>
  15.170 +		/// <exception cref="ArgumentOutOfRangeException">value is less than zero; greater than <see cref="MaxSize"/></exception>
  15.171 +		public long MinSize
  15.172 +		{
  15.173 +			get { return minSize_; }
  15.174 +			set
  15.175 +			{
  15.176 +				if ( (value < 0) || (maxSize_ < value) ) {
  15.177 +					throw new ArgumentOutOfRangeException("value");
  15.178 +				}
  15.179 +
  15.180 +				minSize_ = value;
  15.181 +			}
  15.182 +		}
  15.183 +		
  15.184 +		/// <summary>
  15.185 +		/// Get/set the maximum size/length for a file that will match this filter.
  15.186 +		/// </summary>
  15.187 +		/// <remarks>The default value is <see cref="System.Int64.MaxValue"/></remarks>
  15.188 +		/// <exception cref="ArgumentOutOfRangeException">value is less than zero or less than <see cref="MinSize"/></exception>
  15.189 +		public long MaxSize
  15.190 +		{
  15.191 +			get { return maxSize_; }
  15.192 +			set
  15.193 +			{
  15.194 +				if ( (value < 0) || (minSize_ > value) ) {
  15.195 +					throw new ArgumentOutOfRangeException("value");
  15.196 +				}
  15.197 +
  15.198 +				maxSize_ = value;
  15.199 +			}
  15.200 +		}
  15.201 +
  15.202 +		/// <summary>
  15.203 +		/// Get/set the minimum <see cref="DateTime"/> value that will match for this filter.
  15.204 +		/// </summary>
  15.205 +		/// <remarks>Files with a LastWrite time less than this value are excluded by the filter.</remarks>
  15.206 +		public DateTime MinDate
  15.207 +		{
  15.208 +			get
  15.209 +			{
  15.210 +				return minDate_;
  15.211 +			}
  15.212 +
  15.213 +			set
  15.214 +			{
  15.215 +				if ( value > maxDate_ ) {
  15.216 +#if NETCF_1_0
  15.217 +					throw new ArgumentOutOfRangeException("value");
  15.218 +#else
  15.219 +					throw new ArgumentOutOfRangeException("value", "Exceeds MaxDate");
  15.220 +#endif
  15.221 +				}
  15.222 +
  15.223 +				minDate_ = value;
  15.224 +			}
  15.225 +		}
  15.226 +
  15.227 +		/// <summary>
  15.228 +		/// Get/set the maximum <see cref="DateTime"/> value that will match for this filter.
  15.229 +		/// </summary>
  15.230 +		/// <remarks>Files with a LastWrite time greater than this value are excluded by the filter.</remarks>
  15.231 +		public DateTime MaxDate
  15.232 +		{
  15.233 +			get
  15.234 +			{
  15.235 +				return maxDate_;
  15.236 +			}
  15.237 +
  15.238 +			set
  15.239 +			{
  15.240 +				if ( minDate_ > value ) {
  15.241 +#if NETCF_1_0
  15.242 +					throw new ArgumentOutOfRangeException("value");
  15.243 +#else
  15.244 +					throw new ArgumentOutOfRangeException("value", "Exceeds MinDate");
  15.245 +#endif
  15.246 +				}
  15.247 +
  15.248 +				maxDate_ = value;
  15.249 +			}
  15.250 +		}
  15.251 +		#endregion
  15.252 +
  15.253 +		#region Instance Fields
  15.254 +		long minSize_;
  15.255 +		long maxSize_ = long.MaxValue;
  15.256 +		DateTime minDate_ = DateTime.MinValue;
  15.257 +		DateTime maxDate_ = DateTime.MaxValue;
  15.258 +		#endregion
  15.259 +	}
  15.260 +
  15.261 +	/// <summary>
  15.262 +	/// NameAndSizeFilter filters based on name and file size.
  15.263 +	/// </summary>
  15.264 +	/// <remarks>A sample showing how filters might be extended.</remarks>
  15.265 +	[Obsolete("Use ExtendedPathFilter instead")]
  15.266 +	public class NameAndSizeFilter : PathFilter
  15.267 +	{
  15.268 +
  15.269 +		/// <summary>
  15.270 +		/// Initialise a new instance of NameAndSizeFilter.
  15.271 +		/// </summary>
  15.272 +		/// <param name="filter">The filter to apply.</param>
  15.273 +		/// <param name="minSize">The minimum file size to include.</param>
  15.274 +		/// <param name="maxSize">The maximum file size to include.</param>
  15.275 +		public NameAndSizeFilter(string filter, long minSize, long maxSize)
  15.276 +			: base(filter)
  15.277 +		{
  15.278 +			MinSize = minSize;
  15.279 +			MaxSize = maxSize;
  15.280 +		}
  15.281 +		
  15.282 +		/// <summary>
  15.283 +		/// Test a filename to see if it matches the filter.
  15.284 +		/// </summary>
  15.285 +		/// <param name="name">The filename to test.</param>
  15.286 +		/// <returns>True if the filter matches, false otherwise.</returns>
  15.287 +		public override bool IsMatch(string name)
  15.288 +		{
  15.289 +			bool result = base.IsMatch(name);
  15.290 +
  15.291 +			if ( result ) {
  15.292 +				FileInfo fileInfo = new FileInfo(name);
  15.293 +				long length = fileInfo.Length;
  15.294 +				result = 
  15.295 +					(MinSize <= length) &&
  15.296 +					(MaxSize >= length);
  15.297 +			}
  15.298 +			return result;
  15.299 +		}
  15.300 +		
  15.301 +		/// <summary>
  15.302 +		/// Get/set the minimum size for a file that will match this filter.
  15.303 +		/// </summary>
  15.304 +		public long MinSize
  15.305 +		{
  15.306 +			get { return minSize_; }
  15.307 +			set {
  15.308 +				if ( (value < 0) || (maxSize_ < value) ) {
  15.309 +					throw new ArgumentOutOfRangeException("value");
  15.310 +				}
  15.311 +
  15.312 +				minSize_ = value;
  15.313 +			}
  15.314 +		}
  15.315 +		
  15.316 +		/// <summary>
  15.317 +		/// Get/set the maximum size for a file that will match this filter.
  15.318 +		/// </summary>
  15.319 +		public long MaxSize
  15.320 +		{
  15.321 +			get { return maxSize_; }
  15.322 +			set
  15.323 +			{
  15.324 +				if ( (value < 0) || (minSize_ > value) ) {
  15.325 +					throw new ArgumentOutOfRangeException("value");
  15.326 +				}
  15.327 +
  15.328 +				maxSize_ = value;
  15.329 +			}
  15.330 +		}
  15.331 +
  15.332 +		#region Instance Fields
  15.333 +		long minSize_;
  15.334 +		long maxSize_ = long.MaxValue;
  15.335 +		#endregion
  15.336 +	}
  15.337 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/Core/StreamUtils.cs	Sat Oct 30 14:03:17 2010 +0000
    16.3 @@ -0,0 +1,246 @@
    16.4 +// StreamUtils.cs
    16.5 +//
    16.6 +// Copyright 2005 John Reilly
    16.7 +//
    16.8 +// This program is free software; you can redistribute it and/or
    16.9 +// modify it under the terms of the GNU General Public License
   16.10 +// as published by the Free Software Foundation; either version 2
   16.11 +// of the License, or (at your option) any later version.
   16.12 +//
   16.13 +// This program is distributed in the hope that it will be useful,
   16.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.16 +// GNU General Public License for more details.
   16.17 +//
   16.18 +// You should have received a copy of the GNU General Public License
   16.19 +// along with this program; if not, write to the Free Software
   16.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   16.21 +//
   16.22 +// Linking this library statically or dynamically with other modules is
   16.23 +// making a combined work based on this library.  Thus, the terms and
   16.24 +// conditions of the GNU General Public License cover the whole
   16.25 +// combination.
   16.26 +// 
   16.27 +// As a special exception, the copyright holders of this library give you
   16.28 +// permission to link this library with independent modules to produce an
   16.29 +// executable, regardless of the license terms of these independent
   16.30 +// modules, and to copy and distribute the resulting executable under
   16.31 +// terms of your choice, provided that you also meet, for each linked
   16.32 +// independent module, the terms and conditions of the license of that
   16.33 +// module.  An independent module is a module which is not derived from
   16.34 +// or based on this library.  If you modify this library, you may extend
   16.35 +// this exception to your version of the library, but you are not
   16.36 +// obligated to do so.  If you do not wish to do so, delete this
   16.37 +// exception statement from your version.
   16.38 +
   16.39 +using System;
   16.40 +using System.IO;
   16.41 +
   16.42 +namespace ICSharpCode.SharpZipLib.Core
   16.43 +{
   16.44 +	/// <summary>
   16.45 +	/// Provides simple <see cref="Stream"/>" utilities.
   16.46 +	/// </summary>
   16.47 +	public sealed class StreamUtils
   16.48 +	{
   16.49 +		/// <summary>
   16.50 +		/// Read from a <see cref="Stream"/> ensuring all the required data is read.
   16.51 +		/// </summary>
   16.52 +		/// <param name="stream">The stream to read.</param>
   16.53 +		/// <param name="buffer">The buffer to fill.</param>
   16.54 +		/// <seealso cref="ReadFully(Stream,byte[],int,int)"/>
   16.55 +		static public void ReadFully(Stream stream, byte[] buffer)
   16.56 +		{
   16.57 +			ReadFully(stream, buffer, 0, buffer.Length);
   16.58 +		}
   16.59 +
   16.60 +		/// <summary>
   16.61 +		/// Read from a <see cref="Stream"/>" ensuring all the required data is read.
   16.62 +		/// </summary>
   16.63 +		/// <param name="stream">The stream to read data from.</param>
   16.64 +		/// <param name="buffer">The buffer to store data in.</param>
   16.65 +		/// <param name="offset">The offset at which to begin storing data.</param>
   16.66 +		/// <param name="count">The number of bytes of data to store.</param>
   16.67 +		/// <exception cref="ArgumentNullException">Required parameter is null</exception>
   16.68 +		/// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> and or <paramref name="count"/> are invalid.</exception>
   16.69 +		/// <exception cref="EndOfStreamException">End of stream is encountered before all the data has been read.</exception>
   16.70 +		static public void ReadFully(Stream stream, byte[] buffer, int offset, int count)
   16.71 +		{
   16.72 +			if ( stream == null ) {
   16.73 +				throw new ArgumentNullException("stream");
   16.74 +			}
   16.75 +
   16.76 +			if ( buffer == null ) {
   16.77 +				throw new ArgumentNullException("buffer");
   16.78 +			}
   16.79 +
   16.80 +			// Offset can equal length when buffer and count are 0.
   16.81 +			if ( (offset < 0) || (offset > buffer.Length) ) {
   16.82 +				throw new ArgumentOutOfRangeException("offset");
   16.83 +			}
   16.84 +
   16.85 +			if ( (count < 0) || (offset + count > buffer.Length) ) {
   16.86 +				throw new ArgumentOutOfRangeException("count");
   16.87 +			}
   16.88 +
   16.89 +			while ( count > 0 ) {
   16.90 +				int readCount = stream.Read(buffer, offset, count);
   16.91 +				if ( readCount <= 0 ) {
   16.92 +					throw new EndOfStreamException();
   16.93 +				}
   16.94 +				offset += readCount;
   16.95 +				count -= readCount;
   16.96 +			}
   16.97 +		}
   16.98 +
   16.99 +		/// <summary>
  16.100 +		/// Copy the contents of one <see cref="Stream"/> to another.
  16.101 +		/// </summary>
  16.102 +		/// <param name="source">The stream to source data from.</param>
  16.103 +		/// <param name="destination">The stream to write data to.</param>
  16.104 +		/// <param name="buffer">The buffer to use during copying.</param>
  16.105 +		static public void Copy(Stream source, Stream destination, byte[] buffer)
  16.106 +		{
  16.107 +			if (source == null) {
  16.108 +				throw new ArgumentNullException("source");
  16.109 +			}
  16.110 +
  16.111 +			if (destination == null) {
  16.112 +				throw new ArgumentNullException("destination");
  16.113 +			}
  16.114 +
  16.115 +			if (buffer == null) {
  16.116 +				throw new ArgumentNullException("buffer");
  16.117 +			}
  16.118 +
  16.119 +			// Ensure a reasonable size of buffer is used without being prohibitive.
  16.120 +			if (buffer.Length < 128) {
  16.121 +				throw new ArgumentException("Buffer is too small", "buffer");
  16.122 +			}
  16.123 +
  16.124 +			bool copying = true;
  16.125 +
  16.126 +			while (copying) {
  16.127 +				int bytesRead = source.Read(buffer, 0, buffer.Length);
  16.128 +				if (bytesRead > 0) {
  16.129 +					destination.Write(buffer, 0, bytesRead);
  16.130 +				}
  16.131 +				else {
  16.132 +					destination.Flush();
  16.133 +					copying = false;
  16.134 +				}
  16.135 +			}
  16.136 +		}
  16.137 +
  16.138 +		/// <summary>
  16.139 +		/// Copy the contents of one <see cref="Stream"/> to another.
  16.140 +		/// </summary>
  16.141 +		/// <param name="source">The stream to source data from.</param>
  16.142 +		/// <param name="destination">The stream to write data to.</param>
  16.143 +		/// <param name="buffer">The buffer to use during copying.</param>
  16.144 +		/// <param name="progressHandler">The <see cref="ProgressHandler">progress handler delegate</see> to use.</param>
  16.145 +		/// <param name="updateInterval">The minimum <see cref="TimeSpan"/> between progress updates.</param>
  16.146 +		/// <param name="sender">The source for this event.</param>
  16.147 +		/// <param name="name">The name to use with the event.</param>
  16.148 +		/// <remarks>This form is specialised for use within #Zip to support events during archive operations.</remarks>
  16.149 +		static public void Copy(Stream source, Stream destination,
  16.150 +			byte[] buffer, ProgressHandler progressHandler, TimeSpan updateInterval, object sender, string name)
  16.151 +		{
  16.152 +			Copy(source, destination, buffer, progressHandler, updateInterval, sender, name, -1);
  16.153 +		}
  16.154 +
  16.155 +		/// <summary>
  16.156 +		/// Copy the contents of one <see cref="Stream"/> to another.
  16.157 +		/// </summary>
  16.158 +		/// <param name="source">The stream to source data from.</param>
  16.159 +		/// <param name="destination">The stream to write data to.</param>
  16.160 +		/// <param name="buffer">The buffer to use during copying.</param>
  16.161 +		/// <param name="progressHandler">The <see cref="ProgressHandler">progress handler delegate</see> to use.</param>
  16.162 +		/// <param name="updateInterval">The minimum <see cref="TimeSpan"/> between progress updates.</param>
  16.163 +		/// <param name="sender">The source for this event.</param>
  16.164 +		/// <param name="name">The name to use with the event.</param>
  16.165 +		/// <param name="fixedTarget">A predetermined fixed target value to use with progress updates.
  16.166 +		/// If the value is negative the target is calculated by looking at the stream.</param>
  16.167 +		/// <remarks>This form is specialised for use within #Zip to support events during archive operations.</remarks>
  16.168 +		static public void Copy(Stream source, Stream destination,
  16.169 +			byte[] buffer, 
  16.170 +			ProgressHandler progressHandler, TimeSpan updateInterval, 
  16.171 +			object sender, string name, long fixedTarget)
  16.172 +		{
  16.173 +			if (source == null) {
  16.174 +				throw new ArgumentNullException("source");
  16.175 +			}
  16.176 +
  16.177 +			if (destination == null) {
  16.178 +				throw new ArgumentNullException("destination");
  16.179 +			}
  16.180 +
  16.181 +			if (buffer == null) {
  16.182 +				throw new ArgumentNullException("buffer");
  16.183 +			}
  16.184 +
  16.185 +			// Ensure a reasonable size of buffer is used without being prohibitive.
  16.186 +			if (buffer.Length < 128) {
  16.187 +				throw new ArgumentException("Buffer is too small", "buffer");
  16.188 +			}
  16.189 +
  16.190 +			if (progressHandler == null) {
  16.191 +				throw new ArgumentNullException("progressHandler");
  16.192 +			}
  16.193 +
  16.194 +			bool copying = true;
  16.195 +
  16.196 +			DateTime marker = DateTime.Now;
  16.197 +			long processed = 0;
  16.198 +			long target = 0;
  16.199 +
  16.200 +			if (fixedTarget >= 0) {
  16.201 +				target = fixedTarget;
  16.202 +			}
  16.203 +			else if (source.CanSeek) {
  16.204 +				target = source.Length - source.Position;
  16.205 +			}
  16.206 +
  16.207 +			// Always fire 0% progress..
  16.208 +			ProgressEventArgs args = new ProgressEventArgs(name, processed, target);
  16.209 +			progressHandler(sender, args);
  16.210 +
  16.211 +			bool progressFired = true;
  16.212 +
  16.213 +			while (copying) {
  16.214 +				int bytesRead = source.Read(buffer, 0, buffer.Length);
  16.215 +				if (bytesRead > 0) {
  16.216 +					processed += bytesRead;
  16.217 +					progressFired = false;
  16.218 +					destination.Write(buffer, 0, bytesRead);
  16.219 +				}
  16.220 +				else {
  16.221 +					destination.Flush();
  16.222 +					copying = false;
  16.223 +				}
  16.224 +
  16.225 +				if (DateTime.Now - marker > updateInterval) {
  16.226 +					progressFired = true;
  16.227 +					marker = DateTime.Now;
  16.228 +					args = new ProgressEventArgs(name, processed, target);
  16.229 +					progressHandler(sender, args);
  16.230 +
  16.231 +					copying = args.ContinueRunning;
  16.232 +				}
  16.233 +			}
  16.234 +
  16.235 +			if (!progressFired) {
  16.236 +				args = new ProgressEventArgs(name, processed, target);
  16.237 +				progressHandler(sender, args);
  16.238 +			}
  16.239 +		}
  16.240 +
  16.241 +		/// <summary>
  16.242 +		/// Initialise an instance of <see cref="StreamUtils"></see>
  16.243 +		/// </summary>
  16.244 +		private StreamUtils()
  16.245 +		{
  16.246 +			// Do nothing.
  16.247 +		}
  16.248 +	}
  16.249 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/Core/WindowsPathUtils.cs	Sat Oct 30 14:03:17 2010 +0000
    17.3 @@ -0,0 +1,94 @@
    17.4 +// WindowsPathUtils.cs
    17.5 +//
    17.6 +// Copyright 2007 John Reilly
    17.7 +//
    17.8 +// This program is free software; you can redistribute it and/or
    17.9 +// modify it under the terms of the GNU General Public License
   17.10 +// as published by the Free Software Foundation; either version 2
   17.11 +// of the License, or (at your option) any later version.
   17.12 +//
   17.13 +// This program is distributed in the hope that it will be useful,
   17.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.16 +// GNU General Public License for more details.
   17.17 +//
   17.18 +// You should have received a copy of the GNU General Public License
   17.19 +// along with this program; if not, write to the Free Software
   17.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   17.21 +//
   17.22 +// Linking this library statically or dynamically with other modules is
   17.23 +// making a combined work based on this library.  Thus, the terms and
   17.24 +// conditions of the GNU General Public License cover the whole
   17.25 +// combination.
   17.26 +// 
   17.27 +// As a special exception, the copyright holders of this library give you
   17.28 +// permission to link this library with independent modules to produce an
   17.29 +// executable, regardless of the license terms of these independent
   17.30 +// modules, and to copy and distribute the resulting executable under
   17.31 +// terms of your choice, provided that you also meet, for each linked
   17.32 +// independent module, the terms and conditions of the license of that
   17.33 +// module.  An independent module is a module which is not derived from
   17.34 +// or based on this library.  If you modify this library, you may extend
   17.35 +// this exception to your version of the library, but you are not
   17.36 +// obligated to do so.  If you do not wish to do so, delete this
   17.37 +// exception statement from your version.
   17.38 +
   17.39 +namespace ICSharpCode.SharpZipLib.Core
   17.40 +{
   17.41 +	/// <summary>
   17.42 +	/// WindowsPathUtils provides simple utilities for handling windows paths.
   17.43 +	/// </summary>
   17.44 +	public abstract class WindowsPathUtils
   17.45 +	{
   17.46 +		/// <summary>
   17.47 +		/// Initializes a new instance of the <see cref="WindowsPathUtils"/> class.
   17.48 +		/// </summary>
   17.49 +		internal WindowsPathUtils()
   17.50 +		{
   17.51 +		}
   17.52 +		
   17.53 +		/// <summary>
   17.54 +		/// Remove any path root present in the path
   17.55 +		/// </summary>
   17.56 +		/// <param name="path">A <see cref="string"/> containing path information.</param>
   17.57 +		/// <returns>The path with the root removed if it was present; path otherwise.</returns>
   17.58 +		/// <remarks>Unlike the <see cref="System.IO.Path"/> class the path isnt otherwise checked for validity.</remarks>
   17.59 +		public static string DropPathRoot(string path)
   17.60 +		{
   17.61 +			string result = path;
   17.62 +			
   17.63 +			if ( (path != null) && (path.Length > 0) ) {
   17.64 +				if ((path[0] == '\\') || (path[0] == '/')) {
   17.65 +					// UNC name ?
   17.66 +					if ((path.Length > 1) && ((path[1] == '\\') || (path[1] == '/'))) {
   17.67 +						int index = 2;
   17.68 +						int elements = 2;
   17.69 +
   17.70 +						// Scan for two separate elements \\machine\share\restofpath
   17.71 +						while ((index <= path.Length) &&
   17.72 +							(((path[index] != '\\') && (path[index] != '/')) || (--elements > 0))) {
   17.73 +							index++;
   17.74 +						}
   17.75 +
   17.76 +						index++;
   17.77 +
   17.78 +						if (index < path.Length) {
   17.79 +							result = path.Substring(index);
   17.80 +						}
   17.81 +						else {
   17.82 +							result = "";
   17.83 +						}
   17.84 +					}
   17.85 +				}
   17.86 +				else if ((path.Length > 1) && (path[1] == ':')) {
   17.87 +					int dropCount = 2;
   17.88 +					if ((path.Length > 2) && ((path[2] == '\\') || (path[2] == '/'))) {
   17.89 +						dropCount = 3;
   17.90 +					}
   17.91 +					result = result.Remove(0, dropCount);
   17.92 +				}
   17.93 +			}
   17.94 +			return result;
   17.95 +		}
   17.96 +	}
   17.97 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/Encryption/PkzipClassic.cs	Sat Oct 30 14:03:17 2010 +0000
    18.3 @@ -0,0 +1,498 @@
    18.4 +//
    18.5 +// PkzipClassic encryption
    18.6 +//
    18.7 +// Copyright 2004 John Reilly
    18.8 +//
    18.9 +// This program is free software; you can redistribute it and/or
   18.10 +// modify it under the terms of the GNU General Public License
   18.11 +// as published by the Free Software Foundation; either version 2
   18.12 +// of the License, or (at your option) any later version.
   18.13 +//
   18.14 +// This program is distributed in the hope that it will be useful,
   18.15 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.16 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.17 +// GNU General Public License for more details.
   18.18 +//
   18.19 +// You should have received a copy of the GNU General Public License
   18.20 +// along with this program; if not, write to the Free Software
   18.21 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   18.22 +//
   18.23 +// Linking this library statically or dynamically with other modules is
   18.24 +// making a combined work based on this library.  Thus, the terms and
   18.25 +// conditions of the GNU General Public License cover the whole
   18.26 +// combination.
   18.27 +// 
   18.28 +// As a special exception, the copyright holders of this library give you
   18.29 +// permission to link this library with independent modules to produce an
   18.30 +// executable, regardless of the license terms of these independent
   18.31 +// modules, and to copy and distribute the resulting executable under
   18.32 +// terms of your choice, provided that you also meet, for each linked
   18.33 +// independent module, the terms and conditions of the license of that
   18.34 +// module.  An independent module is a module which is not derived from
   18.35 +// or based on this library.  If you modify this library, you may extend
   18.36 +// this exception to your version of the library, but you are not
   18.37 +// obligated to do so.  If you do not wish to do so, delete this
   18.38 +// exception statement from your version.
   18.39 +//
   18.40 +
   18.41 +
   18.42 +#if !NETCF_1_0
   18.43 +
   18.44 +using System;
   18.45 +using System.Security.Cryptography;
   18.46 +using ICSharpCode.SharpZipLib.Checksums;
   18.47 +
   18.48 +namespace ICSharpCode.SharpZipLib.Encryption
   18.49 +{
   18.50 +	/// <summary>
   18.51 +	/// PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives.
   18.52 +	/// While it has been superceded by more recent and more powerful algorithms, its still in use and 
   18.53 +	/// is viable for preventing casual snooping
   18.54 +	/// </summary>
   18.55 +	public abstract class PkzipClassic : SymmetricAlgorithm
   18.56 +	{
   18.57 +		/// <summary>
   18.58 +		/// Generates new encryption keys based on given seed
   18.59 +		/// </summary>
   18.60 +		/// <param name="seed">The seed value to initialise keys with.</param>
   18.61 +		/// <returns>A new key value.</returns>
   18.62 +		static public byte[] GenerateKeys(byte[] seed)
   18.63 +		{
   18.64 +			if ( seed == null ) {
   18.65 +				throw new ArgumentNullException("seed");
   18.66 +			}
   18.67 +
   18.68 +			if ( seed.Length == 0 ) {
   18.69 +				throw new ArgumentException("Length is zero", "seed");
   18.70 +			}
   18.71 +
   18.72 +			uint[] newKeys = new uint[] {
   18.73 +				0x12345678,
   18.74 +				0x23456789,
   18.75 +				0x34567890
   18.76 +			 };
   18.77 +			
   18.78 +			for (int i = 0; i < seed.Length; ++i) {
   18.79 +				newKeys[0] = Crc32.ComputeCrc32(newKeys[0], seed[i]);
   18.80 +				newKeys[1] = newKeys[1] + (byte)newKeys[0];
   18.81 +				newKeys[1] = newKeys[1] * 134775813 + 1;
   18.82 +				newKeys[2] = Crc32.ComputeCrc32(newKeys[2], (byte)(newKeys[1] >> 24));
   18.83 +			}
   18.84 +
   18.85 +			byte[] result = new byte[12];
   18.86 +			result[0] = (byte)(newKeys[0] & 0xff);
   18.87 +			result[1] = (byte)((newKeys[0] >> 8) & 0xff);
   18.88 +			result[2] = (byte)((newKeys[0] >> 16) & 0xff);
   18.89 +			result[3] = (byte)((newKeys[0] >> 24) & 0xff);
   18.90 +			result[4] = (byte)(newKeys[1] & 0xff);
   18.91 +			result[5] = (byte)((newKeys[1] >> 8) & 0xff);
   18.92 +			result[6] = (byte)((newKeys[1] >> 16) & 0xff);
   18.93 +			result[7] = (byte)((newKeys[1] >> 24) & 0xff);
   18.94 +			result[8] = (byte)(newKeys[2] & 0xff);
   18.95 +			result[9] = (byte)((newKeys[2] >> 8) & 0xff);
   18.96 +			result[10] = (byte)((newKeys[2] >> 16) & 0xff);
   18.97 +			result[11] = (byte)((newKeys[2] >> 24) & 0xff);
   18.98 +			return result;
   18.99 +		}
  18.100 +	}
  18.101 +
  18.102 +	/// <summary>
  18.103 +	/// PkzipClassicCryptoBase provides the low level facilities for encryption
  18.104 +	/// and decryption using the PkzipClassic algorithm.
  18.105 +	/// </summary>
  18.106 +	class PkzipClassicCryptoBase
  18.107 +	{
  18.108 +		/// <summary>
  18.109 +		/// Transform a single byte 
  18.110 +		/// </summary>
  18.111 +		/// <returns>
  18.112 +		/// The transformed value
  18.113 +		/// </returns>
  18.114 +		protected byte TransformByte()
  18.115 +		{
  18.116 +			uint temp = ((keys[2] & 0xFFFF) | 2);
  18.117 +			return (byte)((temp * (temp ^ 1)) >> 8);
  18.118 +		}
  18.119 +
  18.120 +		/// <summary>
  18.121 +		/// Set the key schedule for encryption/decryption.
  18.122 +		/// </summary>
  18.123 +		/// <param name="keyData">The data use to set the keys from.</param>
  18.124 +		protected void SetKeys(byte[] keyData)
  18.125 +		{
  18.126 +			if ( keyData == null ) {
  18.127 +				throw new ArgumentNullException("keyData");
  18.128 +			}
  18.129 +		
  18.130 +			if ( keyData.Length != 12 ) {
  18.131 +				throw new InvalidOperationException("Key length is not valid");
  18.132 +			}
  18.133 +			
  18.134 +			keys = new uint[3];
  18.135 +			keys[0] = (uint)((keyData[3] << 24) | (keyData[2] << 16) | (keyData[1] << 8) | keyData[0]);
  18.136 +			keys[1] = (uint)((keyData[7] << 24) | (keyData[6] << 16) | (keyData[5] << 8) | keyData[4]);
  18.137 +			keys[2] = (uint)((keyData[11] << 24) | (keyData[10] << 16) | (keyData[9] << 8) | keyData[8]);
  18.138 +		}
  18.139 +
  18.140 +		/// <summary>
  18.141 +		/// Update encryption keys 
  18.142 +		/// </summary>		
  18.143 +		protected void UpdateKeys(byte ch)
  18.144 +		{
  18.145 +			keys[0] = Crc32.ComputeCrc32(keys[0], ch);
  18.146 +			keys[1] = keys[1] + (byte)keys[0];
  18.147 +			keys[1] = keys[1] * 134775813 + 1;
  18.148 +			keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24));
  18.149 +		}
  18.150 +
  18.151 +		/// <summary>
  18.152 +		/// Reset the internal state.
  18.153 +		/// </summary>
  18.154 +		protected void Reset()
  18.155 +		{
  18.156 +			keys[0] = 0;
  18.157 +			keys[1] = 0;
  18.158 +			keys[2] = 0;
  18.159 +		}
  18.160 +		
  18.161 +		#region Instance Fields
  18.162 +		uint[] keys;
  18.163 +		#endregion
  18.164 +	}
  18.165 +
  18.166 +	/// <summary>
  18.167 +	/// PkzipClassic CryptoTransform for encryption.
  18.168 +	/// </summary>
  18.169 +	class PkzipClassicEncryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform
  18.170 +	{
  18.171 +		/// <summary>
  18.172 +		/// Initialise a new instance of <see cref="PkzipClassicEncryptCryptoTransform"></see>
  18.173 +		/// </summary>
  18.174 +		/// <param name="keyBlock">The key block to use.</param>
  18.175 +		internal PkzipClassicEncryptCryptoTransform(byte[] keyBlock)
  18.176 +		{
  18.177 +			SetKeys(keyBlock);
  18.178 +		}
  18.179 +
  18.180 +		#region ICryptoTransform Members
  18.181 +
  18.182 +		/// <summary>
  18.183 +		/// Transforms the specified region of the specified byte array.
  18.184 +		/// </summary>
  18.185 +		/// <param name="inputBuffer">The input for which to compute the transform.</param>
  18.186 +		/// <param name="inputOffset">The offset into the byte array from which to begin using data.</param>
  18.187 +		/// <param name="inputCount">The number of bytes in the byte array to use as data.</param>
  18.188 +		/// <returns>The computed transform.</returns>
  18.189 +		public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
  18.190 +		{
  18.191 +			byte[] result = new byte[inputCount];
  18.192 +			TransformBlock(inputBuffer, inputOffset, inputCount, result, 0);
  18.193 +			return result;
  18.194 +		}
  18.195 +
  18.196 +		/// <summary>
  18.197 +		/// Transforms the specified region of the input byte array and copies 
  18.198 +		/// the resulting transform to the specified region of the output byte array.
  18.199 +		/// </summary>
  18.200 +		/// <param name="inputBuffer">The input for which to compute the transform.</param>
  18.201 +		/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
  18.202 +		/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
  18.203 +		/// <param name="outputBuffer">The output to which to write the transform.</param>
  18.204 +		/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
  18.205 +		/// <returns>The number of bytes written.</returns>
  18.206 +		public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
  18.207 +		{
  18.208 +			for (int i = inputOffset; i < inputOffset + inputCount; ++i) {
  18.209 +				byte oldbyte = inputBuffer[i];
  18.210 +				outputBuffer[outputOffset++] = (byte)(inputBuffer[i] ^ TransformByte());
  18.211 +				UpdateKeys(oldbyte);
  18.212 +			}
  18.213 +			return inputCount;
  18.214 +		}
  18.215 +
  18.216 +		/// <summary>
  18.217 +		/// Gets a value indicating whether the current transform can be reused.
  18.218 +		/// </summary>
  18.219 +		public bool CanReuseTransform
  18.220 +		{
  18.221 +			get {
  18.222 +				return true;
  18.223 +			}
  18.224 +		}
  18.225 +
  18.226 +		/// <summary>
  18.227 +		/// Gets the size of the input data blocks in bytes.
  18.228 +		/// </summary>
  18.229 +		public int InputBlockSize
  18.230 +		{
  18.231 +			get {
  18.232 +				return 1;
  18.233 +			}
  18.234 +		}
  18.235 +
  18.236 +		/// <summary>
  18.237 +		/// Gets the size of the output data blocks in bytes.
  18.238 +		/// </summary>
  18.239 +		public int OutputBlockSize
  18.240 +		{
  18.241 +			get {
  18.242 +				return 1;
  18.243 +			}
  18.244 +		}
  18.245 +
  18.246 +		/// <summary>
  18.247 +		/// Gets a value indicating whether multiple blocks can be transformed.
  18.248 +		/// </summary>
  18.249 +		public bool CanTransformMultipleBlocks
  18.250 +		{
  18.251 +			get {
  18.252 +				return true;
  18.253 +			}
  18.254 +		}
  18.255 +
  18.256 +		#endregion
  18.257 +
  18.258 +		#region IDisposable Members
  18.259 +
  18.260 +		/// <summary>
  18.261 +		/// Cleanup internal state.
  18.262 +		/// </summary>
  18.263 +		public void Dispose()
  18.264 +		{
  18.265 +			Reset();
  18.266 +		}
  18.267 +
  18.268 +		#endregion
  18.269 +	}
  18.270 +
  18.271 +
  18.272 +	/// <summary>
  18.273 +	/// PkzipClassic CryptoTransform for decryption.
  18.274 +	/// </summary>
  18.275 +	class PkzipClassicDecryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform
  18.276 +	{
  18.277 +		/// <summary>
  18.278 +		/// Initialise a new instance of <see cref="PkzipClassicDecryptCryptoTransform"></see>.
  18.279 +		/// </summary>
  18.280 +		/// <param name="keyBlock">The key block to decrypt with.</param>
  18.281 +		internal PkzipClassicDecryptCryptoTransform(byte[] keyBlock)
  18.282 +		{
  18.283 +			SetKeys(keyBlock);
  18.284 +		}
  18.285 +
  18.286 +		#region ICryptoTransform Members
  18.287 +
  18.288 +		/// <summary>
  18.289 +		/// Transforms the specified region of the specified byte array.
  18.290 +		/// </summary>
  18.291 +		/// <param name="inputBuffer">The input for which to compute the transform.</param>
  18.292 +		/// <param name="inputOffset">The offset into the byte array from which to begin using data.</param>
  18.293 +		/// <param name="inputCount">The number of bytes in the byte array to use as data.</param>
  18.294 +		/// <returns>The computed transform.</returns>
  18.295 +		public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
  18.296 +		{
  18.297 +			byte[] result = new byte[inputCount];
  18.298 +			TransformBlock(inputBuffer, inputOffset, inputCount, result, 0);
  18.299 +			return result;
  18.300 +		}
  18.301 +
  18.302 +		/// <summary>
  18.303 +		/// Transforms the specified region of the input byte array and copies 
  18.304 +		/// the resulting transform to the specified region of the output byte array.
  18.305 +		/// </summary>
  18.306 +		/// <param name="inputBuffer">The input for which to compute the transform.</param>
  18.307 +		/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
  18.308 +		/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
  18.309 +		/// <param name="outputBuffer">The output to which to write the transform.</param>
  18.310 +		/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
  18.311 +		/// <returns>The number of bytes written.</returns>
  18.312 +		public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
  18.313 +		{
  18.314 +			for (int i = inputOffset; i < inputOffset + inputCount; ++i) {
  18.315 +				byte newByte = (byte)(inputBuffer[i] ^ TransformByte());
  18.316 +				outputBuffer[outputOffset++] = newByte;
  18.317 +				UpdateKeys(newByte);
  18.318 +			}
  18.319 +			return inputCount;
  18.320 +		}
  18.321 +
  18.322 +		/// <summary>
  18.323 +		/// Gets a value indicating whether the current transform can be reused.
  18.324 +		/// </summary>
  18.325 +		public bool CanReuseTransform
  18.326 +		{
  18.327 +			get {
  18.328 +				return true;
  18.329 +			}
  18.330 +		}
  18.331 +
  18.332 +		/// <summary>
  18.333 +		/// Gets the size of the input data blocks in bytes.
  18.334 +		/// </summary>
  18.335 +		public int InputBlockSize
  18.336 +		{
  18.337 +			get {
  18.338 +				return 1;
  18.339 +			}
  18.340 +		}
  18.341 +
  18.342 +		/// <summary>
  18.343 +		/// Gets the size of the output data blocks in bytes.
  18.344 +		/// </summary>
  18.345 +		public int OutputBlockSize
  18.346 +		{
  18.347 +			get {
  18.348 +				return 1;
  18.349 +			}
  18.350 +		}
  18.351 +
  18.352 +		/// <summary>
  18.353 +		/// Gets a value indicating whether multiple blocks can be transformed.
  18.354 +		/// </summary>
  18.355 +		public bool CanTransformMultipleBlocks
  18.356 +		{
  18.357 +			get {
  18.358 +				return true;
  18.359 +			}
  18.360 +		}
  18.361 +
  18.362 +		#endregion
  18.363 +
  18.364 +		#region IDisposable Members
  18.365 +
  18.366 +		/// <summary>
  18.367 +		/// Cleanup internal state.
  18.368 +		/// </summary>
  18.369 +		public void Dispose()
  18.370 +		{
  18.371 +			Reset();
  18.372 +		}
  18.373 +
  18.374 +		#endregion
  18.375 +	}
  18.376 +
  18.377 +	/// <summary>
  18.378 +	/// Defines a wrapper object to access the Pkzip algorithm. 
  18.379 +	/// This class cannot be inherited.
  18.380 +	/// </summary>
  18.381 +	public sealed class PkzipClassicManaged : PkzipClassic
  18.382 +	{
  18.383 +		/// <summary>
  18.384 +		/// Get / set the applicable block size in bits.
  18.385 +		/// </summary>
  18.386 +		/// <remarks>The only valid block size is 8.</remarks>
  18.387 +		public override int BlockSize 
  18.388 +		{
  18.389 +			get { 
  18.390 +				return 8; 
  18.391 +			}
  18.392 +
  18.393 +			set {
  18.394 +				if (value != 8) {
  18.395 +					throw new CryptographicException("Block size is invalid");
  18.396 +				}
  18.397 +			}
  18.398 +		}
  18.399 +
  18.400 +		/// <summary>
  18.401 +		/// Get an array of legal <see cref="KeySizes">key sizes.</see>
  18.402 +		/// </summary>
  18.403 +		public override KeySizes[] LegalKeySizes
  18.404 +		{
  18.405 +			get {
  18.406 +				KeySizes[] keySizes = new KeySizes[1];
  18.407 +				keySizes[0] = new KeySizes(12 * 8, 12 * 8, 0);
  18.408 +				return keySizes; 
  18.409 +			}
  18.410 +		}
  18.411 +
  18.412 +		/// <summary>
  18.413 +		/// Generate an initial vector.
  18.414 +		/// </summary>
  18.415 +		public override void GenerateIV()
  18.416 +		{
  18.417 +			// Do nothing.
  18.418 +		}
  18.419 +
  18.420 +		/// <summary>
  18.421 +		/// Get an array of legal <see cref="KeySizes">block sizes</see>.
  18.422 +		/// </summary>
  18.423 +		public override KeySizes[] LegalBlockSizes
  18.424 +		{
  18.425 +			get {
  18.426 +				KeySizes[] keySizes = new KeySizes[1];
  18.427 +				keySizes[0] = new KeySizes(1 * 8, 1 * 8, 0);
  18.428 +				return keySizes; 
  18.429 +			}
  18.430 +		}
  18.431 +
  18.432 +		/// <summary>
  18.433 +		/// Get / set the key value applicable.
  18.434 +		/// </summary>
  18.435 +		public override byte[] Key
  18.436 +		{
  18.437 +			get {
  18.438 +				if ( key_ == null ) {
  18.439 +					GenerateKey();
  18.440 +				}
  18.441 +				
  18.442 +				return (byte[]) key_.Clone();
  18.443 +			}
  18.444 +		
  18.445 +			set {
  18.446 +				if ( value == null ) {
  18.447 +					throw new ArgumentNullException("value");
  18.448 +				}
  18.449 +				
  18.450 +				if ( value.Length != 12 ) {
  18.451 +					throw new CryptographicException("Key size is illegal");
  18.452 +				}
  18.453 +				
  18.454 +				key_ = (byte[]) value.Clone();
  18.455 +			}
  18.456 +		}
  18.457 +
  18.458 +		/// <summary>
  18.459 +		/// Generate a new random key.
  18.460 +		/// </summary>
  18.461 +		public override void GenerateKey()
  18.462 +		{
  18.463 +			key_ = new byte[12];
  18.464 +			Random rnd = new Random();
  18.465 +			rnd.NextBytes(key_);
  18.466 +		}
  18.467 +
  18.468 +		/// <summary>
  18.469 +		/// Create an encryptor.
  18.470 +		/// </summary>
  18.471 +		/// <param name="rgbKey">The key to use for this encryptor.</param>
  18.472 +		/// <param name="rgbIV">Initialisation vector for the new encryptor.</param>
  18.473 +		/// <returns>Returns a new PkzipClassic encryptor</returns>
  18.474 +		public override ICryptoTransform CreateEncryptor(
  18.475 +			byte[] rgbKey,
  18.476 +			byte[] rgbIV)
  18.477 +		{
  18.478 +			key_ = rgbKey;
  18.479 +			return new PkzipClassicEncryptCryptoTransform(Key);
  18.480 +		}
  18.481 +
  18.482 +		/// <summary>
  18.483 +		/// Create a decryptor.
  18.484 +		/// </summary>
  18.485 +		/// <param name="rgbKey">Keys to use for this new decryptor.</param>
  18.486 +		/// <param name="rgbIV">Initialisation vector for the new decryptor.</param>
  18.487 +		/// <returns>Returns a new decryptor.</returns>
  18.488 +		public override ICryptoTransform CreateDecryptor(
  18.489 +			byte[] rgbKey,
  18.490 +			byte[] rgbIV)
  18.491 +		{
  18.492 +			key_ = rgbKey;
  18.493 +			return new PkzipClassicDecryptCryptoTransform(Key);
  18.494 +		}
  18.495 +		
  18.496 +		#region Instance Fields
  18.497 +		byte[] key_;
  18.498 +		#endregion
  18.499 +	}
  18.500 +}
  18.501 +#endif
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/Encryption/ZipAESStream.cs	Sat Oct 30 14:03:17 2010 +0000
    19.3 @@ -0,0 +1,170 @@
    19.4 +//
    19.5 +// ZipAESStream.cs
    19.6 +//
    19.7 +// Copyright 2009 David Pierson
    19.8 +//
    19.9 +// This program is free software; you can redistribute it and/or
   19.10 +// modify it under the terms of the GNU General Public License
   19.11 +// as published by the Free Software Foundation; either version 2
   19.12 +// of the License, or (at your option) any later version.
   19.13 +//
   19.14 +// This program is distributed in the hope that it will be useful,
   19.15 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   19.16 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19.17 +// GNU General Public License for more details.
   19.18 +//
   19.19 +// You should have received a copy of the GNU General Public License
   19.20 +// along with this program; if not, write to the Free Software
   19.21 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   19.22 +//
   19.23 +// Linking this library statically or dynamically with other modules is
   19.24 +// making a combined work based on this library.  Thus, the terms and
   19.25 +// conditions of the GNU General Public License cover the whole
   19.26 +// combination.
   19.27 +// 
   19.28 +// As a special exception, the copyright holders of this library give you
   19.29 +// permission to link this library with independent modules to produce an
   19.30 +// executable, regardless of the license terms of these independent
   19.31 +// modules, and to copy and distribute the resulting executable under
   19.32 +// terms of your choice, provided that you also meet, for each linked
   19.33 +// independent module, the terms and conditions of the license of that
   19.34 +// module.  An independent module is a module which is not derived from
   19.35 +// or based on this library.  If you modify this library, you may extend
   19.36 +// this exception to your version of the library, but you are not
   19.37 +// obligated to do so.  If you do not wish to do so, delete this
   19.38 +// exception statement from your version.
   19.39 +// 
   19.40 +
   19.41 +#if !NET_1_1 && !NETCF_2_0
   19.42 +
   19.43 +using System;
   19.44 +using System.IO;
   19.45 +using System.Security.Cryptography;
   19.46 +
   19.47 +namespace ICSharpCode.SharpZipLib.Encryption {
   19.48 +
   19.49 +	// Based on information from http://www.winzip.com/aes_info.htm
   19.50 +	// and http://www.gladman.me.uk/cryptography_technology/fileencrypt/
   19.51 +
   19.52 +	/// <summary>
   19.53 +	/// Encrypts and decrypts AES ZIP
   19.54 +	/// </summary>
   19.55 +	internal class ZipAESStream : CryptoStream {
   19.56 +
   19.57 +		/// <summary>
   19.58 +		/// Constructor
   19.59 +		/// </summary>
   19.60 +		/// <param name="stream">The stream on which to perform the cryptographic transformation.</param>
   19.61 +		/// <param name="transform">Instance of ZipAESTransform</param>
   19.62 +		/// <param name="mode">Read or Write</param>
   19.63 +		public ZipAESStream(Stream stream, ZipAESTransform transform, CryptoStreamMode mode)
   19.64 +			: base(stream, transform, mode) {
   19.65 +
   19.66 +			_stream = stream;
   19.67 +			_transform = transform;
   19.68 +			_slideBuffer = new byte[1024];
   19.69 +
   19.70 +			_blockAndAuth = CRYPTO_BLOCK_SIZE + AUTH_CODE_LENGTH;
   19.71 +
   19.72 +			// mode:
   19.73 +			//  CryptoStreamMode.Read means we read from "stream" and pass decrypted to our Read() method.
   19.74 +			//  Write bypasses this stream and uses the Transform directly.
   19.75 +			if (mode != CryptoStreamMode.Read) {
   19.76 +				throw new Exception("ZipAESStream only for read");
   19.77 +			}
   19.78 +		}
   19.79 +
   19.80 +		// The final n bytes of the AES stream contain the Auth Code.
   19.81 +		private const int AUTH_CODE_LENGTH = 10;
   19.82 +
   19.83 +		private Stream _stream;
   19.84 +		private ZipAESTransform _transform;
   19.85 +		private byte[] _slideBuffer;
   19.86 +		private int _slideBufStartPos;
   19.87 +		private int _slideBufFreePos;
   19.88 +		// Blocksize is always 16 here, even for AES-256 which has transform.InputBlockSize of 32.
   19.89 +		private const int CRYPTO_BLOCK_SIZE = 16;
   19.90 +		private int _blockAndAuth;
   19.91 +
   19.92 +		/// <summary>
   19.93 +		/// Reads a sequence of bytes from the current CryptoStream into buffer,
   19.94 +		/// and advances the position within the stream by the number of bytes read.
   19.95 +		/// </summary>
   19.96 +		public override int Read(byte[] outBuffer, int offset, int count) {
   19.97 +			int nBytes = 0;
   19.98 +			while (nBytes < count) {
   19.99 +				// Calculate buffer quantities vs read-ahead size, and check for sufficient free space
  19.100 +				int byteCount = _slideBufFreePos - _slideBufStartPos;
  19.101 +
  19.102 +				// Need to handle final block and Auth Code specially, but don't know total data length.
  19.103 +				// Maintain a read-ahead equal to the length of (crypto block + Auth Code). 
  19.104 +				// When that runs out we can detect these final sections.
  19.105 +				int lengthToRead = _blockAndAuth - byteCount;
  19.106 +				if (_slideBuffer.Length - _slideBufFreePos < lengthToRead) {
  19.107 +					// Shift the data to the beginning of the buffer
  19.108 +					int iTo = 0;
  19.109 +					for (int iFrom = _slideBufStartPos; iFrom < _slideBufFreePos; iFrom++, iTo++) {
  19.110 +						_slideBuffer[iTo] = _slideBuffer[iFrom];
  19.111 +					}
  19.112 +					_slideBufFreePos -= _slideBufStartPos;		// Note the -=
  19.113 +					_slideBufStartPos = 0;
  19.114 +				}
  19.115 +				int obtained = _stream.Read(_slideBuffer, _slideBufFreePos, lengthToRead);
  19.116 +				_slideBufFreePos += obtained;
  19.117 +
  19.118 +				// Recalculate how much data we now have
  19.119 +				byteCount = _slideBufFreePos - _slideBufStartPos;
  19.120 +				if (byteCount >= _blockAndAuth) {
  19.121 +					// At least a 16 byte block and an auth code remains.
  19.122 +					_transform.TransformBlock(_slideBuffer,
  19.123 +											  _slideBufStartPos,
  19.124 +											  CRYPTO_BLOCK_SIZE,
  19.125 +											  outBuffer,
  19.126 +											  offset);
  19.127 +					nBytes += CRYPTO_BLOCK_SIZE;
  19.128 +					offset += CRYPTO_BLOCK_SIZE;
  19.129 +					_slideBufStartPos += CRYPTO_BLOCK_SIZE;
  19.130 +				} else {
  19.131 +					// Last round.
  19.132 +					if (byteCount > AUTH_CODE_LENGTH) {
  19.133 +						// At least one byte of data plus auth code
  19.134 +						int finalBlock = byteCount - AUTH_CODE_LENGTH;
  19.135 +						_transform.TransformBlock(_slideBuffer,
  19.136 +												  _slideBufStartPos,
  19.137 +												  finalBlock,
  19.138 +												  outBuffer,
  19.139 +												  offset);
  19.140 +
  19.141 +						nBytes += finalBlock;
  19.142 +						_slideBufStartPos += finalBlock;
  19.143 +					}
  19.144 +					else if (byteCount < AUTH_CODE_LENGTH)
  19.145 +						throw new Exception("Internal error missed auth code");	// Coding bug
  19.146 +					// Final block done. Check Auth code.
  19.147 +					byte[] calcAuthCode = _transform.GetAuthCode();
  19.148 +					for (int i = 0; i < AUTH_CODE_LENGTH; i++) {
  19.149 +						if (calcAuthCode[i] != _slideBuffer[_slideBufStartPos + i]) {
  19.150 +							throw new Exception("AES Authentication Code does not match. This is a super-CRC check on the data in the file after compression and encryption. \r\n"
  19.151 +								+ "The file may be damaged.");
  19.152 +						}
  19.153 +					}
  19.154 +
  19.155 +					break;	// Reached the auth code
  19.156 +				}
  19.157 +			}
  19.158 +			return nBytes;
  19.159 +		}
  19.160 +
  19.161 +		/// <summary>
  19.162 +		/// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
  19.163 +		/// </summary>
  19.164 +		/// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream. </param>
  19.165 +		/// <param name="offset">The byte offset in buffer at which to begin copying bytes to the current stream. </param>
  19.166 +		/// <param name="count">The number of bytes to be written to the current stream. </param>
  19.167 +		public override void Write(byte[] buffer, int offset, int count) {
  19.168 +			// ZipAESStream is used for reading but not for writing. Writing uses the ZipAESTransform directly.
  19.169 +			throw new NotImplementedException();
  19.170 +		}
  19.171 +	}
  19.172 +}
  19.173 +#endif
  19.174 \ No newline at end of file
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/Encryption/ZipAESTransform.cs	Sat Oct 30 14:03:17 2010 +0000
    20.3 @@ -0,0 +1,219 @@
    20.4 +//
    20.5 +// ZipAESTransform.cs
    20.6 +//
    20.7 +// Copyright 2009 David Pierson
    20.8 +//
    20.9 +// This program is free software; you can redistribute it and/or
   20.10 +// modify it under the terms of the GNU General Public License
   20.11 +// as published by the Free Software Foundation; either version 2
   20.12 +// of the License, or (at your option) any later version.
   20.13 +//
   20.14 +// This program is distributed in the hope that it will be useful,
   20.15 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.16 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.17 +// GNU General Public License for more details.
   20.18 +//
   20.19 +// You should have received a copy of the GNU General Public License
   20.20 +// along with this program; if not, write to the Free Software
   20.21 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   20.22 +//
   20.23 +// Linking this library statically or dynamically with other modules is
   20.24 +// making a combined work based on this library.  Thus, the terms and
   20.25 +// conditions of the GNU General Public License cover the whole
   20.26 +// combination.
   20.27 +// 
   20.28 +// As a special exception, the copyright holders of this library give you
   20.29 +// permission to link this library with independent modules to produce an
   20.30 +// executable, regardless of the license terms of these independent
   20.31 +// modules, and to copy and distribute the resulting executable under
   20.32 +// terms of your choice, provided that you also meet, for each linked
   20.33 +// independent module, the terms and conditions of the license of that
   20.34 +// module.  An independent module is a module which is not derived from
   20.35 +// or based on this library.  If you modify this library, you may extend
   20.36 +// this exception to your version of the library, but you are not
   20.37 +// obligated to do so.  If you do not wish to do so, delete this
   20.38 +// exception statement from your version.
   20.39 +//
   20.40 +
   20.41 +#if !NET_1_1 && !NETCF_2_0
   20.42 +// Framework version 2.0 required for Rfc2898DeriveBytes 
   20.43 +
   20.44 +using System;
   20.45 +using System.Security.Cryptography;
   20.46 +
   20.47 +namespace ICSharpCode.SharpZipLib.Encryption {
   20.48 +
   20.49 +	/// <summary>
   20.50 +	/// Transforms stream using AES in CTR mode
   20.51 +	/// </summary>
   20.52 +	internal class ZipAESTransform : ICryptoTransform {
   20.53 +
   20.54 +		private const int PWD_VER_LENGTH = 2;
   20.55 +
   20.56 +		// WinZip use iteration count of 1000 for PBKDF2 key generation
   20.57 +		private const int KEY_ROUNDS = 1000;
   20.58 +
   20.59 +		// For 128-bit AES (16 bytes) the encryption is implemented as expected.
   20.60 +		// For 256-bit AES (32 bytes) WinZip do full 256 bit AES of the nonce to create the encryption
   20.61 +		// block but use only the first 16 bytes of it, and discard the second half.
   20.62 +		private const int ENCRYPT_BLOCK = 16;
   20.63 +
   20.64 +		private int _blockSize;
   20.65 +		private ICryptoTransform _encryptor;
   20.66 +		private readonly byte[] _counterNonce;
   20.67 +		private byte[] _encryptBuffer;
   20.68 +		private int _encrPos;
   20.69 +		private byte[] _pwdVerifier;
   20.70 +		private HMACSHA1 _hmacsha1;
   20.71 +		private bool _finalised;
   20.72 +
   20.73 +		private bool _writeMode;
   20.74 +
   20.75 +		/// <summary>
   20.76 +		/// Constructor.
   20.77 +		/// </summary>
   20.78 +		/// <param name="key">Password string</param>
   20.79 +		/// <param name="saltBytes">Random bytes, length depends on encryption strength.
   20.80 +		/// 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes.</param>
   20.81 +		/// <param name="blockSize">The encryption strength, in bytes eg 16 for 128 bits.</param>
   20.82 +		/// <param name="writeMode">True when creating a zip, false when reading. For the AuthCode.</param>
   20.83 +		///
   20.84 +		public ZipAESTransform(string key, byte[] saltBytes, int blockSize, bool writeMode) {
   20.85 +
   20.86 +			if (blockSize != 16 && blockSize != 32)	// 24 valid for AES but not supported by Winzip
   20.87 +				throw new Exception("Invalid blocksize " + blockSize + ". Must be 16 or 32.");
   20.88 +			if (saltBytes.Length != blockSize / 2)
   20.89 +				throw new Exception("Invalid salt len. Must be " + blockSize / 2 + " for blocksize " + blockSize);
   20.90 +			// initialise the encryption buffer and buffer pos
   20.91 +			_blockSize = blockSize;
   20.92 +			_encryptBuffer = new byte[_blockSize];
   20.93 +			_encrPos = ENCRYPT_BLOCK;
   20.94 +
   20.95 +			// Performs the equivalent of derive_key in Dr Brian Gladman's pwd2key.c
   20.96 +			Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, saltBytes, KEY_ROUNDS);
   20.97 +			RijndaelManaged rm = new RijndaelManaged();
   20.98 +			rm.Mode = CipherMode.ECB;			// No feedback from cipher for CTR mode
   20.99 +			_counterNonce = new byte[_blockSize];
  20.100 +			byte[] byteKey1 = pdb.GetBytes(_blockSize);
  20.101 +			byte[] byteKey2 = pdb.GetBytes(_blockSize);
  20.102 +			_encryptor = rm.CreateEncryptor(byteKey1, byteKey2);
  20.103 +			_pwdVerifier = pdb.GetBytes(PWD_VER_LENGTH);
  20.104 +			//
  20.105 +			_hmacsha1 = new HMACSHA1(byteKey2);
  20.106 +			_writeMode = writeMode;
  20.107 +		}
  20.108 +
  20.109 +		/// <summary>
  20.110 +		/// Implement the ICryptoTransform method.
  20.111 +		/// </summary>
  20.112 +		public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) {
  20.113 +
  20.114 +			// Pass the data stream to the hash algorithm for generating the Auth Code.
  20.115 +			// This does not change the inputBuffer. Do this before decryption for read mode.
  20.116 +			if (!_writeMode) {
  20.117 +				_hmacsha1.TransformBlock(inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset);
  20.118 +			}
  20.119 +			// Encrypt with AES in CTR mode. Regards to Dr Brian Gladman for this.
  20.120 +			int ix = 0;
  20.121 +			while (ix < inputCount) {
  20.122 +				if (_encrPos == ENCRYPT_BLOCK) {
  20.123 +					/* increment encryption nonce   */
  20.124 +					int j = 0;
  20.125 +					while (++_counterNonce[j] == 0) {
  20.126 +						++j;
  20.127 +					}
  20.128 +					/* encrypt the nonce to form next xor buffer    */
  20.129 +					_encryptor.TransformBlock(_counterNonce, 0, _blockSize, _encryptBuffer, 0);
  20.130 +					_encrPos = 0;
  20.131 +				}
  20.132 +				outputBuffer[ix + outputOffset] = (byte)(inputBuffer[ix + inputOffset] ^ _encryptBuffer[_encrPos++]);
  20.133 +				//
  20.134 +				ix++;
  20.135 +			}
  20.136 +			if (_writeMode) {
  20.137 +				// This does not change the buffer. 
  20.138 +				_hmacsha1.TransformBlock(outputBuffer, outputOffset, inputCount, outputBuffer, outputOffset);
  20.139 +			}
  20.140 +			return inputCount;
  20.141 +		}
  20.142 +
  20.143 +		/// <summary>
  20.144 +		/// Returns the 2 byte password verifier
  20.145 +		/// </summary>
  20.146 +		public byte[] PwdVerifier {
  20.147 +			get {
  20.148 +				return _pwdVerifier;
  20.149 +			}
  20.150 +		}
  20.151 +
  20.152 +		/// <summary>
  20.153 +		/// Returns the 10 byte AUTH CODE to be checked or appended immediately following the AES data stream.
  20.154 +		/// </summary>
  20.155 +		public byte[] GetAuthCode() {
  20.156 +			// We usually don't get advance notice of final block. Hash requres a TransformFinal.
  20.157 +			if (!_finalised) {
  20.158 +				byte[] dummy = new byte[0];
  20.159 +				_hmacsha1.TransformFinalBlock(dummy, 0, 0);
  20.160 +				_finalised = true;
  20.161 +			}
  20.162 +			return _hmacsha1.Hash;
  20.163 +		}
  20.164 +
  20.165 +		#region ICryptoTransform Members
  20.166 +
  20.167 +		/// <summary>
  20.168 +		/// Not implemented.
  20.169 +		/// </summary>
  20.170 +		public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) {
  20.171 +
  20.172 +			throw new NotImplementedException("ZipAESTransform.TransformFinalBlock");
  20.173 +		}
  20.174 +
  20.175 +		/// <summary>
  20.176 +		/// Gets the size of the input data blocks in bytes.
  20.177 +		/// </summary>
  20.178 +		public int InputBlockSize {
  20.179 +			get {
  20.180 +				return _blockSize;
  20.181 +			}
  20.182 +		}
  20.183 +
  20.184 +		/// <summary>
  20.185 +		/// Gets the size of the output data blocks in bytes.
  20.186 +		/// </summary>
  20.187 +		public int OutputBlockSize {
  20.188 +			get {
  20.189 +				return _blockSize;
  20.190 +			}
  20.191 +		}
  20.192 +
  20.193 +		/// <summary>
  20.194 +		/// Gets a value indicating whether multiple blocks can be transformed.
  20.195 +		/// </summary>
  20.196 +		public bool CanTransformMultipleBlocks {
  20.197 +			get {
  20.198 +				return true;
  20.199 +			}
  20.200 +		}
  20.201 +
  20.202 +		/// <summary>
  20.203 +		/// Gets a value indicating whether the current transform can be reused.
  20.204 +		/// </summary>
  20.205 +		public bool CanReuseTransform {
  20.206 +			get {
  20.207 +				return true;
  20.208 +			}
  20.209 +		}
  20.210 +
  20.211 +		/// <summary>
  20.212 +		/// Cleanup internal state.
  20.213 +		/// </summary>
  20.214 +		public void Dispose() {
  20.215 +			_encryptor.Dispose();
  20.216 +		}
  20.217 +
  20.218 +		#endregion
  20.219 +
  20.220 +	}
  20.221 +}
  20.222 +#endif
  20.223 \ No newline at end of file
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/GZip/GZIPConstants.cs	Sat Oct 30 14:03:17 2010 +0000
    21.3 @@ -0,0 +1,97 @@
    21.4 +// GZipConstants.cs
    21.5 +//
    21.6 +// Copyright (C) 2001 Mike Krueger
    21.7 +//
    21.8 +// This file was translated from java, it was part of the GNU Classpath
    21.9 +// Copyright (C) 2001 Free Software Foundation, Inc.
   21.10 +//
   21.11 +// This program is free software; you can redistribute it and/or
   21.12 +// modify it under the terms of the GNU General Public License
   21.13 +// as published by the Free Software Foundation; either version 2
   21.14 +// of the License, or (at your option) any later version.
   21.15 +//
   21.16 +// This program is distributed in the hope that it will be useful,
   21.17 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.18 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.19 +// GNU General Public License for more details.
   21.20 +//
   21.21 +// You should have received a copy of the GNU General Public License
   21.22 +// along with this program; if not, write to the Free Software
   21.23 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   21.24 +//
   21.25 +// Linking this library statically or dynamically with other modules is
   21.26 +// making a combined work based on this library.  Thus, the terms and
   21.27 +// conditions of the GNU General Public License cover the whole
   21.28 +// combination.
   21.29 +// 
   21.30 +// As a special exception, the copyright holders of this library give you
   21.31 +// permission to link this library with independent modules to produce an
   21.32 +// executable, regardless of the license terms of these independent
   21.33 +// modules, and to copy and distribute the resulting executable under
   21.34 +// terms of your choice, provided that you also meet, for each linked
   21.35 +// independent module, the terms and conditions of the license of that
   21.36 +// module.  An independent module is a module which is not derived from
   21.37 +// or based on this library.  If you modify this library, you may extend
   21.38 +// this exception to your version of the library, but you are not
   21.39 +// obligated to do so.  If you do not wish to do so, delete this
   21.40 +// exception statement from your version.
   21.41 +
   21.42 +namespace ICSharpCode.SharpZipLib.GZip 
   21.43 +{
   21.44 +	
   21.45 +	/// <summary>
   21.46 +	/// This class contains constants used for gzip.
   21.47 +	/// </summary>
   21.48 +	sealed public class GZipConstants
   21.49 +	{
   21.50 +		/// <summary>
   21.51 +		/// Magic number found at start of GZIP header
   21.52 +		/// </summary>
   21.53 +		public const int GZIP_MAGIC = 0x1F8B;
   21.54 +		
   21.55 +		/*  The flag byte is divided into individual bits as follows:
   21.56 +			
   21.57 +			bit 0   FTEXT
   21.58 +			bit 1   FHCRC
   21.59 +			bit 2   FEXTRA
   21.60 +			bit 3   FNAME
   21.61 +			bit 4   FCOMMENT
   21.62 +			bit 5   reserved
   21.63 +			bit 6   reserved
   21.64 +			bit 7   reserved
   21.65 +		 */
   21.66 +		 
   21.67 +		/// <summary>
   21.68 +		/// Flag bit mask for text
   21.69 +		/// </summary>
   21.70 +		public const int FTEXT    = 0x1;
   21.71 +		
   21.72 +		/// <summary>
   21.73 +		/// Flag bitmask for Crc
   21.74 +		/// </summary>
   21.75 +		public const int FHCRC    = 0x2;
   21.76 +		
   21.77 +		/// <summary>
   21.78 +		/// Flag bit mask for extra
   21.79 +		/// </summary>
   21.80 +		public const int FEXTRA   = 0x4;
   21.81 +		
   21.82 +		/// <summary>
   21.83 +		/// flag bitmask for name
   21.84 +		/// </summary>
   21.85 +		public const int FNAME    = 0x8;
   21.86 +		
   21.87 +		/// <summary>
   21.88 +		/// flag bit mask indicating comment is present
   21.89 +		/// </summary>
   21.90 +		public const int FCOMMENT = 0x10;
   21.91 +		
   21.92 +		/// <summary>
   21.93 +		/// Initialise default instance.
   21.94 +		/// </summary>
   21.95 +		/// <remarks>Constructor is private to prevent instances being created.</remarks>
   21.96 +		GZipConstants()
   21.97 +		{
   21.98 +		}
   21.99 +	}
  21.100 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/GZip/GZipException.cs	Sat Oct 30 14:03:17 2010 +0000
    22.3 @@ -0,0 +1,91 @@
    22.4 +// GZipException.cs
    22.5 +//
    22.6 +// Copyright 2004 John Reilly
    22.7 +//
    22.8 +// This program is free software; you can redistribute it and/or
    22.9 +// modify it under the terms of the GNU General Public License
   22.10 +// as published by the Free Software Foundation; either version 2
   22.11 +// of the License, or (at your option) any later version.
   22.12 +//
   22.13 +// This program is distributed in the hope that it will be useful,
   22.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.16 +// GNU General Public License for more details.
   22.17 +//
   22.18 +// You should have received a copy of the GNU General Public License
   22.19 +// along with this program; if not, write to the Free Software
   22.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   22.21 +//
   22.22 +// Linking this library statically or dynamically with other modules is
   22.23 +// making a combined work based on this library.  Thus, the terms and
   22.24 +// conditions of the GNU General Public License cover the whole
   22.25 +// combination.
   22.26 +// 
   22.27 +// As a special exception, the copyright holders of this library give you
   22.28 +// permission to link this library with independent modules to produce an
   22.29 +// executable, regardless of the license terms of these independent
   22.30 +// modules, and to copy and distribute the resulting executable under
   22.31 +// terms of your choice, provided that you also meet, for each linked
   22.32 +// independent module, the terms and conditions of the license of that
   22.33 +// module.  An independent module is a module which is not derived from
   22.34 +// or based on this library.  If you modify this library, you may extend
   22.35 +// this exception to your version of the library, but you are not
   22.36 +// obligated to do so.  If you do not wish to do so, delete this
   22.37 +// exception statement from your version.
   22.38 +
   22.39 +using System;
   22.40 +
   22.41 +#if !NETCF_1_0 && !NETCF_2_0
   22.42 +using System.Runtime.Serialization;
   22.43 +#endif
   22.44 +
   22.45 +namespace ICSharpCode.SharpZipLib.GZip
   22.46 +{
   22.47 +	/// <summary>
   22.48 +	/// GZipException represents a Gzip specific exception	
   22.49 +	/// </summary>
   22.50 +#if !NETCF_1_0 && !NETCF_2_0
   22.51 +	[Serializable]
   22.52 +#endif	
   22.53 +	public class GZipException : SharpZipBaseException
   22.54 +	{
   22.55 +#if !NETCF_1_0 && !NETCF_2_0
   22.56 +		/// <summary>
   22.57 +		/// Deserialization constructor 
   22.58 +		/// </summary>
   22.59 +		/// <param name="info"><see cref="SerializationInfo"/> for this constructor</param>
   22.60 +		/// <param name="context"><see cref="StreamingContext"/> for this constructor</param>
   22.61 +		protected GZipException(SerializationInfo info, StreamingContext context)
   22.62 +			: base(info, context)
   22.63 +
   22.64 +		{
   22.65 +		}
   22.66 +#endif
   22.67 +
   22.68 +		/// <summary>
   22.69 +		/// Initialise a new instance of GZipException
   22.70 +		/// </summary>
   22.71 +		public GZipException()
   22.72 +		{
   22.73 +		}
   22.74 +		
   22.75 +		/// <summary>
   22.76 +		/// Initialise a new instance of GZipException with its message string.
   22.77 +		/// </summary>
   22.78 +		/// <param name="message">A <see cref="string"/> that describes the error.</param>
   22.79 +		public GZipException(string message)
   22.80 +			: base(message)
   22.81 +		{
   22.82 +		}
   22.83 +		
   22.84 +		/// <summary>
   22.85 +		/// Initialise a new instance of <see cref="GZipException"></see>.
   22.86 +		/// </summary>
   22.87 +		/// <param name="message">A <see cref="string"/> that describes the error.</param>
   22.88 +		/// <param name="innerException">The <see cref="Exception"/> that caused this exception.</param>
   22.89 +		public GZipException(string message, Exception innerException)
   22.90 +			: base (message, innerException)
   22.91 +		{	
   22.92 +		}
   22.93 +	}
   22.94 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/GZip/GzipInputStream.cs	Sat Oct 30 14:03:17 2010 +0000
    23.3 @@ -0,0 +1,384 @@
    23.4 +// GzipInputStream.cs
    23.5 +//
    23.6 +// Copyright (C) 2001 Mike Krueger
    23.7 +//
    23.8 +// This file was translated from java, it was part of the GNU Classpath
    23.9 +// Copyright (C) 2001 Free Software Foundation, Inc.
   23.10 +//
   23.11 +// This program is free software; you can redistribute it and/or
   23.12 +// modify it under the terms of the GNU General Public License
   23.13 +// as published by the Free Software Foundation; either version 2
   23.14 +// of the License, or (at your option) any later version.
   23.15 +//
   23.16 +// This program is distributed in the hope that it will be useful,
   23.17 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.18 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.19 +// GNU General Public License for more details.
   23.20 +//
   23.21 +// You should have received a copy of the GNU General Public License
   23.22 +// along with this program; if not, write to the Free Software
   23.23 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   23.24 +//
   23.25 +// Linking this library statically or dynamically with other modules is
   23.26 +// making a combined work based on this library.  Thus, the terms and
   23.27 +// conditions of the GNU General Public License cover the whole
   23.28 +// combination.
   23.29 +// 
   23.30 +// As a special exception, the copyright holders of this library give you
   23.31 +// permission to link this library with independent modules to produce an
   23.32 +// executable, regardless of the license terms of these independent
   23.33 +// modules, and to copy and distribute the resulting executable under
   23.34 +// terms of your choice, provided that you also meet, for each linked
   23.35 +// independent module, the terms and conditions of the license of that
   23.36 +// module.  An independent module is a module which is not derived from
   23.37 +// or based on this library.  If you modify this library, you may extend
   23.38 +// this exception to your version of the library, but you are not
   23.39 +// obligated to do so.  If you do not wish to do so, delete this
   23.40 +// exception statement from your version.
   23.41 +
   23.42 +// HISTORY
   23.43 +//	11-08-2009	GeoffHart	T9121	Added Multi-member gzip support
   23.44 +
   23.45 +using System;
   23.46 +using System.IO;
   23.47 +
   23.48 +using ICSharpCode.SharpZipLib.Checksums;
   23.49 +using ICSharpCode.SharpZipLib.Zip.Compression;
   23.50 +using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
   23.51 +
   23.52 +namespace ICSharpCode.SharpZipLib.GZip 
   23.53 +{
   23.54 +	
   23.55 +	/// <summary>
   23.56 +	/// This filter stream is used to decompress a "GZIP" format stream.
   23.57 +	/// The "GZIP" format is described baseInputStream RFC 1952.
   23.58 +	/// 
   23.59 +	/// author of the original java version : John Leuner
   23.60 +	/// </summary>
   23.61 +	/// <example> This sample shows how to unzip a gzipped file
   23.62 +	/// <code>
   23.63 +	/// using System;
   23.64 +	/// using System.IO;
   23.65 +	/// 
   23.66 +	/// using ICSharpCode.SharpZipLib.Core;
   23.67 +	/// using ICSharpCode.SharpZipLib.GZip;
   23.68 +	/// 
   23.69 +	/// class MainClass
   23.70 +	/// {
   23.71 +	/// 	public static void Main(string[] args)
   23.72 +	/// 	{
   23.73 +	///			using (Stream inStream = new GZipInputStream(File.OpenRead(args[0])))
   23.74 +	///			using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) {
   23.75 +	///				byte[] buffer = new byte[4096];
   23.76 +	///				StreamUtils.Copy(inStream, outStream, buffer);
   23.77 +	/// 		}
   23.78 +	/// 	}
   23.79 +	/// }	
   23.80 +	/// </code>
   23.81 +	/// </example>
   23.82 +	public class GZipInputStream : InflaterInputStream
   23.83 +	{
   23.84 +		#region Instance Fields
   23.85 +		/// <summary>
   23.86 +		/// CRC-32 value for uncompressed data
   23.87 +		/// </summary>
   23.88 +        protected Crc32 crc;
   23.89 +		
   23.90 +        /// <summary>
   23.91 +        /// Flag to indicate if we've read the GZIP header yet for the current member (block of compressed data).
   23.92 +        /// This is tracked per-block as the file is parsed.
   23.93 +        /// </summary>
   23.94 +		bool readGZIPHeader;
   23.95 +		#endregion
   23.96 +
   23.97 +		#region Constructors
   23.98 +		/// <summary>
   23.99 +		/// Creates a GZipInputStream with the default buffer size
  23.100 +		/// </summary>
  23.101 +		/// <param name="baseInputStream">
  23.102 +		/// The stream to read compressed data from (baseInputStream GZIP format)
  23.103 +		/// </param>
  23.104 +		public GZipInputStream(Stream baseInputStream)
  23.105 +			: this(baseInputStream, 4096)
  23.106 +		{
  23.107 +		}
  23.108 +		
  23.109 +		/// <summary>
  23.110 +		/// Creates a GZIPInputStream with the specified buffer size
  23.111 +		/// </summary>
  23.112 +		/// <param name="baseInputStream">
  23.113 +		/// The stream to read compressed data from (baseInputStream GZIP format)
  23.114 +		/// </param>
  23.115 +		/// <param name="size">
  23.116 +		/// Size of the buffer to use
  23.117 +		/// </param>
  23.118 +		public GZipInputStream(Stream baseInputStream, int size)
  23.119 +			: base(baseInputStream, new Inflater(true), size)
  23.120 +		{
  23.121 +		}
  23.122 +		#endregion	
  23.123 +
  23.124 +		#region Stream overrides
  23.125 +		/// <summary>
  23.126 +		/// Reads uncompressed data into an array of bytes
  23.127 +		/// </summary>
  23.128 +		/// <param name="buffer">
  23.129 +		/// The buffer to read uncompressed data into
  23.130 +		/// </param>
  23.131 +		/// <param name="offset">
  23.132 +		/// The offset indicating where the data should be placed
  23.133 +		/// </param>
  23.134 +		/// <param name="count">
  23.135 +		/// The number of uncompressed bytes to be read
  23.136 +		/// </param>
  23.137 +		/// <returns>Returns the number of bytes actually read.</returns>
  23.138 +		public override int Read(byte[] buffer, int offset, int count) 
  23.139 +		{
  23.140 +			// A GZIP file can contain multiple blocks of compressed data, although this is quite rare.
  23.141 +			// A compressed block could potentially be empty, so we need to loop until we reach EOF or
  23.142 +			// we find data.
  23.143 +			while (true) {
  23.144 +
  23.145 +				// If we haven't read the header for this block, read it
  23.146 +				if (! readGZIPHeader) {
  23.147 +
  23.148 +					// Try to read header. If there is no header (0 bytes available), this is EOF. If there is
  23.149 +					// an incomplete header, this will throw an exception.
  23.150 +					if (! ReadHeader()) {
  23.151 +						return 0;
  23.152 +					}
  23.153 +				}
  23.154 +
  23.155 +				// Try to read compressed data
  23.156 +				int bytesRead = base.Read(buffer, offset, count);
  23.157 +				if (bytesRead > 0) {
  23.158 +					crc.Update(buffer, offset, bytesRead);
  23.159 +				}
  23.160 +
  23.161 +				// If this is the end of stream, read the footer
  23.162 +				if (inf.IsFinished) {
  23.163 +					ReadFooter();
  23.164 +				}
  23.165 +
  23.166 +				if (bytesRead > 0) {
  23.167 +					return bytesRead;
  23.168 +				}
  23.169 +			}
  23.170 +		}
  23.171 +		#endregion	
  23.172 +
  23.173 +		#region Support routines
  23.174 +		bool ReadHeader() 
  23.175 +		{
  23.176 +			// Initialize CRC for this block
  23.177 +			crc = new Crc32();
  23.178 +
  23.179 +			// Make sure there is data in file. We can't rely on ReadLeByte() to fill the buffer, as this could be EOF,
  23.180 +			// which is fine, but ReadLeByte() throws an exception if it doesn't find data, so we do this part ourselves.
  23.181 +			if (inputBuffer.Available <= 0) {
  23.182 +				inputBuffer.Fill();
  23.183 +				if (inputBuffer.Available <= 0) {
  23.184 +					// No header, EOF.
  23.185 +					return false;
  23.186 +				}
  23.187 +			}
  23.188 +
  23.189 +			// 1. Check the two magic bytes
  23.190 +			Crc32 headCRC = new Crc32();
  23.191 +			int magic = inputBuffer.ReadLeByte();
  23.192 +
  23.193 +			if (magic < 0) {
  23.194 +				throw new EndOfStreamException("EOS reading GZIP header");
  23.195 +			}
  23.196 +
  23.197 +			headCRC.Update(magic);
  23.198 +			if (magic != (GZipConstants.GZIP_MAGIC >> 8)) {
  23.199 +				throw new GZipException("Error GZIP header, first magic byte doesn't match");
  23.200 +			}
  23.201 +
  23.202 +			//magic = baseInputStream.ReadByte();
  23.203 +			magic = inputBuffer.ReadLeByte();
  23.204 +
  23.205 +			if (magic < 0) {
  23.206 +				throw new EndOfStreamException("EOS reading GZIP header");
  23.207 +			}
  23.208 +
  23.209 +			if (magic != (GZipConstants.GZIP_MAGIC & 0xFF)) {
  23.210 +				throw new GZipException("Error GZIP header,  second magic byte doesn't match");
  23.211 +			}
  23.212 +
  23.213 +			headCRC.Update(magic);
  23.214 +
  23.215 +			// 2. Check the compression type (must be 8)
  23.216 +			int compressionType = inputBuffer.ReadLeByte();
  23.217 +
  23.218 +			if ( compressionType < 0 ) {
  23.219 +				throw new EndOfStreamException("EOS reading GZIP header");
  23.220 +			}
  23.221 +
  23.222 +			if ( compressionType != 8 ) {
  23.223 +				throw new GZipException("Error GZIP header, data not in deflate format");
  23.224 +			}
  23.225 +			headCRC.Update(compressionType);
  23.226 +
  23.227 +			// 3. Check the flags
  23.228 +			int flags = inputBuffer.ReadLeByte();
  23.229 +			if (flags < 0) {
  23.230 +				throw new EndOfStreamException("EOS reading GZIP header");
  23.231 +			}
  23.232 +			headCRC.Update(flags);
  23.233 +
  23.234 +			/*    This flag byte is divided into individual bits as follows:
  23.235 +
  23.236 +			bit 0   FTEXT
  23.237 +			bit 1   FHCRC
  23.238 +			bit 2   FEXTRA
  23.239 +			bit 3   FNAME
  23.240 +			bit 4   FCOMMENT
  23.241 +			bit 5   reserved
  23.242 +			bit 6   reserved
  23.243 +			bit 7   reserved
  23.244 +			*/
  23.245 +
  23.246 +			// 3.1 Check the reserved bits are zero
  23.247 +
  23.248 +			if ((flags & 0xE0) != 0) {
  23.249 +				throw new GZipException("Reserved flag bits in GZIP header != 0");
  23.250 +			}
  23.251 +
  23.252 +			// 4.-6. Skip the modification time, extra flags, and OS type
  23.253 +			for (int i=0; i< 6; i++) {
  23.254 +				int readByte = inputBuffer.ReadLeByte();
  23.255 +				if (readByte < 0) {
  23.256 +					throw new EndOfStreamException("EOS reading GZIP header");
  23.257 +				}
  23.258 +				headCRC.Update(readByte);
  23.259 +			}
  23.260 +
  23.261 +			// 7. Read extra field
  23.262 +			if ((flags & GZipConstants.FEXTRA) != 0) {
  23.263 +				// Skip subfield id
  23.264 +				for (int i=0; i< 2; i++) {
  23.265 +					int readByte = inputBuffer.ReadLeByte();
  23.266 +					if (readByte < 0) {
  23.267 +						throw new EndOfStreamException("EOS reading GZIP header");
  23.268 +					}
  23.269 +					headCRC.Update(readByte);
  23.270 +				}
  23.271 +
  23.272 +				if (inputBuffer.ReadLeByte() < 0 || inputBuffer.ReadLeByte() < 0) {
  23.273 +					throw new EndOfStreamException("EOS reading GZIP header");
  23.274 +				}
  23.275 +
  23.276 +				int len1, len2;
  23.277 +				len1 = inputBuffer.ReadLeByte();
  23.278 +				len2 = inputBuffer.ReadLeByte();
  23.279 +				if ((len1 < 0) || (len2 < 0)) {
  23.280 +					throw new EndOfStreamException("EOS reading GZIP header");
  23.281 +				}
  23.282 +				headCRC.Update(len1);
  23.283 +				headCRC.Update(len2);
  23.284 +
  23.285 +				int extraLen = (len1 << 8) | len2;
  23.286 +				for (int i = 0; i < extraLen;i++) {
  23.287 +					int readByte = inputBuffer.ReadLeByte();
  23.288 +					if (readByte < 0) 
  23.289 +					{
  23.290 +						throw new EndOfStreamException("EOS reading GZIP header");
  23.291 +					}
  23.292 +					headCRC.Update(readByte);
  23.293 +				}
  23.294 +			}
  23.295 +
  23.296 +			// 8. Read file name
  23.297 +			if ((flags & GZipConstants.FNAME) != 0) {
  23.298 +				int readByte;
  23.299 +				while ( (readByte = inputBuffer.ReadLeByte()) > 0) {
  23.300 +					headCRC.Update(readByte);
  23.301 +				}
  23.302 +
  23.303 +				if (readByte < 0) {
  23.304 +					throw new EndOfStreamException("EOS reading GZIP header");
  23.305 +				}
  23.306 +				headCRC.Update(readByte);
  23.307 +			}
  23.308 +
  23.309 +			// 9. Read comment
  23.310 +			if ((flags & GZipConstants.FCOMMENT) != 0) {
  23.311 +				int readByte;
  23.312 +				while ( (readByte = inputBuffer.ReadLeByte()) > 0) {
  23.313 +					headCRC.Update(readByte);
  23.314 +				}
  23.315 +
  23.316 +				if (readByte < 0) {
  23.317 +					throw new EndOfStreamException("EOS reading GZIP header");
  23.318 +				}
  23.319 +
  23.320 +				headCRC.Update(readByte);
  23.321 +			}
  23.322 +
  23.323 +			// 10. Read header CRC
  23.324 +			if ((flags & GZipConstants.FHCRC) != 0) {
  23.325 +				int tempByte;
  23.326 +				int crcval = inputBuffer.ReadLeByte();
  23.327 +				if (crcval < 0) {
  23.328 +					throw new EndOfStreamException("EOS reading GZIP header");
  23.329 +				}
  23.330 +
  23.331 +				tempByte = inputBuffer.ReadLeByte();
  23.332 +				if (tempByte < 0) {
  23.333 +					throw new EndOfStreamException("EOS reading GZIP header");
  23.334 +				}
  23.335 +
  23.336 +				crcval = (crcval << 8) | tempByte;
  23.337 +				if (crcval != ((int) headCRC.Value & 0xffff)) {
  23.338 +					throw new GZipException("Header CRC value mismatch");
  23.339 +				}
  23.340 +			}
  23.341 +
  23.342 +			readGZIPHeader = true;
  23.343 +			return true;
  23.344 +		}
  23.345 +		
  23.346 +		void ReadFooter() 
  23.347 +		{
  23.348 +			byte[] footer = new byte[8];
  23.349 +
  23.350 +			// End of stream; reclaim all bytes from inf, read the final byte count, and reset the inflator
  23.351 +			long bytesRead = inf.TotalOut & 0xffffffff;
  23.352 +			inputBuffer.Available += inf.RemainingInput;
  23.353 +			inf.Reset();            
  23.354 +
  23.355 +			// Read footer from inputBuffer
  23.356 +			int needed = 8;
  23.357 +			while (needed > 0) {
  23.358 +				int count = inputBuffer.ReadClearTextBuffer(footer, 8 - needed, needed);
  23.359 +				if (count <= 0) {
  23.360 +					throw new EndOfStreamException("EOS reading GZIP footer");
  23.361 +				}
  23.362 +				needed -= count; // Jewel Jan 16
  23.363 +			}
  23.364 +
  23.365 +			// Calculate CRC
  23.366 +			int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8) | ((footer[2] & 0xff) << 16) | (footer[3] << 24);
  23.367 +			if (crcval != (int) crc.Value) {
  23.368 +				throw new GZipException("GZIP crc sum mismatch, theirs \"" + crcval + "\" and ours \"" + (int) crc.Value);
  23.369 +			}
  23.370 +
  23.371 +			// NOTE The total here is the original total modulo 2 ^ 32.
  23.372 +			uint total = 
  23.373 +				(uint)((uint)footer[4] & 0xff) |
  23.374 +				(uint)(((uint)footer[5] & 0xff) << 8) |
  23.375 +				(uint)(((uint)footer[6] & 0xff) << 16) |
  23.376 +				(uint)((uint)footer[7] << 24);
  23.377 +
  23.378 +			if (bytesRead != total) {
  23.379 +				throw new GZipException("Number of bytes mismatch in footer");
  23.380 +			}
  23.381 +
  23.382 +			// Mark header read as false so if another header exists, we'll continue reading through the file
  23.383 +			readGZIPHeader = false;
  23.384 +		}
  23.385 +		#endregion
  23.386 +	}
  23.387 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/GZip/GzipOutputStream.cs	Sat Oct 30 14:03:17 2010 +0000
    24.3 @@ -0,0 +1,261 @@
    24.4 +// GZipOutputStream.cs
    24.5 +//
    24.6 +// Copyright (C) 2001 Mike Krueger
    24.7 +//
    24.8 +// This file was translated from java, it was part of the GNU Classpath
    24.9 +// Copyright (C) 2001 Free Software Foundation, Inc.
   24.10 +//
   24.11 +// This program is free software; you can redistribute it and/or
   24.12 +// modify it under the terms of the GNU General Public License
   24.13 +// as published by the Free Software Foundation; either version 2
   24.14 +// of the License, or (at your option) any later version.
   24.15 +//
   24.16 +// This program is distributed in the hope that it will be useful,
   24.17 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.18 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.19 +// GNU General Public License for more details.
   24.20 +//
   24.21 +// You should have received a copy of the GNU General Public License
   24.22 +// along with this program; if not, write to the Free Software
   24.23 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   24.24 +//
   24.25 +// Linking this library statically or dynamically with other modules is
   24.26 +// making a combined work based on this library.  Thus, the terms and
   24.27 +// conditions of the GNU General Public License cover the whole
   24.28 +// combination.
   24.29 +// 
   24.30 +// As a special exception, the copyright holders of this library give you
   24.31 +// permission to link this library with independent modules to produce an
   24.32 +// executable, regardless of the license terms of these independent
   24.33 +// modules, and to copy and distribute the resulting executable under
   24.34 +// terms of your choice, provided that you also meet, for each linked
   24.35 +// independent module, the terms and conditions of the license of that
   24.36 +// module.  An independent module is a module which is not derived from
   24.37 +// or based on this library.  If you modify this library, you may extend
   24.38 +// this exception to your version of the library, but you are not
   24.39 +// obligated to do so.  If you do not wish to do so, delete this
   24.40 +// exception statement from your version.
   24.41 +
   24.42 +using System;
   24.43 +using System.IO;
   24.44 +
   24.45 +using ICSharpCode.SharpZipLib.Checksums;
   24.46 +using ICSharpCode.SharpZipLib.Zip.Compression;
   24.47 +using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
   24.48 +
   24.49 +namespace ICSharpCode.SharpZipLib.GZip 
   24.50 +{
   24.51 +	
   24.52 +	/// <summary>
   24.53 +	/// This filter stream is used to compress a stream into a "GZIP" stream.
   24.54 +	/// The "GZIP" format is described in RFC 1952.
   24.55 +	///
   24.56 +	/// author of the original java version : John Leuner
   24.57 +	/// </summary>
   24.58 +	/// <example> This sample shows how to gzip a file
   24.59 +	/// <code>
   24.60 +	/// using System;
   24.61 +	/// using System.IO;
   24.62 +	/// 
   24.63 +	/// using ICSharpCode.SharpZipLib.GZip;
   24.64 +	/// using ICSharpCode.SharpZipLib.Core;
   24.65 +	/// 
   24.66 +	/// class MainClass
   24.67 +	/// {
   24.68 +	/// 	public static void Main(string[] args)
   24.69 +	/// 	{
   24.70 +	/// 			using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz")))
   24.71 +	/// 			using (FileStream fs = File.OpenRead(args[0])) {
   24.72 +	/// 				byte[] writeData = new byte[4096];
   24.73 +	/// 				Streamutils.Copy(s, fs, writeData);
   24.74 +	/// 			}
   24.75 +	/// 		}
   24.76 +	/// 	}
   24.77 +	/// }	
   24.78 +	/// </code>
   24.79 +	/// </example>
   24.80 +	public class GZipOutputStream : DeflaterOutputStream
   24.81 +	{
   24.82 +        enum OutputState
   24.83 +        {
   24.84 +            Header,
   24.85 +            Footer, 
   24.86 +            Finished,
   24.87 +            Closed,
   24.88 +        };
   24.89 +
   24.90 +		#region Instance Fields
   24.91 +		/// <summary>
   24.92 +		/// CRC-32 value for uncompressed data
   24.93 +		/// </summary>
   24.94 +		protected Crc32 crc = new Crc32();
   24.95 +        OutputState state_ = OutputState.Header;
   24.96 +		#endregion
   24.97 +
   24.98 +		#region Constructors
   24.99 +		/// <summary>
  24.100 +		/// Creates a GzipOutputStream with the default buffer size
  24.101 +		/// </summary>
  24.102 +		/// <param name="baseOutputStream">
  24.103 +		/// The stream to read data (to be compressed) from
  24.104 +		/// </param>
  24.105 +		public GZipOutputStream(Stream baseOutputStream)
  24.106 +			: this(baseOutputStream, 4096)
  24.107 +		{
  24.108 +		}
  24.109 +		
  24.110 +		/// <summary>
  24.111 +		/// Creates a GZipOutputStream with the specified buffer size
  24.112 +		/// </summary>
  24.113 +		/// <param name="baseOutputStream">
  24.114 +		/// The stream to read data (to be compressed) from
  24.115 +		/// </param>
  24.116 +		/// <param name="size">
  24.117 +		/// Size of the buffer to use
  24.118 +		/// </param>
  24.119 +		public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size)
  24.120 +		{
  24.121 +		}
  24.122 +		#endregion
  24.123 +	
  24.124 +		#region Public API
  24.125 +		/// <summary>
  24.126 +		/// Sets the active compression level (1-9).  The new level will be activated
  24.127 +		/// immediately.
  24.128 +		/// </summary>
  24.129 +		/// <param name="level">The compression level to set.</param>
  24.130 +		/// <exception cref="ArgumentOutOfRangeException">
  24.131 +		/// Level specified is not supported.
  24.132 +		/// </exception>
  24.133 +		/// <see cref="Deflater"/>
  24.134 +		public void SetLevel(int level)
  24.135 +		{
  24.136 +			if (level < Deflater.BEST_SPEED) {
  24.137 +				throw new ArgumentOutOfRangeException("level");
  24.138 +			}
  24.139 +			deflater_.SetLevel(level);
  24.140 +		}
  24.141 +		
  24.142 +		/// <summary>
  24.143 +		/// Get the current compression level.
  24.144 +		/// </summary>
  24.145 +		/// <returns>The current compression level.</returns>
  24.146 +		public int GetLevel()
  24.147 +		{
  24.148 +			return deflater_.GetLevel();
  24.149 +		}
  24.150 +		#endregion
  24.151 +		
  24.152 +		#region Stream overrides
  24.153 +		/// <summary>
  24.154 +		/// Write given buffer to output updating crc
  24.155 +		/// </summary>
  24.156 +		/// <param name="buffer">Buffer to write</param>
  24.157 +		/// <param name="offset">Offset of first byte in buf to write</param>
  24.158 +		/// <param name="count">Number of bytes to write</param>
  24.159 +		public override void Write(byte[] buffer, int offset, int count)
  24.160 +		{
  24.161 +			if ( state_ == OutputState.Header ) {
  24.162 +				WriteHeader();
  24.163 +			}
  24.164 +
  24.165 +            if( state_!=OutputState.Footer )
  24.166 +            {
  24.167 +                throw new InvalidOperationException("Write not permitted in current state");
  24.168 +            }
  24.169 +
  24.170 +			crc.Update(buffer, offset, count);
  24.171 +			base.Write(buffer, offset, count);
  24.172 +		}
  24.173 +		
  24.174 +		/// <summary>
  24.175 +		/// Writes remaining compressed output data to the output stream
  24.176 +		/// and closes it.
  24.177 +		/// </summary>
  24.178 +		public override void Close()
  24.179 +		{
  24.180 +			try {
  24.181 +				Finish();
  24.182 +			}
  24.183 +			finally {
  24.184 +                if ( state_ != OutputState.Closed ) {
  24.185 +                    state_ = OutputState.Closed;
  24.186 +				    if( IsStreamOwner ) {
  24.187 +					    baseOutputStream_.Close();
  24.188 +				    }
  24.189 +                }
  24.190 +			}
  24.191 +		}
  24.192 +		#endregion
  24.193 +		
  24.194 +		#region DeflaterOutputStream overrides
  24.195 +		/// <summary>
  24.196 +		/// Finish compression and write any footer information required to stream
  24.197 +		/// </summary>
  24.198 +		public override void Finish()
  24.199 +		{
  24.200 +			// If no data has been written a header should be added.
  24.201 +			if ( state_ == OutputState.Header ) {
  24.202 +				WriteHeader();
  24.203 +			}
  24.204 +
  24.205 +            if( state_ == OutputState.Footer)
  24.206 +            {
  24.207 +                state_=OutputState.Finished;
  24.208 +                base.Finish();
  24.209 +
  24.210 +                uint totalin=(uint)(deflater_.TotalIn&0xffffffff);
  24.211 +                uint crcval=(uint)(crc.Value&0xffffffff);
  24.212 +
  24.213 +                byte[] gzipFooter;
  24.214 +
  24.215 +                unchecked
  24.216 +                {
  24.217 +                    gzipFooter=new byte[] {
  24.218 +					(byte) crcval, (byte) (crcval >> 8),
  24.219 +					(byte) (crcval >> 16), (byte) (crcval >> 24),
  24.220 +					
  24.221 +					(byte) totalin, (byte) (totalin >> 8),
  24.222 +					(byte) (totalin >> 16), (byte) (totalin >> 24)
  24.223 +				};
  24.224 +                }
  24.225 +
  24.226 +                baseOutputStream_.Write(gzipFooter, 0, gzipFooter.Length);
  24.227 +            }
  24.228 +		}
  24.229 +		#endregion
  24.230 +		
  24.231 +		#region Support Routines
  24.232 +		void WriteHeader()
  24.233 +		{
  24.234 +			if ( state_ == OutputState.Header ) 
  24.235 +			{
  24.236 +                state_=OutputState.Footer;
  24.237 +
  24.238 +				int mod_time = (int)((DateTime.Now.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000L);  // Ticks give back 100ns intervals
  24.239 +				byte[] gzipHeader = {
  24.240 +					// The two magic bytes
  24.241 +					(byte) (GZipConstants.GZIP_MAGIC >> 8), (byte) (GZipConstants.GZIP_MAGIC & 0xff),
  24.242 +
  24.243 +					// The compression type
  24.244 +					(byte) Deflater.DEFLATED,
  24.245 +
  24.246 +					// The flags (not set)
  24.247 +					0,
  24.248 +
  24.249 +					// The modification time
  24.250 +					(byte) mod_time, (byte) (mod_time >> 8),
  24.251 +					(byte) (mod_time >> 16), (byte) (mod_time >> 24),
  24.252 +
  24.253 +					// The extra flags
  24.254 +					0,
  24.255 +
  24.256 +					// The OS type (unknown)
  24.257 +					(byte) 255
  24.258 +				};
  24.259 +				baseOutputStream_.Write(gzipHeader, 0, gzipHeader.Length);
  24.260 +			}
  24.261 +		}
  24.262 +		#endregion
  24.263 +	}
  24.264 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/ICSharpCode.SharpZLib.csproj	Sat Oct 30 14:03:17 2010 +0000
    25.3 @@ -0,0 +1,111 @@
    25.4 +<?xml version="1.0" encoding="utf-8"?>
    25.5 +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" xmlns:Conversion="urn:Conversion">
    25.6 +  <PropertyGroup>
    25.7 +    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    25.8 +    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    25.9 +    <SchemaVersion>2.0</SchemaVersion>
   25.10 +    <ProjectGuid>{0E7413FF-EB9E-4714-ACF2-BE3A6A7B2FFD}</ProjectGuid>
   25.11 +    <RootNamespace>ICSharpCode.SharpZipLib</RootNamespace>
   25.12 +    <AssemblyName>ICSharpCode.SharpZipLib</AssemblyName>
   25.13 +    <OutputType>Library</OutputType>
   25.14 +    <WarningLevel>4</WarningLevel>
   25.15 +    <NoStdLib>False</NoStdLib>
   25.16 +    <NoConfig>False</NoConfig>
   25.17 +    <RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
   25.18 +    <PreBuildEvent />
   25.19 +    <PostBuildEvent />
   25.20 +    <DocumentationFile>bin\ICSharpCode.SharpZipLib.xml</DocumentationFile>
   25.21 +    <ProductVersion>8.0.50727</ProductVersion>
   25.22 +  </PropertyGroup>
   25.23 +  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   25.24 +    <Optimize>true</Optimize>
   25.25 +    <OutputPath>bin\Release\</OutputPath>
   25.26 +    <DebugType>none</DebugType>
   25.27 +    <WarningLevel>4</WarningLevel>
   25.28 +  </PropertyGroup>
   25.29 +  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   25.30 +    <DebugSymbols>true</DebugSymbols>
   25.31 +    <Optimize>false</Optimize>
   25.32 +    <OutputPath>bin\Debug\</OutputPath>
   25.33 +    <DebugType>full</DebugType>
   25.34 +    <WarningLevel>4</WarningLevel>
   25.35 +  </PropertyGroup>
   25.36 +  <PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
   25.37 +    <RegisterForComInterop>False</RegisterForComInterop>
   25.38 +    <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
   25.39 +    <BaseAddress>4194304</BaseAddress>
   25.40 +    <PlatformTarget>AnyCPU</PlatformTarget>
   25.41 +    <FileAlignment>4096</FileAlignment>
   25.42 +  </PropertyGroup>
   25.43 +  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
   25.44 +    <DefineConstants>NET_2_0</DefineConstants>
   25.45 +  </PropertyGroup>
   25.46 +  <ItemGroup>
   25.47 +    <Reference Include="System" />
   25.48 +  </ItemGroup>
   25.49 +  <ItemGroup>
   25.50 +    <Compile Include="Core\WindowsPathUtils.cs" />
   25.51 +    <Compile Include="Encryption\ZipAESStream.cs" />
   25.52 +    <Compile Include="Encryption\ZipAESTransform.cs" />
   25.53 +    <Compile Include="Main.cs" />
   25.54 +    <Compile Include="AssemblyInfo.cs" />
   25.55 +    <Compile Include="Checksums\IChecksum.cs" />
   25.56 +    <Compile Include="Checksums\Adler32.cs" />
   25.57 +    <Compile Include="Zip\WindowsNameTransform.cs" />
   25.58 +    <Compile Include="Zip\ZipEntry.cs" />
   25.59 +    <Compile Include="Zip\ZipInputStream.cs" />
   25.60 +    <Compile Include="Zip\ZipOutputStream.cs" />
   25.61 +    <Compile Include="Zip\ZipConstants.cs" />
   25.62 +    <Compile Include="Zip\ZipFile.cs" />
   25.63 +    <Compile Include="GZip\GzipOutputStream.cs" />
   25.64 +    <Compile Include="GZip\GzipInputStream.cs" />
   25.65 +    <Compile Include="Zip\ZipException.cs" />
   25.66 +    <Compile Include="BZip2\BZip2InputStream.cs" />
   25.67 +    <Compile Include="BZip2\BZip2OutputStream.cs" />
   25.68 +    <Compile Include="BZip2\BZip2Constants.cs" />
   25.69 +    <Compile Include="BZip2\BZip2.cs" />
   25.70 +    <Compile Include="Tar\TarEntry.cs" />
   25.71 +    <Compile Include="Tar\TarHeader.cs" />
   25.72 +    <Compile Include="Tar\TarBuffer.cs" />
   25.73 +    <Compile Include="Tar\TarOutputStream.cs" />
   25.74 +    <Compile Include="Tar\InvalidHeaderException.cs" />
   25.75 +    <Compile Include="Tar\TarInputStream.cs" />
   25.76 +    <Compile Include="Tar\TarArchive.cs" />
   25.77 +    <Compile Include="Zip\Compression\PendingBuffer.cs" />
   25.78 +    <Compile Include="Zip\Compression\InflaterDynHeader.cs" />
   25.79 +    <Compile Include="Zip\Compression\InflaterHuffmanTree.cs" />
   25.80 +    <Compile Include="Zip\Compression\DeflaterPending.cs" />
   25.81 +    <Compile Include="Zip\Compression\DeflaterHuffman.cs" />
   25.82 +    <Compile Include="Zip\Compression\DeflaterEngine.cs" />
   25.83 +    <Compile Include="Zip\Compression\Inflater.cs" />
   25.84 +    <Compile Include="Zip\Compression\DeflaterConstants.cs" />
   25.85 +    <Compile Include="Zip\Compression\Deflater.cs" />
   25.86 +    <Compile Include="Zip\Compression\Streams\DeflaterOutputStream.cs" />
   25.87 +    <Compile Include="Zip\Compression\Streams\InflaterInputStream.cs" />
   25.88 +    <Compile Include="Zip\Compression\Streams\StreamManipulator.cs" />
   25.89 +    <Compile Include="Zip\Compression\Streams\OutputWindow.cs" />
   25.90 +    <Compile Include="SharpZipBaseException.cs" />
   25.91 +    <Compile Include="Tar\TarException.cs" />
   25.92 +    <Compile Include="GZip\GZipException.cs" />
   25.93 +    <Compile Include="BZip2\BZip2Exception.cs" />
   25.94 +    <Compile Include="Core\NameFilter.cs" />
   25.95 +    <Compile Include="Zip\FastZip.cs" />
   25.96 +    <Compile Include="Core\FileSystemScanner.cs" />
   25.97 +    <Compile Include="Core\PathFilter.cs" />
   25.98 +    <Compile Include="Core\INameTransform.cs" />
   25.99 +    <Compile Include="Zip\ZipNameTransform.cs" />
  25.100 +    <Compile Include="Encryption\PkzipClassic.cs" />
  25.101 +    <Compile Include="Core\IScanFilter.cs" />
  25.102 +    <Compile Include="Zip\ZipHelperStream.cs" />
  25.103 +    <Compile Include="Zip\ZipExtraData.cs" />
  25.104 +    <Compile Include="Core\StreamUtils.cs" />
  25.105 +    <Compile Include="Zip\ZipEntryFactory.cs" />
  25.106 +    <Compile Include="Zip\IEntryFactory.cs" />
  25.107 +    <Compile Include="Checksums\CRC32.cs" />
  25.108 +    <Compile Include="GZip\GZIPConstants.cs" />
  25.109 +    <Compile Include="Checksums\StrangeCRC.cs" />
  25.110 +  </ItemGroup>
  25.111 +  <ItemGroup />
  25.112 +  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
  25.113 +  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  25.114 +</Project>
  25.115 \ No newline at end of file
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/Main.cs	Sat Oct 30 14:03:17 2010 +0000
    26.3 @@ -0,0 +1,36 @@
    26.4 +// Main.cs
    26.5 +//
    26.6 +// Copyright (C) 2001 Mike Krueger
    26.7 +//
    26.8 +// This program is free software; you can redistribute it and/or
    26.9 +// modify it under the terms of the GNU General Public License
   26.10 +// as published by the Free Software Foundation; either version 2
   26.11 +// of the License, or (at your option) any later version.
   26.12 +//
   26.13 +// This program is distributed in the hope that it will be useful,
   26.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   26.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   26.16 +// GNU General Public License for more details.
   26.17 +//
   26.18 +// You should have received a copy of the GNU General Public License
   26.19 +// along with this program; if not, write to the Free Software
   26.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   26.21 +//
   26.22 +// Linking this library statically or dynamically with other modules is
   26.23 +// making a combined work based on this library.  Thus, the terms and
   26.24 +// conditions of the GNU General Public License cover the whole
   26.25 +// combination.
   26.26 +// 
   26.27 +// As a special exception, the copyright holders of this library give you
   26.28 +// permission to link this library with independent modules to produce an
   26.29 +// executable, regardless of the license terms of these independent
   26.30 +// modules, and to copy and distribute the resulting executable under
   26.31 +// terms of your choice, provided that you also meet, for each linked
   26.32 +// independent module, the terms and conditions of the license of that
   26.33 +// module.  An independent module is a module which is not derived from
   26.34 +// or based on this library.  If you modify this library, you may extend
   26.35 +// this exception to your version of the library, but you are not
   26.36 +// obligated to do so.  If you do not wish to do so, delete this
   26.37 +// exception statement from your version.
   26.38 +//
   26.39 +
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/SharpZipBaseException.cs	Sat Oct 30 14:03:17 2010 +0000
    27.3 @@ -0,0 +1,94 @@
    27.4 +// SharpZipBaseException.cs
    27.5 +//
    27.6 +// Copyright 2004 John Reilly
    27.7 +//
    27.8 +// This program is free software; you can redistribute it and/or
    27.9 +// modify it under the terms of the GNU General Public License
   27.10 +// as published by the Free Software Foundation; either version 2
   27.11 +// of the License, or (at your option) any later version.
   27.12 +//
   27.13 +// This program is distributed in the hope that it will be useful,
   27.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.16 +// GNU General Public License for more details.
   27.17 +//
   27.18 +// You should have received a copy of the GNU General Public License
   27.19 +// along with this program; if not, write to the Free Software
   27.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   27.21 +//
   27.22 +// Linking this library statically or dynamically with other modules is
   27.23 +// making a combined work based on this library.  Thus, the terms and
   27.24 +// conditions of the GNU General Public License cover the whole
   27.25 +// combination.
   27.26 +// 
   27.27 +// As a special exception, the copyright holders of this library give you
   27.28 +// permission to link this library with independent modules to produce an
   27.29 +// executable, regardless of the license terms of these independent
   27.30 +// modules, and to copy and distribute the resulting executable under
   27.31 +// terms of your choice, provided that you also meet, for each linked
   27.32 +// independent module, the terms and conditions of the license of that
   27.33 +// module.  An independent module is a module which is not derived from
   27.34 +// or based on this library.  If you modify this library, you may extend
   27.35 +// this exception to your version of the library, but you are not
   27.36 +// obligated to do so.  If you do not wish to do so, delete this
   27.37 +// exception statement from your version.
   27.38 +
   27.39 +using System;
   27.40 +
   27.41 +#if !NETCF_1_0 && !NETCF_2_0
   27.42 +using System.Runtime.Serialization;
   27.43 +#endif
   27.44 +
   27.45 +namespace ICSharpCode.SharpZipLib
   27.46 +{
   27.47 +	/// <summary>
   27.48 +	/// SharpZipBaseException is the base exception class for the SharpZipLibrary.
   27.49 +	/// All library exceptions are derived from this.
   27.50 +	/// </summary>
   27.51 +	/// <remarks>NOTE: Not all exceptions thrown will be derived from this class.
   27.52 +	/// A variety of other exceptions are possible for example <see cref="ArgumentNullException"></see></remarks>
   27.53 +#if !NETCF_1_0 && !NETCF_2_0
   27.54 +	[Serializable]
   27.55 +#endif
   27.56 +	public class SharpZipBaseException : ApplicationException
   27.57 +	{
   27.58 +#if !NETCF_1_0 && !NETCF_2_0
   27.59 +		/// <summary>
   27.60 +		/// Deserialization constructor 
   27.61 +		/// </summary>
   27.62 +		/// <param name="info"><see cref="System.Runtime.Serialization.SerializationInfo"/> for this constructor</param>
   27.63 +		/// <param name="context"><see cref="StreamingContext"/> for this constructor</param>
   27.64 +		protected SharpZipBaseException(SerializationInfo info, StreamingContext context )
   27.65 +			: base( info, context )
   27.66 +		{
   27.67 +		}
   27.68 +#endif
   27.69 +		
   27.70 +		/// <summary>
   27.71 +		/// Initializes a new instance of the SharpZipBaseException class.
   27.72 +		/// </summary>
   27.73 +		public SharpZipBaseException()
   27.74 +		{
   27.75 +		}
   27.76 +		
   27.77 +		/// <summary>
   27.78 +		/// Initializes a new instance of the SharpZipBaseException class with a specified error message.
   27.79 +		/// </summary>
   27.80 +		/// <param name="message">A message describing the exception.</param>
   27.81 +		public SharpZipBaseException(string message)
   27.82 +			: base(message)
   27.83 +		{
   27.84 +		}
   27.85 +
   27.86 +		/// <summary>
   27.87 +		/// Initializes a new instance of the SharpZipBaseException class with a specified
   27.88 +		/// error message and a reference to the inner exception that is the cause of this exception.
   27.89 +		/// </summary>
   27.90 +		/// <param name="message">A message describing the exception.</param>
   27.91 +		/// <param name="innerException">The inner exception</param>
   27.92 +		public SharpZipBaseException(string message, Exception innerException)
   27.93 +			: base(message, innerException)
   27.94 +		{
   27.95 +		}
   27.96 +	}
   27.97 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/Tar/InvalidHeaderException.cs	Sat Oct 30 14:03:17 2010 +0000
    28.3 @@ -0,0 +1,109 @@
    28.4 +// InvalidHeaderException.cs
    28.5 +//
    28.6 +// Copyright (C) 2001 Mike Krueger
    28.7 +//
    28.8 +// This program is free software; you can redistribute it and/or
    28.9 +// modify it under the terms of the GNU General Public License
   28.10 +// as published by the Free Software Foundation; either version 2
   28.11 +// of the License, or (at your option) any later version.
   28.12 +//
   28.13 +// This program is distributed in the hope that it will be useful,
   28.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.16 +// GNU General Public License for more details.
   28.17 +//
   28.18 +// You should have received a copy of the GNU General Public License
   28.19 +// along with this program; if not, write to the Free Software
   28.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   28.21 +//
   28.22 +// Linking this library statically or dynamically with other modules is
   28.23 +// making a combined work based on this library.  Thus, the terms and
   28.24 +// conditions of the GNU General Public License cover the whole
   28.25 +// combination.
   28.26 +// 
   28.27 +// As a special exception, the copyright holders of this library give you
   28.28 +// permission to link this library with independent modules to produce an
   28.29 +// executable, regardless of the license terms of these independent
   28.30 +// modules, and to copy and distribute the resulting executable under
   28.31 +// terms of your choice, provided that you also meet, for each linked
   28.32 +// independent module, the terms and conditions of the license of that
   28.33 +// module.  An independent module is a module which is not derived from
   28.34 +// or based on this library.  If you modify this library, you may extend
   28.35 +// this exception to your version of the library, but you are not
   28.36 +// obligated to do so.  If you do not wish to do so, delete this
   28.37 +// exception statement from your version.
   28.38 +
   28.39 +using System;
   28.40 +
   28.41 +#if !NETCF_1_0 && !NETCF_2_0
   28.42 +using System.Runtime.Serialization;
   28.43 +#endif
   28.44 +
   28.45 +namespace ICSharpCode.SharpZipLib.Tar {
   28.46 +	
   28.47 +	/// <summary>
   28.48 +	/// This exception is used to indicate that there is a problem
   28.49 +	/// with a TAR archive header.
   28.50 +	/// </summary>
   28.51 +#if !NETCF_1_0 && !NETCF_2_0
   28.52 +	[Serializable]
   28.53 +#endif
   28.54 +	public class InvalidHeaderException : TarException
   28.55 +	{
   28.56 +
   28.57 +#if !NETCF_1_0 && !NETCF_2_0
   28.58 +		/// <summary>
   28.59 +		/// Deserialization constructor 
   28.60 +		/// </summary>
   28.61 +		/// <param name="information"><see cref="SerializationInfo"/> for this constructor</param>
   28.62 +		/// <param name="context"><see cref="StreamingContext"/> for this constructor</param>
   28.63 +		protected InvalidHeaderException(SerializationInfo information, StreamingContext context)
   28.64 +			: base(information, context)
   28.65 +
   28.66 +		{
   28.67 +		}
   28.68 +#endif
   28.69 +
   28.70 +		/// <summary>
   28.71 +		/// Initialise a new instance of the InvalidHeaderException class.
   28.72 +		/// </summary>
   28.73 +		public InvalidHeaderException()
   28.74 +		{
   28.75 +		}
   28.76 +
   28.77 +		/// <summary>
   28.78 +		/// Initialises a new instance of the InvalidHeaderException class with a specified message.
   28.79 +		/// </summary>
   28.80 +		/// <param name="message">Message describing the exception cause.</param>
   28.81 +		public InvalidHeaderException(string message)
   28.82 +			: base(message)
   28.83 +		{
   28.84 +		}
   28.85 +
   28.86 +		/// <summary>
   28.87 +		/// Initialise a new instance of InvalidHeaderException
   28.88 +		/// </summary>
   28.89 +		/// <param name="message">Message describing the problem.</param>
   28.90 +		/// <param name="exception">The exception that is the cause of the current exception.</param>
   28.91 +		public InvalidHeaderException(string message, Exception exception)
   28.92 +			: base(message, exception)
   28.93 +		{
   28.94 +		}
   28.95 +	}
   28.96 +}
   28.97 +
   28.98 +/* The original Java file had this header:
   28.99 +** Authored by Timothy Gerard Endres
  28.100 +** <mailto:time@gjt.org>  <http://www.trustice.com>
  28.101 +** 
  28.102 +** This work has been placed into the public domain.
  28.103 +** You may use this work in any way and for any purpose you wish.
  28.104 +**
  28.105 +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
  28.106 +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
  28.107 +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
  28.108 +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
  28.109 +** REDISTRIBUTION OF THIS SOFTWARE. 
  28.110 +** 
  28.111 +*/
  28.112 +
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/Tar/TarArchive.cs	Sat Oct 30 14:03:17 2010 +0000
    29.3 @@ -0,0 +1,894 @@
    29.4 +// TarArchive.cs
    29.5 +//
    29.6 +// Copyright (C) 2001 Mike Krueger
    29.7 +//
    29.8 +// This program is free software; you can redistribute it and/or
    29.9 +// modify it under the terms of the GNU General Public License
   29.10 +// as published by the Free Software Foundation; either version 2
   29.11 +// of the License, or (at your option) any later version.
   29.12 +//
   29.13 +// This program is distributed in the hope that it will be useful,
   29.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.16 +// GNU General Public License for more details.
   29.17 +//
   29.18 +// You should have received a copy of the GNU General Public License
   29.19 +// along with this program; if not, write to the Free Software
   29.20 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   29.21 +//
   29.22 +// Linking this library statically or dynamically with other modules is
   29.23 +// making a combined work based on this library.  Thus, the terms and
   29.24 +// conditions of the GNU General Public License cover the whole
   29.25 +// combination.
   29.26 +//
   29.27 +// As a special exception, the copyright holders of this library give you
   29.28 +// permission to link this library with independent modules to produce an
   29.29 +// executable, regardless of the license terms of these independent
   29.30 +// modules, and to copy and distribute the resulting executable under
   29.31 +// terms of your choice, provided that you also meet, for each linked
   29.32 +// independent module, the terms and conditions of the license of that
   29.33 +// module.  An independent module is a module which is not derived from
   29.34 +// or based on this library.  If you modify this library, you may extend
   29.35 +// this exception to your version of the library, but you are not
   29.36 +// obligated to do so.  If you do not wish to do so, delete this
   29.37 +// exception statement from your version.
   29.38 +
   29.39 +// HISTORY
   29.40 +//	28-01-2010	DavidPierson	Added IsStreamOwner
   29.41 +
   29.42 +using System;
   29.43 +using System.IO;
   29.44 +using System.Text;
   29.45 +
   29.46 +namespace ICSharpCode.SharpZipLib.Tar
   29.47 +{
   29.48 +	/// <summary>
   29.49 +	/// Used to advise clients of 'events' while processing archives
   29.50 +	/// </summary>
   29.51 +	public delegate void ProgressMessageHandler(TarArchive archive, TarEntry entry, string message);
   29.52 +
   29.53 +	/// <summary>
   29.54 +	/// The TarArchive class implements the concept of a
   29.55 +	/// 'Tape Archive'. A tar archive is a series of entries, each of
   29.56 +	/// which represents a file system object. Each entry in
   29.57 +	/// the archive consists of a header block followed by 0 or more data blocks.
   29.58 +	/// Directory entries consist only of the header block, and are followed by entries
   29.59 +	/// for the directory's contents. File entries consist of a
   29.60 +	/// header followed by the number of blocks needed to
   29.61 +	/// contain the file's contents. All entries are written on
   29.62 +	/// block boundaries. Blocks are 512 bytes long.
   29.63 +	/// 
   29.64 +	/// TarArchives are instantiated in either read or write mode,
   29.65 +	/// based upon whether they are instantiated with an InputStream
   29.66 +	/// or an OutputStream. Once instantiated TarArchives read/write
   29.67 +	/// mode can not be changed.
   29.68 +	/// 
   29.69 +	/// There is currently no support for random access to tar archives.
   29.70 +	/// However, it seems that subclassing TarArchive, and using the
   29.71 +	/// TarBuffer.CurrentRecord and TarBuffer.CurrentBlock
   29.72 +	/// properties, this would be rather trivial.
   29.73 +	/// </summary>
   29.74 +	public class TarArchive : IDisposable
   29.75 +	{
   29.76 +		/// <summary>
   29.77 +		/// Client hook allowing detailed information to be reported during processing
   29.78 +		/// </summary>
   29.79 +		public event ProgressMessageHandler ProgressMessageEvent;
   29.80 +		
   29.81 +		/// <summary>
   29.82 +		/// Raises the ProgressMessage event
   29.83 +		/// </summary>
   29.84 +		/// <param name="entry">The <see cref="TarEntry">TarEntry</see> for this event</param>
   29.85 +		/// <param name="message">message for this event.  Null is no message</param>
   29.86 +		protected virtual void OnProgressMessageEvent(TarEntry entry, string message)
   29.87 +		{
   29.88 +		    ProgressMessageHandler handler = ProgressMessageEvent;
   29.89 +			if (handler != null) {
   29.90 +				handler(this, entry, message);
   29.91 +			}
   29.92 +		}
   29.93 +		
   29.94 +		#region Constructors
   29.95 +		/// <summary>
   29.96 +		/// Constructor for a default <see cref="TarArchive"/>.
   29.97 +		/// </summary>
   29.98 +		protected TarArchive()
   29.99 +		{
  29.100 +		}
  29.101 +		
  29.102 +		/// <summary>
  29.103 +		/// Initalise a TarArchive for input.
  29.104 +		/// </summary>
  29.105 +		/// <param name="stream">The <see cref="TarInputStream"/> to use for input.</param>
  29.106 +		protected TarArchive(TarInputStream stream)
  29.107 +		{
  29.108 +			if ( stream == null ) {
  29.109 +				throw new ArgumentNullException("stream");
  29.110 +			}
  29.111 +			
  29.112 +			tarIn = stream;
  29.113 +		}
  29.114 +		
  29.115 +		/// <summary>
  29.116 +		/// Initialise a TarArchive for output.
  29.117 +		/// </summary>
  29.118 +		/// <param name="stream">The <see cref="TarOutputStream"/> to use for output.</param> 
  29.119 +		protected TarArchive(TarOutputStream stream)
  29.120 +		{
  29.121 +			if ( stream == null ) {
  29.122 +				throw new ArgumentNullException("stream");
  29.123 +			}
  29.124 +			
  29.125 +			tarOut = stream;
  29.126 +		}
  29.127 +		#endregion
  29.128 +		
  29.129 +		#region Static factory methods
  29.130 +		/// <summary>
  29.131 +		/// The InputStream based constructors create a TarArchive for the
  29.132 +		/// purposes of extracting or listing a tar archive. Thus, use
  29.133 +		/// these constructors when you wish to extract files from or list
  29.134 +		/// the contents of an existing tar archive.
  29.135 +		/// </summary>
  29.136 +		/// <param name="inputStream">The stream to retrieve archive data from.</param>
  29.137 +		/// <returns>Returns a new <see cref="TarArchive"/> suitable for reading from.</returns>
  29.138 +		public static TarArchive CreateInputTarArchive(Stream inputStream)
  29.139 +		{
  29.140 +			if ( inputStream == null ) {
  29.141 +				throw new ArgumentNullException("inputStream");
  29.142 +			}
  29.143 +
  29.144 +			TarInputStream tarStream = inputStream as TarInputStream;
  29.145 +
  29.146 +		    TarArchive result;
  29.147 +			if ( tarStream != null ) {
  29.148 +				result = new TarArchive(tarStream);
  29.149 +			}
  29.150 +			else {
  29.151 +				result = CreateInputTarArchive(inputStream, TarBuffer.DefaultBlockFactor);
  29.152 +			}
  29.153 +		    return result;
  29.154 +		}
  29.155 +		
  29.156 +		/// <summary>
  29.157 +		/// Create TarArchive for reading setting block factor
  29.158 +		/// </summary>
  29.159 +		/// <param name="inputStream">A stream containing the tar archive contents</param>
  29.160 +		/// <param name="blockFactor">The blocking factor to apply</param>
  29.161 +		/// <returns>Returns a <see cref="TarArchive"/> suitable for reading.</returns>
  29.162 +		public static TarArchive CreateInputTarArchive(Stream inputStream, int blockFactor)
  29.163 +		{
  29.164 +			if ( inputStream == null ) {
  29.165 +				throw new ArgumentNullException("inputStream");
  29.166 +			}
  29.167 +
  29.168 +			if ( inputStream is TarInputStream ) {
  29.169 +				throw new ArgumentException("TarInputStream not valid");
  29.170 +			}
  29.171 +			
  29.172 +			return new TarArchive(new TarInputStream(inputStream, blockFactor));
  29.173 +		}
  29.174 +		
  29.175 +		/// <summary>
  29.176 +		/// Create a TarArchive for writing to, using the default blocking factor
  29.177 +		/// </summary>
  29.178 +		/// <param name="outputStream">The <see cref="Stream"/> to write to</param>
  29.179 +		/// <returns>Returns a <see cref="TarArchive"/> suitable for writing.</returns>
  29.180 +		public static TarArchive CreateOutputTarArchive(Stream outputStream)
  29.181 +		{
  29.182 +			if ( outputStream == null ) {
  29.183 +				throw new ArgumentNullException("outputStream");
  29.184 +			}
  29.185 +			
  29.186 +            TarOutputStream tarStream = outputStream as TarOutputStream;
  29.187 +
  29.188 +		    TarArchive result;
  29.189 +			if ( tarStream != null ) {
  29.190 +				result = new TarArchive(tarStream);
  29.191 +			}
  29.192 +			else {
  29.193 +				result = CreateOutputTarArchive(outputStream, TarBuffer.DefaultBlockFactor);
  29.194 +			}
  29.195 +		    return result;
  29.196 +		}
  29.197 +
  29.198 +		/// <summary>
  29.199 +		/// Create a <see cref="TarArchive">tar archive</see> for writing.
  29.200 +		/// </summary>
  29.201 +		/// <param name="outputStream">The stream to write to</param>
  29.202 +		/// <param name="blockFactor">The blocking factor to use for buffering.</param>
  29.203 +		/// <returns>Returns a <see cref="TarArchive"/> suitable for writing.</returns>
  29.204 +		public static TarArchive CreateOutputTarArchive(Stream outputStream, int blockFactor)
  29.205 +		{
  29.206 +			if ( outputStream == null ) {
  29.207 +				throw new ArgumentNullException("outputStream");
  29.208 +			}
  29.209 +
  29.210 +			if ( outputStream is TarOutputStream ) {
  29.211 +				throw new ArgumentException("TarOutputStream is not valid");
  29.212 +			}
  29.213 +
  29.214 +			return new TarArchive(new TarOutputStream(outputStream, blockFactor));
  29.215 +		}
  29.216 +		#endregion
  29.217 +		
  29.218 +		/// <summary>
  29.219 +		/// Set the flag that determines whether existing files are
  29.220 +		/// kept, or overwritten during extraction.
  29.221 +		/// </summary>
  29.222 +		/// <param name="keepExistingFiles">
  29.223 +		/// If true, do not overwrite existing files.
  29.224 +		/// </param>
  29.225 +		public void SetKeepOldFiles(bool keepExistingFiles)
  29.226 +		{
  29.227 +			if ( isDisposed ) {
  29.228 +				throw new ObjectDisposedException("TarArchive");
  29.229 +			}
  29.230 +			
  29.231 +			keepOldFiles = keepExistingFiles;
  29.232 +		}
  29.233 +		
  29.234 +		/// <summary>
  29.235 +		/// Get/set the ascii file translation flag. If ascii file translation
  29.236 +		/// is true, then the file is checked to see if it a binary file or not. 
  29.237 +		/// If the flag is true and the test indicates it is ascii text 
  29.238 +		/// file, it will be translated. The translation converts the local
  29.239 +		/// operating system's concept of line ends into the UNIX line end,
  29.240 +		/// '\n', which is the defacto standard for a TAR archive. This makes
  29.241 +		/// text files compatible with UNIX.
  29.242 +		/// </summary>
  29.243 +		public bool AsciiTranslate
  29.244 +		{
  29.245 +			get {
  29.246 +				if ( isDisposed ) {
  29.247 +					throw new ObjectDisposedException("TarArchive");
  29.248 +				}
  29.249 +			
  29.250 +				return asciiTranslate;
  29.251 +			}
  29.252 +			
  29.253 +			set { 
  29.254 +				if ( isDisposed ) {
  29.255 +					throw new ObjectDisposedException("TarArchive");
  29.256 +				}
  29.257 +			
  29.258 +				asciiTranslate = value; 
  29.259 +			}
  29.260 +		
  29.261 +		}
  29.262 +		
  29.263 +		/// <summary>
  29.264 +		/// Set the ascii file translation flag.
  29.265 +		/// </summary>
  29.266 +		/// <param name= "translateAsciiFiles">
  29.267 +		/// If true, translate ascii text files.
  29.268 +		/// </param>
  29.269 +		[Obsolete("Use the AsciiTranslate property")]
  29.270 +		public void SetAsciiTranslation(bool translateAsciiFiles)
  29.271 +		{
  29.272 +			if ( isDisposed ) {
  29.273 +				throw new ObjectDisposedException("TarArchive");
  29.274 +			}
  29.275 +			
  29.276 +			asciiTranslate = translateAsciiFiles;
  29.277 +		}
  29.278 +
  29.279 +		/// <summary>
  29.280 +		/// PathPrefix is added to entry names as they are written if the value is not null.
  29.281 +		/// A slash character is appended after PathPrefix 
  29.282 +		/// </summary>
  29.283 +		public string PathPrefix
  29.284 +		{
  29.285 +			get { 
  29.286 +				if ( isDisposed ) {
  29.287 +					throw new ObjectDisposedException("TarArchive");
  29.288 +				}
  29.289 +			
  29.290 +				return pathPrefix;
  29.291 +			}
  29.292 +			
  29.293 +			set { 
  29.294 +				if ( isDisposed ) {
  29.295 +					throw new ObjectDisposedException("TarArchive");
  29.296 +				}
  29.297 +			
  29.298 +				pathPrefix = value;
  29.299 +			}
  29.300 +		
  29.301 +		}
  29.302 +		
  29.303 +		/// <summary>
  29.304 +		/// RootPath is removed from entry names if it is found at the
  29.305 +		/// beginning of the name.
  29.306 +		/// </summary>
  29.307 +		public string RootPath
  29.308 +		{
  29.309 +			get {
  29.310 +				if ( isDisposed ) {
  29.311 +					throw new ObjectDisposedException("TarArchive");
  29.312 +				}
  29.313 +			
  29.314 +				return rootPath;
  29.315 +			}
  29.316 +
  29.317 +			set {
  29.318 +				if ( isDisposed ) {
  29.319 +					throw new ObjectDisposedException("TarArchive");
  29.320 +				}
  29.321 +			
  29.322 +				rootPath = value;
  29.323 +			}
  29.324 +		}
  29.325 +		
  29.326 +		/// <summary>
  29.327 +		/// Set user and group information that will be used to fill in the
  29.328 +		/// tar archive's entry headers. This information is based on that available 
  29.329 +		/// for the linux operating system, which is not always available on other
  29.330 +		/// operating systems.  TarArchive allows the programmer to specify values
  29.331 +		/// to be used in their place.
  29.332 +		/// <see cref="ApplyUserInfoOverrides"/> is set to true by this call.
  29.333 +		/// </summary>
  29.334 +		/// <param name="userId">
  29.335 +		/// The user id to use in the headers.
  29.336 +		/// </param>
  29.337 +		/// <param name="userName">
  29.338 +		/// The user name to use in the headers.
  29.339 +		/// </param>
  29.340 +		/// <param name="groupId">
  29.341 +		/// The group id to use in the headers.
  29.342 +		/// </param>
  29.343 +		/// <param name="groupName">
  29.344 +		/// The group name to use in the headers.
  29.345 +		/// </param>
  29.346 +		public void SetUserInfo(int userId, string userName, int groupId, string groupName)
  29.347 +		{
  29.348 +			if ( isDisposed ) {
  29.349 +				throw new ObjectDisposedException("TarArchive");
  29.350 +			}
  29.351 +			
  29.352 +			this.userId    = userId;
  29.353 +			this.userName  = userName;
  29.354 +			this.groupId   = groupId;
  29.355 +			this.groupName = groupName;
  29.356 +			applyUserInfoOverrides = true;
  29.357 +		}
  29.358 +		
  29.359 +		/// <summary>
  29.360 +		/// Get or set a value indicating if overrides defined by <see cref="SetUserInfo">SetUserInfo</see> should be applied.
  29.361 +		/// </summary>
  29.362 +		/// <remarks>If overrides are not applied then the values as set in each header will be used.</remarks>
  29.363 +		public bool ApplyUserInfoOverrides
  29.364 +		{
  29.365 +			get {
  29.366 +				if ( isDisposed ) {
  29.367 +					throw new ObjectDisposedException("TarArchive");
  29.368 +				}
  29.369 +			
  29.370 +				return applyUserInfoOverrides;
  29.371 +			}
  29.372 +
  29.373 +			set {
  29.374 +				if ( isDisposed ) {
  29.375 +					throw new ObjectDisposedException("TarArchive");
  29.376 +				}
  29.377 +			
  29.378 +				applyUserInfoOverrides = value;
  29.379 +			}
  29.380 +		}
  29.381 +
  29.382 +		/// <summary>
  29.383 +		/// Get the archive user id.
  29.384 +		/// See <see cref="ApplyUserInfoOverrides">ApplyUserInfoOverrides</see> for detail
  29.385 +		/// on how to allow setting values on a per entry basis.
  29.386 +		/// </summary>
  29.387 +		/// <returns>
  29.388 +		/// The current user id.
  29.389 +		/// </returns>
  29.390 +		public int UserId {
  29.391 +			get {
  29.392 +				if ( isDisposed ) {
  29.393 +					throw new ObjectDisposedException("TarArchive");
  29.394 +				}
  29.395 +			
  29.396 +				return userId;
  29.397 +			}
  29.398 +		}
  29.399 +		
  29.400 +		/// <summary>
  29.401 +		/// Get the archive user name.
  29.402 +		/// See <see cref="ApplyUserInfoOverrides">ApplyUserInfoOverrides</see> for detail
  29.403 +		/// on how to allow setting values on a per entry basis.
  29.404 +		/// </summary>
  29.405 +		/// <returns>
  29.406 +		/// The current user name.
  29.407 +		/// </returns>
  29.408 +		public string UserName {
  29.409 +			get {
  29.410 +				if ( isDisposed ) {
  29.411 +					throw new ObjectDisposedException("TarArchive");
  29.412 +				}
  29.413 +			
  29.414 +				return userName;
  29.415 +			}
  29.416 +		}
  29.417 +		
  29.418 +		/// <summary>
  29.419 +		/// Get the archive group id.
  29.420 +		/// See <see cref="ApplyUserInfoOverrides">ApplyUserInfoOverrides</see> for detail
  29.421 +		/// on how to allow setting values on a per entry basis.
  29.422 +		/// </summary>
  29.423 +		/// <returns>
  29.424 +		/// The current group id.
  29.425 +		/// </returns>
  29.426 +		public int GroupId {
  29.427 +			get {
  29.428 +				if ( isDisposed ) {
  29.429 +					throw new ObjectDisposedException("TarArchive");
  29.430 +				}
  29.431 +			
  29.432 +				return groupId;
  29.433 +			}
  29.434 +		}
  29.435 +		
  29.436 +		/// <summary>
  29.437 +		/// Get the archive group name.
  29.438 +		/// See <see cref="ApplyUserInfoOverrides">ApplyUserInfoOverrides</see> for detail
  29.439 +		/// on how to allow setting values on a per entry basis.
  29.440 +		/// </summary>
  29.441 +		/// <returns>
  29.442 +		/// The current group name.
  29.443 +		/// </returns>
  29.444 +		public string GroupName {
  29.445 +			get {
  29.446 +				if ( isDisposed ) {
  29.447 +					throw new ObjectDisposedException("TarArchive");
  29.448 +				}
  29.449 +			
  29.450 +				return groupName;
  29.451 +			}
  29.452 +		}
  29.453 +		
  29.454 +		/// <summary>
  29.455 +		/// Get the archive's record size. Tar archives are composed of
  29.456 +		/// a series of RECORDS each containing a number of BLOCKS.
  29.457 +		/// This allowed tar archives to match the IO characteristics of
  29.458 +		/// the physical device being used. Archives are expected
  29.459 +		/// to be properly "blocked".
  29.460 +		/// </summary>
  29.461 +		/// <returns>
  29.462 +		/// The record size this archive is using.
  29.463 +		/// </returns>
  29.464 +		public int RecordSize {
  29.465 +			get {
  29.466 +				if ( isDisposed ) {
  29.467 +					throw new ObjectDisposedException("TarArchive");
  29.468 +				}
  29.469 +				
  29.470 +				if (tarIn != null) {
  29.471 +					return tarIn.RecordSize;
  29.472 +				} else if (tarOut != null) {
  29.473 +					return tarOut.RecordSize;
  29.474 +				}
  29.475 +				return TarBuffer.DefaultRecordSize;
  29.476 +			}
  29.477 +		}
  29.478 +		
  29.479 +		/// <summary>
  29.480 +		/// Sets the IsStreamOwner property on the underlying stream.
  29.481 +		/// Set this to false to prevent the Close of the TarArchive from closing the stream.
  29.482 +		/// </summary>
  29.483 +		public bool IsStreamOwner {
  29.484 +			set {
  29.485 +				if (tarIn != null) {
  29.486 +					tarIn.IsStreamOwner = value;
  29.487 +				} else {
  29.488 +					tarOut.IsStreamOwner = value;
  29.489 +				}
  29.490 +			}
  29.491 +		}
  29.492 +
  29.493 +		/// <summary>
  29.494 +		/// Close the archive.
  29.495 +		/// </summary>
  29.496 +		[Obsolete("Use Close instead")]
  29.497 +		public void CloseArchive()
  29.498 +		{
  29.499 +			Close();
  29.500 +		}
  29.501 +		
  29.502 +		/// <summary>
  29.503 +		/// Perform the "list" command for the archive contents.
  29.504 +		/// 
  29.505 +		/// NOTE That this method uses the <see cref="ProgressMessageEvent"> progress event</see> to actually list
  29.506 +		/// the contents. If the progress display event is not set, nothing will be listed!
  29.507 +		/// </summary>
  29.508 +		public void ListContents()
  29.509 +		{
  29.510 +			if ( isDisposed ) {
  29.511 +				throw new ObjectDisposedException("TarArchive");
  29.512 +			}
  29.513 +			
  29.514 +			while (true) {
  29.515 +				TarEntry entry = tarIn.GetNextEntry();
  29.516 +				
  29.517 +				if (entry == null) {
  29.518 +					break;
  29.519 +				}
  29.520 +				OnProgressMessageEvent(entry, null);
  29.521 +			}
  29.522 +		}
  29.523 +		
  29.524 +		/// <summary>
  29.525 +		/// Perform the "extract" command and extract the contents of the archive.
  29.526 +		/// </summary>
  29.527 +		/// <param name="destinationDirectory">
  29.528 +		/// The destination directory into which to extract.
  29.529 +		/// </param>
  29.530 +		public void ExtractContents(string destinationDirectory)
  29.531 +		{
  29.532 +			if ( isDisposed ) {
  29.533 +				throw new ObjectDisposedException("TarArchive");
  29.534 +			}
  29.535 +			
  29.536 +			while (true) {
  29.537 +				TarEntry entry = tarIn.GetNextEntry();
  29.538 +				
  29.539 +				if (entry == null) {
  29.540 +					break;
  29.541 +				}
  29.542 +				
  29.543 +				ExtractEntry(destinationDirectory, entry);
  29.544 +			}
  29.545 +		}
  29.546 +		
  29.547 +		/// <summary>
  29.548 +		/// Extract an entry from the archive. This method assumes that the
  29.549 +		/// tarIn stream has been properly set with a call to GetNextEntry().
  29.550 +		/// </summary>
  29.551 +		/// <param name="destDir">
  29.552 +		/// The destination directory into which to extract.
  29.553 +		/// </param>
  29.554 +		/// <param name="entry">
  29.555 +		/// The TarEntry returned by tarIn.GetNextEntry().
  29.556 +		/// </param>
  29.557 +		void ExtractEntry(string destDir, TarEntry entry)
  29.558 +		{
  29.559 +			OnProgressMessageEvent(entry, null);
  29.560 +			
  29.561 +			string name = entry.Name;
  29.562 +			
  29.563 +			if (Path.IsPathRooted(name)) {
  29.564 +				// NOTE:
  29.565 +				// for UNC names...  \\machine\share\zoom\beet.txt gives \zoom\beet.txt
  29.566 +				name = name.Substring(Path.GetPathRoot(name).Length);
  29.567 +			}
  29.568 +			
  29.569 +			name = name.Replace('/', Path.DirectorySeparatorChar);
  29.570 +			
  29.571 +			string destFile = Path.Combine(destDir, name);
  29.572 +			
  29.573 +			if (entry.IsDirectory) {
  29.574 +				EnsureDirectoryExists(destFile);
  29.575 +			} else {
  29.576 +				string parentDirectory = Path.GetDirectoryName(destFile);
  29.577 +				EnsureDirectoryExists(parentDirectory);
  29.578 +				
  29.579 +				bool process = true;
  29.580 +				FileInfo fileInfo = new FileInfo(destFile);
  29.581 +				if (fileInfo.Exists) {
  29.582 +					if (keepOldFiles) {
  29.583 +						OnProgressMessageEvent(entry, "Destination file already exists");
  29.584 +						process = false;
  29.585 +					} else if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0) {
  29.586 +						OnProgressMessageEvent(entry, "Destination file already exists, and is read-only");
  29.587 +						process = false;
  29.588 +					}
  29.589 +				}
  29.590 +				
  29.591 +				if (process) {
  29.592 +					bool asciiTrans = false;
  29.593 +					
  29.594 +					Stream outputStream = File.Create(destFile);
  29.595 +					if (this.asciiTranslate) {
  29.596 +						asciiTrans = !IsBinary(destFile);
  29.597 +					}
  29.598 +					
  29.599 +					StreamWriter outw = null;
  29.600 +					if (asciiTrans) {
  29.601 +						outw = new StreamWriter(outputStream);
  29.602 +					}
  29.603 +					
  29.604 +					byte[] rdbuf = new byte[32 * 1024];
  29.605 +					
  29.606 +					while (true) {
  29.607 +						int numRead = tarIn.Read(rdbuf, 0, rdbuf.Length);
  29.608 +						
  29.609 +						if (numRead <= 0) {
  29.610 +							break;
  29.611 +						}
  29.612 +						
  29.613 +						if (asciiTrans) {
  29.614 +							for (int off = 0, b = 0; b < numRead; ++b) {
  29.615 +								if (rdbuf[b] == 10) {
  29.616 +									string s = Encoding.ASCII.GetString(rdbuf, off, (b - off));
  29.617 +									outw.WriteLine(s);
  29.618 +									off = b + 1;
  29.619 +								}
  29.620 +							}
  29.621 +						} else {
  29.622 +							outputStream.Write(rdbuf, 0, numRead);
  29.623 +						}
  29.624 +					}
  29.625 +					
  29.626 +					if (asciiTrans) {
  29.627 +						outw.Close();
  29.628 +					} else {
  29.629 +						outputStream.Close();
  29.630 +					}
  29.631 +				}
  29.632 +			}
  29.633 +		}
  29.634 +
  29.635 +		/// <summary>
  29.636 +		/// Write an entry to the archive. This method will call the putNextEntry
  29.637 +		/// and then write the contents of the entry, and finally call closeEntry()
  29.638 +		/// for entries that are files. For directories, it will call putNextEntry(),
  29.639 +		/// and then, if the recurse flag is true, process each entry that is a
  29.640 +		/// child of the directory.
  29.641 +		/// </summary>
  29.642 +		/// <param name="sourceEntry">
  29.643 +		/// The TarEntry representing the entry to write to the archive.
  29.644 +		/// </param>
  29.645 +		/// <param name="recurse">
  29.646 +		/// If true, process the children of directory entries.
  29.647 +		/// </param>
  29.648 +		public void WriteEntry(TarEntry sourceEntry, bool recurse)
  29.649 +		{
  29.650 +			if ( sourceEntry == null ) {
  29.651 +				throw new ArgumentNullException("sourceEntry");
  29.652 +			}
  29.653 +			
  29.654 +			if ( isDisposed ) {
  29.655 +				throw new ObjectDisposedException("TarArchive");
  29.656 +			}
  29.657 +			
  29.658 +			try
  29.659 +			{
  29.660 +				if ( recurse ) {
  29.661 +					TarHeader.SetValueDefaults(sourceEntry.UserId, sourceEntry.UserName,
  29.662 +											   sourceEntry.GroupId, sourceEntry.GroupName);
  29.663 +				}
  29.664 +				WriteEntryCore(sourceEntry, recurse);
  29.665 +			}
  29.666 +			finally
  29.667 +			{
  29.668 +				if ( recurse ) {
  29.669 +					TarHeader.RestoreSetValues();
  29.670 +				}
  29.671 +			}
  29.672 +		}
  29.673 +		
  29.674 +		/// <summary>
  29.675 +		/// Write an entry to the archive. This method will call the putNextEntry
  29.676 +		/// and then write the contents of the entry, and finally call closeEntry()
  29.677 +		/// for entries that are files. For directories, it will call putNextEntry(),
  29.678 +		/// and then, if the recurse flag is true, process each entry that is a
  29.679 +		/// child of the directory.
  29.680 +		/// </summary>
  29.681 +		/// <param name="sourceEntry">
  29.682 +		/// The TarEntry representing the entry to write to the archive.
  29.683 +		/// </param>
  29.684 +		/// <param name="recurse">
  29.685 +		/// If true, process the children of directory entries.
  29.686 +		/// </param>
  29.687 +		void WriteEntryCore(TarEntry sourceEntry, bool recurse)
  29.688 +		{
  29.689 +			string tempFileName = null;
  29.690 +			string entryFilename   = sourceEntry.File;
  29.691 +			
  29.692 +			TarEntry entry = (TarEntry)sourceEntry.Clone();
  29.693 +
  29.694 +			if ( applyUserInfoOverrides ) {
  29.695 +				entry.GroupId = groupId;
  29.696 +				entry.GroupName = groupName;
  29.697 +				entry.UserId = userId;
  29.698 +				entry.UserName = userName;
  29.699 +			}
  29.700 +			
  29.701 +			OnProgressMessageEvent(entry, null);
  29.702 +			
  29.703 +			if (asciiTranslate && !entry.IsDirectory) {
  29.704 +
  29.705 +				if (!IsBinary(entryFilename)) {
  29.706 +					tempFileName = Path.GetTempFileName();
  29.707 +					
  29.708 +					using (StreamReader inStream  = File.OpenText(entryFilename)) {
  29.709 +						using (Stream outStream = File.Create(tempFileName)) {
  29.710 +						
  29.711 +							while (true) {
  29.712 +								string line = inStream.ReadLine();
  29.713 +								if (line == null) {
  29.714 +									break;
  29.715 +								}
  29.716 +								byte[] data = Encoding.ASCII.GetBytes(line);
  29.717 +								outStream.Write(data, 0, data.Length);
  29.718 +								outStream.WriteByte((byte)'\n');
  29.719 +							}
  29.720 +							
  29.721 +							outStream.Flush();
  29.722 +						}
  29.723 +					}
  29.724 +					
  29.725 +					entry.Size = new FileInfo(tempFileName).Length;
  29.726 +					entryFilename = tempFileName;
  29.727 +				}
  29.728 +			}
  29.729 +			
  29.730 +			string newName = null;
  29.731 +		
  29.732 +			if (rootPath != null) {
  29.733 +				if (entry.Name.StartsWith(rootPath)) {
  29.734 +					newName = entry.Name.Substring(rootPath.Length + 1 );
  29.735 +				}
  29.736 +			}
  29.737 +			
  29.738 +			if (pathPrefix != null) {
  29.739 +				newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName;
  29.740 +			}
  29.741 +			
  29.742 +			if (newName != null) {
  29.743 +				entry.Name = newName;
  29.744 +			}
  29.745 +			
  29.746 +			tarOut.PutNextEntry(entry);
  29.747 +			
  29.748 +			if (entry.IsDirectory) {
  29.749 +				if (recurse) {
  29.750 +					TarEntry[] list = entry.GetDirectoryEntries();
  29.751 +					for (int i = 0; i < list.Length; ++i) {
  29.752 +						WriteEntryCore(list[i], recurse);
  29.753 +					}
  29.754 +				}
  29.755 +			}
  29.756 +			else {
  29.757 +				using (Stream inputStream = File.OpenRead(entryFilename)) {
  29.758 +					byte[] localBuffer = new byte[32 * 1024];
  29.759 +					while (true) {
  29.760 +						int numRead = inputStream.Read(localBuffer, 0, localBuffer.Length);
  29.761 +						
  29.762 +						if (numRead <=0) {
  29.763 +							break;
  29.764 +						}
  29.765 +						
  29.766 +						tarOut.Write(localBuffer, 0, numRead);
  29.767 +					}
  29.768 +				}
  29.769 +				
  29.770 +				if ( (tempFileName != null) && (tempFileName.Length > 0) ) {
  29.771 +					File.Delete(tempFileName);
  29.772 +				}
  29.773 +				
  29.774 +				tarOut.CloseEntry();
  29.775 +			}
  29.776 +		}
  29.777 +
  29.778 +        /// <summary>
  29.779 +        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  29.780 +        /// </summary>
  29.781 +        public void Dispose()
  29.782 +        {
  29.783 +            Dispose(true);
  29.784 +            GC.SuppressFinalize(this);
  29.785 +        }
  29.786 +
  29.787 +	    /// <summary>
  29.788 +		/// Releases the unmanaged resources used by the FileStream and optionally releases the managed resources.
  29.789 +		/// </summary>
  29.790 +		/// <param name="disposing">true to release both managed and unmanaged resources;
  29.791 +		/// false to release only unmanaged resources.</param>
  29.792 +		protected virtual void Dispose(bool disposing)
  29.793 +		{
  29.794 +			if ( !isDisposed ) {
  29.795 +				isDisposed = true;
  29.796 +				if ( disposing ) {
  29.797 +					if ( tarOut != null ) {
  29.798 +						tarOut.Flush();
  29.799 +						tarOut.Close();
  29.800 +					}
  29.801 +		
  29.802 +					if ( tarIn != null ) {
  29.803 +						tarIn.Close();
  29.804 +					}
  29.805 +				}
  29.806 +			}
  29.807 +        }
  29.808 +		
  29.809 +		/// <summary>
  29.810 +		/// Closes the archive and releases any associated resources.
  29.811 +		/// </summary>
  29.812 +		public virtual void Close()
  29.813 +		{
  29.814 +			Dispose(true);
  29.815 +		}
  29.816 +		
  29.817 +		/// <summary>
  29.818 +		/// Ensures that resources are freed and other cleanup operations are performed
  29.819 +		/// when the garbage collector reclaims the <see cref="TarArchive"/>.
  29.820 +		/// </summary>
  29.821 +		~TarArchive()
  29.822 +		{
  29.823 +			Dispose(false);
  29.824 +		}
  29.825 +		
  29.826 +		static void EnsureDirectoryExists(string directoryName)
  29.827 +		{
  29.828 +			if (!Directory.Exists(directoryName)) {
  29.829 +				try {
  29.830 +					Directory.CreateDirectory(directoryName);
  29.831 +				}
  29.832 +				catch (Exception e) {
  29.833 +					throw new TarException("Exception creating directory '" + directoryName + "', " + e.Message, e);
  29.834 +				}
  29.835 +			}
  29.836 +		}
  29.837 +		
  29.838 +		// TODO: TarArchive - Is there a better way to test for a text file?
  29.839 +		// It no longer reads entire files into memory but is still a weak test!
  29.840 +		// This assumes that byte values 0-7, 14-31 or 255 are binary
  29.841 +		// and that all non text files contain one of these values
  29.842 +		static bool IsBinary(string filename)
  29.843 +		{
  29.844 +			using (FileStream fs = File.OpenRead(filename))
  29.845 +			{
  29.846 +				int sampleSize = Math.Min(4096, (int)fs.Length);
  29.847 +				byte[] content = new byte[sampleSize];
  29.848 +			
  29.849 +				int bytesRead = fs.Read(content, 0, sampleSize);
  29.850 +			
  29.851 +				for (int i = 0; i < bytesRead; ++i) {
  29.852 +					byte b = content[i];
  29.853 +					if ( (b < 8) || ((b > 13) && (b < 32)) || (b == 255) ) {
  29.854 +						return true;
  29.855 +					}
  29.856 +				}
  29.857 +			}
  29.858 +			return false;
  29.859 +		}		
  29.860 +		
  29.861 +		#region Instance Fields
  29.862 +		bool keepOldFiles;
  29.863 +		bool asciiTranslate;
  29.864 +		
  29.865 +		int    userId;
  29.866 +		string userName = string.Empty;
  29.867 +		int    groupId;
  29.868 +		string groupName = string.Empty;
  29.869 +		
  29.870 +		string rootPath;
  29.871 +		string pathPrefix;
  29.872 +		
  29.873 +		bool applyUserInfoOverrides;
  29.874 +		
  29.875 +		TarInputStream  tarIn;
  29.876 +		TarOutputStream tarOut;
  29.877 +		bool isDisposed;
  29.878 +		#endregion
  29.879 +	}
  29.880 +}
  29.881 +
  29.882 +
  29.883 +/* The original Java file had this header:
  29.884 +	** Authored by Timothy Gerard Endres
  29.885 +	** <mailto:time@gjt.org>  <http://www.trustice.com>
  29.886 +	**
  29.887 +	** This work has been placed into the public domain.
  29.888 +	** You may use this work in any way and for any purpose you wish.
  29.889 +	**
  29.890 +	** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
  29.891 +	** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
  29.892 +	** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
  29.893 +	** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
  29.894 +	** REDISTRIBUTION OF THIS SOFTWARE.
  29.895 +	**
  29.896 +	*/
  29.897 +
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/Tar/TarBuffer.cs	Sat Oct 30 14:03:17 2010 +0000
    30.3 @@ -0,0 +1,624 @@
    30.4 +// TarBuffer.cs
    30.5 +// Copyright (C) 2001 Mike Krueger
    30.6 +//
    30.7 +// This program is free software; you can redistribute it and/or
    30.8 +// modify it under the terms of the GNU General Public License
    30.9 +// as published by the Free Software Foundation; either version 2
   30.10 +// of the License, or (at your option) any later version.
   30.11 +//
   30.12 +// This program is distributed in the hope that it will be useful,
   30.13 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.14 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.15 +// GNU General Public License for more details.
   30.16 +//
   30.17 +// You should have received a copy of the GNU General Public License
   30.18 +// along with this program; if not, write to the Free Software
   30.19 +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   30.20 +//
   30.21 +// Linking this library statically or dynamically with other modules is
   30.22 +// making a combined work based on this library.  Thus, the terms and
   30.23 +// conditions of the GNU General Public License cover the whole
   30.24 +// combination.
   30.25 +//
   30.26 +// As a special exception, the copyright holders of this library give you
   30.27 +// permission to link this library with independent modules to produce an
   30.28 +// executable, regardless of the license terms of these independent
   30.29 +// modules, and to copy and distribute the resulting executable under
   30.30 +// terms of your choice, provided that you also meet, for each linked
   30.31 +// independent module, the terms and conditions of the license of that
   30.32 +// module.  An independent module is a module which is not derived from
   30.33 +// or based on this library.  If you modify this library, you may extend
   30.34 +// this exception to your version of the library, but you are not
   30.35 +// obligated to do so.  If you do not wish to do so, delete this
   30.36 +// exception statement from your version.
   30.37 +
   30.38 +using System;
   30.39 +using System.IO;
   30.40 +
   30.41 +namespace ICSharpCode.SharpZipLib.Tar 
   30.42 +{
   30.43 +	
   30.44 +	/// <summary>
   30.45 +	/// The TarBuffer class implements the tar archive concept
   30.46 +	/// of a buffered input stream. This concept goes back to the
   30.47 +	/// days of blocked tape drives and special io devices. In the
   30.48 +	/// C# universe, the only real function that this class
   30.49 +	/// performs is to ensure that files have the correct "record"
   30.50 +	/// size, or other tars will complain.
   30.51 +	/// <p>
   30.52 +	/// You should never have a need to access this class directly.
   30.53 +	/// TarBuffers are created by Tar IO Streams.
   30.54 +	/// </p>
   30.55 +	/// </summary>
   30.56 +	public class TarBuffer
   30.57 +	{
   30.58 +
   30.59 +/* A quote from GNU tar man file on blocking and records
   30.60 +   A `tar' archive file contains a series of blocks.  Each block
   30.61 +contains `BLOCKSIZE' bytes.  Although this format may be thought of as
   30.62 +being on magnetic tape, other media are often used.
   30.63 +
   30.64 +   Each file archived is represented by a header block which describes
   30.65 +the file, followed by zero or more blocks which give the contents of
   30.66 +the file.  At the end of the archive file there may be a block filled
   30.67 +with binary zeros as an end-of-file marker.  A reasonable system should
   30.68 +write a block of zeros at the end, but must not assume that such a
   30.69 +block exists when reading an archive.
   30.70 +
   30.71 +   The blocks may be "blocked" for physical I/O operations.  Each
   30.72 +record of N blocks is written with a single 'write ()'
   30.73 +operation.  On magnetic tapes, the result of such a write is a single
   30.74 +record.  When writing an archive, the last record of blocks should be
   30.75 +written at the full size, with blocks after the zero block containing
   30.76 +all zeros.  When reading an archive, a reasonable system should
   30.77 +properly handle an archive whose last record is shorter than the rest,
   30.78 +or which contains garbage records after a zero block.
   30.79 +*/
   30.80 +
   30.81 +		#region Constants
   30.82 +		/// <summary>
   30.83 +		/// The size of a block in a tar archive in bytes.
   30.84 +		/// </summary>
   30.85 +		/// <remarks>This is 512 bytes.</remarks>
   30.86 +		public const int BlockSize = 512;
   30.87 +		
   30.88 +		/// <summary>
   30.89 +		/// The number of blocks in a default record.
   30.90 +		/// </summary>
   30.91 +		/// <remarks>
   30.92 +		/// The default value is 20 blocks per record.
   30.93 +		/// </remarks>
   30.94 +		public const int DefaultBlockFactor = 20;
   30.95 +		
   30.96 +		/// <summary>
   30.97 +		/// The size in bytes of a default record.
   30.98 +		/// </summary>
   30.99 +		/// <remarks>
  30.100 +		/// The default size is 10KB.
  30.101 +		/// </remarks>
  30.102 +		public const int DefaultRecordSize = BlockSize * DefaultBlockFactor;
  30.103 +		#endregion
  30.104 +
  30.105 +		/// <summary>
  30.106 +		/// Get the record size for this buffer
  30.107 +		/// </summary>
  30.108 +		/// <value>The record size in bytes.
  30.109 +		/// This is equal to the <see cref="BlockFactor"/> multiplied by the <see cref="BlockSize"/></value>
  30.110 +		public int RecordSize 
  30.111 +		{
  30.112 +			get { 
  30.113 +				return recordSize; 
  30.114 +			}
  30.115 +		}
  30.116 +
  30.117 +		/// <summary>
  30.118 +		/// Get the TAR Buffer's record size.
  30.119 +		/// </summary>
  30.120 +		/// <returns>The record size in bytes.
  30.121 +		/// This is equal to the <see cref="BlockFactor"/> multiplied by the <see cref="BlockSize"/></returns>
  30.122 +		[Obsolete("Use RecordSize property instead")]
  30.123 +		public int GetRecordSize()
  30.124 +		{
  30.125 +			return recordSize;
  30.126 +		}
  30.127 +
  30.128 +		/// <summary>
  30.129 +		/// Get the Blocking factor for the buffer
  30.130 +		/// </summary>
  30.131 +		/// <value>This is the number of blocks in each record.</value>
  30.132 +		public int BlockFactor {
  30.133 +			get { 
  30.134 +				return blockFactor; 
  30.135 +			}
  30.136 +		}
  30.137 +
  30.138 +		/// <summary>
  30.139 +		/// Get the TAR Buffer's block factor
  30.140 +		/// </summary>
  30.141 +		/// <returns>The block factor; the number of blocks per record.</returns>
  30.142 +		[Obsolete("Use BlockFactor property instead")]
  30.143 +		public int GetBlockFactor()
  30.144 +		{
  30.145 +			return blockFactor;
  30.146 +		}
  30.147 +		
  30.148 +		/// <summary>
  30.149 +		/// Construct a default TarBuffer
  30.150 +		/// </summary>
  30.151 +		protected TarBuffer()
  30.152 +		{
  30.153 +		}
  30.154 +		
  30.155 +		/// <summary>
  30.156 +		/// Create TarBuffer for reading with default BlockFactor
  30.157 +		/// </summary>
  30.158 +		/// <param name="inputStream">Stream to buffer</param>
  30.159 +		/// <returns>A new <see cref="TarBuffer"/> suitable for input.</returns>
  30.160 +		public static TarBuffer CreateInputTarBuffer(Stream inputStream)
  30.161 +		{
  30.162 +			if ( inputStream == null )
  30.163 +			{
  30.164 +				throw new ArgumentNullException("inputStream");
  30.165 +			}
  30.166 +
  30.167 +			return CreateInputTarBuffer(inputStream, DefaultBlockFactor);
  30.168 +		}
  30.169 +
  30.170 +		/// <summary>
  30.171 +		/// Construct TarBuffer for reading inputStream setting BlockFactor
  30.172 +		/// </summary>
  30.173 +		/// <param name="inputStream">Stream to buffer</param>
  30.174 +		/// <param name="blockFactor">Blocking factor to apply</param>
  30.175 +		/// <returns>A new <see cref="TarBuffer"/> suitable for input.</returns>
  30.176 +		public static TarBuffer CreateInputTarBuffer(Stream inputStream, int blockFactor)
  30.177 +		{
  30.178 +			if ( inputStream == null )
  30.179 +			{
  30.180 +				throw new ArgumentNullException("inputStream");
  30.181 +			}
  30.182 +			
  30.183 +			if ( blockFactor <= 0 )
  30.184 +			{
  30.185 +#if NETCF_1_0
  30.186 +				throw new ArgumentOutOfRangeException("blockFactor");
  30.187 +#else
  30.188 +				throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative");
  30.189 +#endif				
  30.190 +			}
  30.191 +
  30.192 +			TarBuffer tarBuffer = new TarBuffer();
  30.193 +			tarBuffer.inputStream  = inputStream;
  30.194 +			tarBuffer.outputStream = null;
  30.195 +			tarBuffer.Initialize(blockFactor);
  30.196 +			
  30.197 +			return tarBuffer;
  30.198 +		}
  30.199 +
  30.200 +		/// <summary>
  30.201 +		/// Construct TarBuffer for writing with default BlockFactor
  30.202 +		/// </summary>
  30.203 +		/// <param name="outputStream">output stream for buffer</param>
  30.204 +		/// <returns>A new <see cref="TarBuffer"/> suitable for output.</returns>
  30.205 +		public static TarBuffer CreateOutputTarBuffer(Stream outputStream)
  30.206 +		{
  30.207 +			if ( outputStream == null )
  30.208 +			{
  30.209 +				throw new ArgumentNullException("outputStream");
  30.210 +			}
  30.211 +
  30.212 +			return CreateOutputTarBuffer(outputStream, DefaultBlockFactor);
  30.213 +		}
  30.214 +
  30.215 +		/// <summary>
  30.216 +		/// Construct TarBuffer for writing Tar output to streams.
  30.217 +		/// </summary>
  30.218 +		/// <param name="outputStream">Output stream to write to.</param>
  30.219 +		/// <param name="blockFactor">Blocking factor to apply</param>
  30.220 +		/// <returns>A new <see cref="TarBuffer"/> suitable for output.</returns>
  30.221 +		public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockFactor)
  30.222 +		{
  30.223 +			if ( outputStream == null )
  30.224 +			{
  30.225 +				throw new ArgumentNullException("outputStream");
  30.226 +			}
  30.227 +
  30.228 +			if ( blockFactor <= 0 )
  30.229 +			{
  30.230 +#if NETCF_1_0
  30.231 +				throw new ArgumentOutOfRangeException("blockFactor");
  30.232 +#else
  30.233 +				throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative");
  30.234 +#endif				
  30.235 +			}
  30.236 +
  30.237 +			TarBuffer tarBuffer = new TarBuffer();
  30.238 +			tarBuffer.inputStream  = null;
  30.239 +			tarBuffer.outputStream = outputStream;
  30.240 +			tarBuffer.Initialize(blockFactor);
  30.241 +			
  30.242 +			return tarBuffer;
  30.243 +		}
  30.244 +		
  30.245 +		/// <summary>
  30.246 +		/// Initialization common to all constructors.
  30.247 +		/// </summary>
  30.248 +		void Initialize(int archiveBlockFactor)
  30.249 +		{
  30.250 +			blockFactor  = archiveBlockFactor;
  30.251 +			recordSize   = archiveBlockFactor * BlockSize;
  30.252 +			recordBuffer  = new byte[RecordSize];
  30.253 +			
  30.254 +			if (inputStream != null) {
  30.255 +				currentRecordIndex = -1;
  30.256 +				currentBlockIndex = BlockFactor;
  30.257 +			}
  30.258 +			else {
  30.259 +				currentRecordIndex = 0;
  30.260 +				currentBlockIndex = 0;
  30.261 +			}
  30.262 +		}
  30.263 +		
  30.264 +		/// <summary>
  30.265 +		/// Determine if an archive block indicates End of Archive. End of
  30.266 +		/// archive is indicated by a block that consists entirely of null bytes.
  30.267 +		/// All remaining blocks for the record should also be null's
  30.268 +		/// However some older tars only do a couple of null blocks (Old GNU tar for one)
  30.269 +		/// and also partial records
  30.270 +		/// </summary>
  30.271 +		/// <param name = "block">The data block to check.</param>
  30.272 +		/// <returns>Returns true if the block is an EOF block; false otherwise.</returns>
  30.273 +		[Obsolete("Use IsEndOfArchiveBlock instead")]
  30.274 +		public bool IsEOFBlock(byte[] block)
  30.275 +		{
  30.276 +			if ( block == null ) {
  30.277 +				throw new ArgumentNullException("block");
  30.278 +			}
  30.279 +
  30.280 +			if ( block.Length != BlockSize ) 
  30.281 +			{
  30.282 +				throw new ArgumentException("block length is invalid");
  30.283 +			}
  30.284 +
  30.285 +			for (int i = 0; i < BlockSize; ++i) {
  30.286 +				if (block[i] != 0) {
  30.287 +					return false;
  30.288 +				}
  30.289 +			}
  30.290 +			
  30.291 +			return true;
  30.292 +		}
  30.293 +
  30.294 +
  30.295 +		/// <summary>
  30.296 +		/// Determine if an archive block indicates the End of an Archive has been reached.
  30.297 +		/// End of archive is indicated by a block that consists entirely of null bytes.
  30.298 +		/// All remaining blocks for the record should also be null's
  30.299 +		/// However some older tars only do a couple of null blocks (Old GNU tar for one)
  30.300 +		/// and also partial records
  30.301 +		/// </summary>
  30.302 +		/// <param name = "block">The data block to check.</param>
  30.303 +		/// <returns>Returns true if the block is an EOF block; false otherwise.</returns>
  30.304 +		public static bool IsEndOfArchiveBlock(byte[] block)
  30.305 +		{
  30.306 +			if ( block == null ) {
  30.307 +				throw new ArgumentNullException("block");
  30.308 +			}
  30.309 +
  30.310 +			if ( block.Length != BlockSize ) {
  30.311 +				throw new ArgumentException("block length is invalid");
  30.312 +			}
  30.313 +
  30.314 +			for ( int i = 0; i < BlockSize; ++i ) {
  30.315 +				if ( block[i] != 0 ) {
  30.316 +					return false;
  30.317 +				}
  30.318 +			}
  30.319 +
  30.320 +			return true;
  30.321 +		}
  30.322 +		
  30.323 +		/// <summary>
  30.324 +		/// Skip over a block on the input stream.
  30.325 +		/// </summary>
  30.326 +		public void SkipBlock()
  30.327 +		{
  30.328 +			if (inputStream == null) {
  30.329 +				throw new TarException("no input stream defined");
  30.330 +			}
  30.331 +			
  30.332 +			if (currentBlockIndex >= BlockFactor) {
  30.333 +				if (!ReadRecord()) {
  30.334 +					throw new TarException("Failed to read a record");
  30.335 +				}
  30.336 +			}
  30.337 +			
  30.338 +			currentBlockIndex++;
  30.339 +		}
  30.340 +		
  30.341 +		/// <summary>
  30.342 +		/// Read a block from the input stream.
  30.343 +		/// </summary>
  30.344 +		/// <returns>
  30.345 +		/// The block of data read.
  30.346 +		/// </returns>
  30.347 +		public byte[] ReadBlock()
  30.348 +		{
  30.349 +			if (inputStream == null) {
  30.350 +				throw new TarException("TarBuffer.ReadBlock - no input stream defined");
  30.351 +			}
  30.352 +			
  30.353 +			if (currentBlockIndex >= BlockFactor) {
  30.354 +				if (!ReadRecord()) {
  30.355 +					throw new TarException("Failed to read a record");
  30.356 +				}
  30.357 +			}
  30.358 +			
  30.359 +			byte[] result = new byte[BlockSize];
  30.360 +			
  30.361 +			Array.Copy(recordBuffer, (currentBlockIndex * BlockSize), result, 0, BlockSize );
  30.362 +			currentBlockIndex++;
  30.363 +			return result;
  30.364 +		}
  30.365 +		
  30.366 +		/// <summary>
  30.367 +		/// Read a record from data stream.
  30.368 +		/// </summary>
  30.369 +		/// <returns>
  30.370 +		/// false if End-Of-File, else true.
  30.371 +		/// </returns>
  30.372 +		bool ReadRecord()
  30.373 +		{
  30.374 +			if (inputStream == null) {
  30.375 +				throw new TarException("no input stream stream defined");
  30.376 +			}
  30.377 +						
  30.378 +			currentBlockIndex = 0;
  30.379 +			
  30.380 +			int offset = 0;
  30.381 +			int bytesNeeded = RecordSize;
  30.382 +
  30.383 +			while (bytesNeeded > 0) {
  30.384 +				long numBytes = inputStream.Read(recordBuffer, offset, bytesNeeded);
  30.385 +				
  30.386 +				//
  30.387 +				// NOTE
  30.388 +				// We have found EOF, and the record is not full!
  30.389 +				//
  30.390 +				// This is a broken archive. It does not follow the standard
  30.391 +				// blocking algorithm. However, because we are generous, and
  30.392 +				// it requires little effort, we will simply ignore the error
  30.393 +				// and continue as if the entire record were read. This does
  30.394 +				// not appear to break anything upstream. We used to return
  30.395 +				// false in this case.
  30.396 +				//
  30.397 +				// Thanks to 'Yohann.Roussel@alcatel.fr' for this fix.
  30.398 +				//
  30.399 +				if (numBytes <= 0) {
  30.400 +					break;
  30.401 +				}
  30.402 +				
  30.403 +				offset      += (int)numBytes;
  30.404 +				bytesNeeded -= (int)numBytes;
  30.405 +			}
  30.406 +			
  30.407 +			currentRecordIndex++;
  30.408 +			return true;
  30.409 +		}
  30.410 +		
  30.411 +		/// <summary>
  30.412 +		/// Get the current block number, within the current record, zero based.
  30.413 +		/// </summary>
  30.414 +        /// <remarks>Block numbers are zero based values</remarks>
  30.415 +        /// <seealso cref="RecordSize"/>
  30.416 +		public int CurrentBlock
  30.417 +		{
  30.418 +			get { return currentBlockIndex; }
  30.419 +		}
  30.420 +
  30.421 +        /// <summary>
  30.422 +        /// Get/set flag indicating ownership of the underlying stream.
  30.423 +        /// When the flag is true <see cref="Close"></see> will close the underlying stream also.
  30.424 +        /// </summary>
  30.425 +        public bool IsStreamOwner
  30.426 +        {
  30.427 +            get { return isStreamOwner_; }
  30.428 +            set { isStreamOwner_ = value; }
  30.429 +        }
  30.430 +
  30.431 +		/// <summary>
  30.432 +		/// Get the current block number, within the current record, zero based.
  30.433 +		/// </summary>
  30.434 +		/// <returns>
  30.435 +		/// The current zero based block number.
  30.436 +		/// </returns>
  30.437 +		/// <remarks>
  30.438 +		/// The absolute block number = (<see cref="GetCurrentRecordNum">record number</see> * <see cref="BlockFactor">block factor</see>) + <see cref="GetCurrentBlockNum">block number</see>.
  30.439 +		/// </remarks>
  30.440 +		[Obsolete("Use CurrentBlock property instead")]
  30.441 +		public int GetCurrentBlockNum()
  30.442 +		{
  30.443 +			return currentBlockIndex;
  30.444 +		}
  30.445 +		
  30.446 +		/// <summary>
  30.447 +		/// Get the current record number.
  30.448 +		/// </summary>
  30.449 +		/// <returns>
  30.450 +		/// The current zero based record number.
  30.451 +		/// </returns>
  30.452 +		public int CurrentRecord
  30.453 +		{
  30.454 +			get { return currentRecordIndex; }
  30.455 +		}
  30.456 +
  30.457 +		/// <summary>
  30.458 +		/// Get the current record number.
  30.459 +		/// </summary>
  30.460 +		/// <returns>
  30.461 +		/// The current zero based record number.
  30.462 +		/// </returns>
  30.463 +		[Obsolete("Use CurrentRecord property instead")]
  30.464 +		public int GetCurrentRecordNum()
  30.465 +		{
  30.466 +			return currentRecordIndex;
  30.467 +		}
  30.468 +		
  30.469 +		/// <summary>
  30.470 +		/// Write a block of data to the archive.
  30.471 +		/// </summary>
  30.472 +		/// <param name="block">
  30.473 +		/// The data to write to the archive.
  30.474 +		/// </param>
  30.475 +		public void WriteBlock(byte[] block)
  30.476 +		{
  30.477 +			if ( block == null ) {
  30.478 +				throw new ArgumentNullException("block");
  30.479 +			}
  30.480 +
  30.481 +			if (outputStream == null) {
  30.482 +				throw new TarException("TarBuffer.WriteBlock - no output stream defined");
  30.483 +			}
  30.484 +						
  30.485 +			if (block.Length != BlockSize) {
  30.486 +				string errorText = string.Format("TarBuffer.WriteBlock - block to write has length '{0}' which is not the block size of '{1}'",
  30.487 +					block.Length, BlockSize );
  30.488 +				throw new TarException(errorText);
  30.489 +			}
  30.490 +			
  30.491 +			if (currentBlockIndex >= BlockFactor) {
  30.492 +				WriteRecord();
  30.493 +			}
  30.494 +
  30.495 +			Array.Copy(block, 0, recordBuffer, (currentBlockIndex * BlockSize), BlockSize);
  30.496 +			currentBlockIndex++;
  30.497 +		}
  30.498 +		
  30.499 +		/// <summary>
  30.500 +		/// Write an archive record to the archive, where the record may be
  30.501 +		/// inside of a larger array buffer. The buffer must be "offset plus
  30.502 +		/// record size" long.
  30.503 +		/// </summary>
  30.504 +		/// <param name="buffer">
  30.505 +		/// The buffer containing the record data to write.
  30.506 +		/// </param>
  30.507 +		/// <param name="offset">
  30.508 +		/// The offset of the record data within buffer.
  30.509 +		/// </param>
  30.510 +		public void WriteBlock(byte[] buffer, int offset)
  30.511 +		{
  30.512 +			if ( buffer == null ) {
  30.513 +				throw new ArgumentNullException("buffer");
  30.514 +			}
  30.515 +
  30.516 +			if (outputStream == null) {
  30.517 +				throw new TarException("TarBuffer.WriteBlock - no output stream stream defined");
  30.518 +			}
  30.519 +						
  30.520 +			if ( (offset < 0) || (offset >= buffer.Length) )
  30.521 +			{
  30.522 +				throw new ArgumentOutOfRangeException("offset");
  30.523 +			}
  30.524 +
  30.525 +			if ((offset + BlockSize) > buffer.Length) {
  30.526 +				string errorText = string.Format("TarBuffer.WriteBlock - record has length '{0}' with offset '{1}' which is less than the record size of '{2}'",
  30.527 +					buffer.Length, offset, recordSize);
  30.528 +				throw new TarException(errorText);
  30.529 +			}
  30.530 +			
  30.531 +			if (currentBlockIndex >= BlockFactor) {
  30.532 +				WriteRecord();
  30.533 +			}
  30.534 +			
  30.535 +			Array.Copy(buffer, offset, recordBuffer, (currentBlockIndex * BlockSize), BlockSize);
  30.536 +			
  30.537 +			currentBlockIndex++;
  30.538 +		}
  30.539 +		
  30.540 +		/// <summary>
  30.541 +		/// Write a TarBuffer record to the archive.
  30.542 +		/// </summary>
  30.543 +		void WriteRecord()
  30.544 +		{
  30.545 +			if (outputStream == null) {
  30.546 +				throw new TarException("TarBuffer.WriteRecord no output stream defined");
  30.547 +			}
  30.548 +			
  30.549 +			outputStream.Write(recordBuffer, 0, RecordSize);
  30.550 +			outputStream.Flush();
  30.551 +			
  30.552 +			currentBlockIndex = 0;
  30.553 +			currentRecordIndex++;
  30.554 +		}
  30.555 +		
  30.556 +		/// <summary>
  30.557 +		/// WriteFinalRecord writes the current record buffer to output any unwritten data is present.
  30.558 +		/// </summary>
  30.559 +        /// <remarks>Any trailing bytes are set to zero which is by definition correct behaviour
  30.560 +        /// for the end of a tar stream.</remarks>
  30.561 +		void WriteFinalRecord()
  30.562 +		{
  30.563 +			if (outputStream == null) {
  30.564 +				throw new TarException("TarBuffer.WriteFinalRecord no output stream defined");
  30.565 +			}
  30.566 +			
  30.567 +			if (currentBlockIndex > 0) {
  30.568 +				int dataBytes = currentBlockIndex * BlockSize;
  30.569 +				Array.Clear(recordBuffer, dataBytes, RecordSize - dataBytes);
  30.570 +				WriteRecord();
  30.571 +			}
  30.572 +
  30.573 +			outputStream.Flush();
  30.574 +		}
  30.575 +		
  30.576 +		/// <summary>
  30.577 +		/// Close the TarBuffer. If this is an output buffer, also flush the
  30.578 +		/// current block before closing.
  30.579 +		/// </summary>
  30.580 +		public void Close()
  30.581 +		{
  30.582 +			if (outputStream != null) {
  30.583 +				WriteFinalRecord();
  30.584 +
  30.585 +                if (isStreamOwner_) {
  30.586 +                    outputStream.Close();
  30.587 +                }
  30.588 +				outputStream = null;
  30.589 +			}
  30.590 +			else if (inputStream != null) {
  30.591 +                if (isStreamOwner_) {