-// AssemblyInfo.cs
-// Copyright (C) 2001 Mike Krueger
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-//
-// Linking this library statically or dynamically with other modules is
-// making a combined work based on this library. Thus, the terms and
-// conditions of the GNU General Public License cover the whole
-// combination.
-//
-// As a special exception, the copyright holders of this library give you
-// permission to link this library with independent modules to produce an
-// executable, regardless of the license terms of these independent
-// modules, and to copy and distribute the resulting executable under
-// terms of your choice, provided that you also meet, for each linked
-// independent module, the terms and conditions of the license of that
-// module. An independent module is a module which is not derived from
-// or based on this library. If you modify this library, you may extend
-// this exception to your version of the library, but you are not
-// obligated to do so. If you do not wish to do so, delete this
-// exception statement from your version.
-
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-[assembly: AssemblyTitle("SharpZipLibrary")]
-[assembly: AssemblyDescription("free C# zlib implementation")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("#ZipLibrary")]
-[assembly: AssemblyCopyright("(c) Mike Krueger 2001-2002")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-#if NET_2_0
-[assembly: AssemblyVersion("0.31.2.0")]
-#else
-[assembly: AssemblyVersion("0.31.0.0")]
-#endif
-
-[assembly: AssemblyDelaySign(false)]
-[assembly: AssemblyKeyFile("SharpZipLib.key")]
+// AssemblyInfo.cs\r
+// Copyright (C) 2001 Mike Krueger\r
+//\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+//\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+// GNU General Public License for more details.\r
+//\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software\r
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
+//\r
+// Linking this library statically or dynamically with other modules is\r
+// making a combined work based on this library. Thus, the terms and\r
+// conditions of the GNU General Public License cover the whole\r
+// combination.\r
+// \r
+// As a special exception, the copyright holders of this library give you\r
+// permission to link this library with independent modules to produce an\r
+// executable, regardless of the license terms of these independent\r
+// modules, and to copy and distribute the resulting executable under\r
+// terms of your choice, provided that you also meet, for each linked\r
+// independent module, the terms and conditions of the license of that\r
+// module. An independent module is a module which is not derived from\r
+// or based on this library. If you modify this library, you may extend\r
+// this exception to your version of the library, but you are not\r
+// obligated to do so. If you do not wish to do so, delete this\r
+// exception statement from your version.\r
+\r
+using System;\r
+using System.Reflection;\r
+using System.Runtime.CompilerServices;\r
+\r
+[assembly: CLSCompliant(true)]\r
+\r
+[assembly: AssemblyTitle("ICSharpCode.SharpZipLibrary")]\r
+[assembly: AssemblyDescription("free C# zlib implementation")]\r
+[assembly: AssemblyConfiguration("")]\r
+[assembly: AssemblyCompany("")]\r
+[assembly: AssemblyProduct("#ZipLibrary")]\r
+[assembly: AssemblyCopyright("(c) Mike Krueger 2001-2004")]\r
+[assembly: AssemblyTrademark("")]\r
+[assembly: AssemblyCulture("")]\r
+\r
+[assembly: AssemblyVersion("0.6.0.0")]\r
+\r
+[assembly: AssemblyDelaySign(false)]\r
+[assembly: AssemblyKeyFile("../ICSharpCode.SharpZipLib.key")]\r
using System;\r
using System.IO;\r
\r
-namespace ICSharpCode.SharpZipLib.BZip2 {\r
+namespace ICSharpCode.SharpZipLib.BZip2 \r
+{\r
\r
/// <summary>\r
/// Does all the compress and decompress pre-operation stuff.\r
{\r
public static void Decompress(Stream instream, Stream outstream) \r
{\r
- BufferedStream bos = new BufferedStream(outstream);\r
- BufferedStream bis = new BufferedStream(instream);\r
- int b = bis.ReadByte();\r
- if (b != 'B') {\r
- return;\r
- }\r
- b = bis.ReadByte();\r
- if (b != 'Z') {\r
- return;\r
- }\r
+ System.IO.Stream bos = outstream;\r
+ System.IO.Stream bis = instream;\r
BZip2InputStream bzis = new BZip2InputStream(bis);\r
int ch = bzis.ReadByte();\r
while (ch != -1) {\r
}\r
\r
public static void Compress(Stream instream, Stream outstream, int blockSize) \r
- {\r
- BufferedStream bos = new BufferedStream(outstream);\r
- bos.WriteByte((byte)'B');\r
- bos.WriteByte((byte)'Z');\r
- BufferedStream bis = new BufferedStream(instream);\r
+ { \r
+ System.IO.Stream bos = outstream;\r
+ System.IO.Stream bis = instream;\r
int ch = bis.ReadByte();\r
- BZip2OutputStream bzos = new BZip2OutputStream(bos);\r
+ BZip2OutputStream bzos = new BZip2OutputStream(bos, blockSize);\r
while(ch != -1) {\r
bzos.WriteByte((byte)ch);\r
ch = bis.ReadByte();\r
// obligated to do so. If you do not wish to do so, delete this\r
// exception statement from your version.\r
\r
-namespace ICSharpCode.SharpZipLib.BZip2 {\r
+namespace ICSharpCode.SharpZipLib.BZip2 \r
+{\r
\r
/// <summary>\r
/// Base class for both the compress and decompress classes.\r
public sealed class BZip2Constants\r
{\r
public readonly static int[] rNums = {\r
- 619, 720, 127, 481, 931, 816, 813, 233, 566, 247,\r
- 985, 724, 205, 454, 863, 491, 741, 242, 949, 214,\r
- 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,\r
- 419, 436, 278, 496, 867, 210, 399, 680, 480, 51,\r
- 878, 465, 811, 169, 869, 675, 611, 697, 867, 561,\r
- 862, 687, 507, 283, 482, 129, 807, 591, 733, 623,\r
- 150, 238, 59, 379, 684, 877, 625, 169, 643, 105,\r
- 170, 607, 520, 932, 727, 476, 693, 425, 174, 647,\r
- 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,\r
- 909, 545, 703, 919, 874, 474, 882, 500, 594, 612,\r
- 641, 801, 220, 162, 819, 984, 589, 513, 495, 799,\r
- 161, 604, 958, 533, 221, 400, 386, 867, 600, 782,\r
- 382, 596, 414, 171, 516, 375, 682, 485, 911, 276,\r
- 98, 553, 163, 354, 666, 933, 424, 341, 533, 870,\r
- 227, 730, 475, 186, 263, 647, 537, 686, 600, 224,\r
- 469, 68, 770, 919, 190, 373, 294, 822, 808, 206,\r
- 184, 943, 795, 384, 383, 461, 404, 758, 839, 887,\r
- 715, 67, 618, 276, 204, 918, 873, 777, 604, 560,\r
- 951, 160, 578, 722, 79, 804, 96, 409, 713, 940,\r
- 652, 934, 970, 447, 318, 353, 859, 672, 112, 785,\r
- 645, 863, 803, 350, 139, 93, 354, 99, 820, 908,\r
- 609, 772, 154, 274, 580, 184, 79, 626, 630, 742,\r
- 653, 282, 762, 623, 680, 81, 927, 626, 789, 125,\r
- 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,\r
- 170, 774, 972, 275, 999, 639, 495, 78, 352, 126,\r
- 857, 956, 358, 619, 580, 124, 737, 594, 701, 612,\r
- 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,\r
- 944, 375, 748, 52, 600, 747, 642, 182, 862, 81,\r
- 344, 805, 988, 739, 511, 655, 814, 334, 249, 515,\r
- 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,\r
- 433, 837, 553, 268, 926, 240, 102, 654, 459, 51,\r
- 686, 754, 806, 760, 493, 403, 415, 394, 687, 700,\r
- 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,\r
- 978, 321, 576, 617, 626, 502, 894, 679, 243, 440,\r
- 680, 879, 194, 572, 640, 724, 926, 56, 204, 700,\r
- 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,\r
- 297, 59, 87, 824, 713, 663, 412, 693, 342, 606,\r
- 134, 108, 571, 364, 631, 212, 174, 643, 304, 329,\r
- 343, 97, 430, 751, 497, 314, 983, 374, 822, 928,\r
- 140, 206, 73, 263, 980, 736, 876, 478, 430, 305,\r
- 170, 514, 364, 692, 829, 82, 855, 953, 676, 246,\r
- 369, 970, 294, 750, 807, 827, 150, 790, 288, 923,\r
- 804, 378, 215, 828, 592, 281, 565, 555, 710, 82,\r
- 896, 831, 547, 261, 524, 462, 293, 465, 502, 56,\r
- 661, 821, 976, 991, 658, 869, 905, 758, 745, 193,\r
- 768, 550, 608, 933, 378, 286, 215, 979, 792, 961,\r
- 61, 688, 793, 644, 986, 403, 106, 366, 905, 644,\r
- 372, 567, 466, 434, 645, 210, 389, 550, 919, 135,\r
- 780, 773, 635, 389, 707, 100, 626, 958, 165, 504,\r
- 920, 176, 193, 713, 857, 265, 203, 50, 668, 108,\r
- 645, 990, 626, 197, 510, 357, 358, 850, 858, 364,\r
- 936, 638\r
- };\r
+ 619, 720, 127, 481, 931, 816, 813, 233, 566, 247,\r
+ 985, 724, 205, 454, 863, 491, 741, 242, 949, 214,\r
+ 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,\r
+ 419, 436, 278, 496, 867, 210, 399, 680, 480, 51,\r
+ 878, 465, 811, 169, 869, 675, 611, 697, 867, 561,\r
+ 862, 687, 507, 283, 482, 129, 807, 591, 733, 623,\r
+ 150, 238, 59, 379, 684, 877, 625, 169, 643, 105,\r
+ 170, 607, 520, 932, 727, 476, 693, 425, 174, 647,\r
+ 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,\r
+ 909, 545, 703, 919, 874, 474, 882, 500, 594, 612,\r
+ 641, 801, 220, 162, 819, 984, 589, 513, 495, 799,\r
+ 161, 604, 958, 533, 221, 400, 386, 867, 600, 782,\r
+ 382, 596, 414, 171, 516, 375, 682, 485, 911, 276,\r
+ 98, 553, 163, 354, 666, 933, 424, 341, 533, 870,\r
+ 227, 730, 475, 186, 263, 647, 537, 686, 600, 224,\r
+ 469, 68, 770, 919, 190, 373, 294, 822, 808, 206,\r
+ 184, 943, 795, 384, 383, 461, 404, 758, 839, 887,\r
+ 715, 67, 618, 276, 204, 918, 873, 777, 604, 560,\r
+ 951, 160, 578, 722, 79, 804, 96, 409, 713, 940,\r
+ 652, 934, 970, 447, 318, 353, 859, 672, 112, 785,\r
+ 645, 863, 803, 350, 139, 93, 354, 99, 820, 908,\r
+ 609, 772, 154, 274, 580, 184, 79, 626, 630, 742,\r
+ 653, 282, 762, 623, 680, 81, 927, 626, 789, 125,\r
+ 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,\r
+ 170, 774, 972, 275, 999, 639, 495, 78, 352, 126,\r
+ 857, 956, 358, 619, 580, 124, 737, 594, 701, 612,\r
+ 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,\r
+ 944, 375, 748, 52, 600, 747, 642, 182, 862, 81,\r
+ 344, 805, 988, 739, 511, 655, 814, 334, 249, 515,\r
+ 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,\r
+ 433, 837, 553, 268, 926, 240, 102, 654, 459, 51,\r
+ 686, 754, 806, 760, 493, 403, 415, 394, 687, 700,\r
+ 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,\r
+ 978, 321, 576, 617, 626, 502, 894, 679, 243, 440,\r
+ 680, 879, 194, 572, 640, 724, 926, 56, 204, 700,\r
+ 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,\r
+ 297, 59, 87, 824, 713, 663, 412, 693, 342, 606,\r
+ 134, 108, 571, 364, 631, 212, 174, 643, 304, 329,\r
+ 343, 97, 430, 751, 497, 314, 983, 374, 822, 928,\r
+ 140, 206, 73, 263, 980, 736, 876, 478, 430, 305,\r
+ 170, 514, 364, 692, 829, 82, 855, 953, 676, 246,\r
+ 369, 970, 294, 750, 807, 827, 150, 790, 288, 923,\r
+ 804, 378, 215, 828, 592, 281, 565, 555, 710, 82,\r
+ 896, 831, 547, 261, 524, 462, 293, 465, 502, 56,\r
+ 661, 821, 976, 991, 658, 869, 905, 758, 745, 193,\r
+ 768, 550, 608, 933, 378, 286, 215, 979, 792, 961,\r
+ 61, 688, 793, 644, 986, 403, 106, 366, 905, 644,\r
+ 372, 567, 466, 434, 645, 210, 389, 550, 919, 135,\r
+ 780, 773, 635, 389, 707, 100, 626, 958, 165, 504,\r
+ 920, 176, 193, 713, 857, 265, 203, 50, 668, 108,\r
+ 645, 990, 626, 197, 510, 357, 358, 850, 858, 364,\r
+ 936, 638\r
+ };\r
\r
public readonly static int baseBlockSize = 100000;\r
\r
\r
using ICSharpCode.SharpZipLib.Checksums;\r
\r
-namespace ICSharpCode.SharpZipLib.BZip2 {\r
+namespace ICSharpCode.SharpZipLib.BZip2 \r
+{\r
\r
/// <summary>\r
/// An input stream that decompresses from the BZip2 format (without the file\r
\r
static void Cadvise()\r
{\r
- Console.WriteLine("CRC Error");\r
+ //Console.WriteLine("CRC Error");\r
//throw new CCoruptionError();\r
}\r
\r
static void BadBGLengths() \r
{\r
- Console.WriteLine("bad BG lengths");\r
+ //Console.WriteLine("bad BG lengths");\r
}\r
\r
- static void bitStreamEOF() \r
+ static void BitStreamEOF() \r
{\r
- Console.WriteLine("bit stream eof");\r
+ //Console.WriteLine("bit stream eof");\r
}\r
\r
static void CompressedStreamEOF() \r
{\r
- Console.WriteLine("compressed stream eof");\r
+ //Console.WriteLine("compressed stream eof");\r
}\r
\r
void MakeMaps() \r
\r
bool blockRandomised;\r
\r
-// private int bytesIn;\r
-// private int bytesOut;\r
+ // private int bytesIn;\r
+ // private int bytesOut;\r
int bsBuff;\r
int bsLive;\r
IChecksum mCrc = new StrangeCRC();\r
public override int ReadByte()\r
{\r
if (streamEnd) {\r
- return -1;\r
+ return -1; // ok\r
}\r
\r
int retChar = currentChar;\r
\r
void Initialize() \r
{\r
+ // -jr- 18-Nov-2003 magic1 and 2 added here so stream is fully capable on its own\r
+ char magic1 = BsGetUChar();\r
+ char magic2 = BsGetUChar();\r
+ \r
char magic3 = BsGetUChar();\r
char magic4 = BsGetUChar();\r
\r
- if (magic3 != 'h' || magic4 < '1' || magic4 > '9') {\r
+ if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') {\r
streamEnd = true;\r
return;\r
}\r
CrcError();\r
}\r
\r
- // 1528150659\r
+ // 1528150659\r
computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31);\r
computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC;\r
}\r
\r
static void BlockOverrun() \r
{\r
- Console.WriteLine("Block overrun");\r
+ //Console.WriteLine("Block overrun");\r
}\r
\r
static void BadBlockHeader() \r
{\r
- Console.WriteLine("Bad block header");\r
+ //Console.WriteLine("Bad block header");\r
}\r
\r
static void CrcError() \r
{\r
- Console.WriteLine("crc error");\r
+ //Console.WriteLine("crc error");\r
}\r
\r
\r
for (int j = 0; j < 16; j++) {\r
inUse[i * 16 + j] = (BsR(1) == 1);\r
}\r
+ } else {\r
+ for (int j = 0; j < 16; j++) {\r
+ inUse[i * 16 + j] = false;\r
+ }\r
}\r
}\r
\r
int zj;\r
\r
while (zvec > limit[zt][zn]) {\r
+ if (zn > 20) { // the longest code\r
+ throw new ApplicationException("Bzip data error"); // -jr- 17-Dec-2003 from bzip 1.02 why 20???\r
+ }\r
zn++;\r
while (bsLive < 1) {\r
FillBuffer();\r
bsLive--;\r
zvec = (zvec << 1) | zj;\r
}\r
+ if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MAX_ALPHA_SIZE) {\r
+ throw new ApplicationException("Bzip data error"); // -jr- 17-Dec-2003 from bzip 1.02\r
+ }\r
nextSym = perm[zt][zvec - baseArray[zt][zn]];\r
\r
while (true) {\r
- \r
if (nextSym == EOB) {\r
break;\r
}\r
int n = 1;\r
do {\r
if (nextSym == BZip2Constants.RUNA) {\r
- s += (0+1) * n;\r
+ s += (0 + 1) * n;\r
} else if (nextSym == BZip2Constants.RUNB) {\r
- s += (1+1) * n;\r
+ s += (1 + 1) * n;\r
}\r
\r
n <<= 1;\r
\r
void SetupRandPartA() \r
{\r
- if(i2 <= last) {\r
+ if (i2 <= last) {\r
chPrev = ch2;\r
ch2 = ll8[tPos];\r
tPos = tt[tPos];\r
\r
void SetDecompressStructureSizes(int newSize100k) \r
{\r
- if (!(0 <= newSize100k && newSize100k <= 9 && \r
- 0 <= blockSize100k && blockSize100k <= 9)) {\r
+ if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) {\r
throw new ApplicationException("Invalid block size");\r
}\r
- \r
+ \r
blockSize100k = newSize100k;\r
\r
if (newSize100k == 0) {\r
\r
using ICSharpCode.SharpZipLib.Checksums;\r
\r
-namespace ICSharpCode.SharpZipLib.BZip2 {\r
+namespace ICSharpCode.SharpZipLib.BZip2 \r
+{\r
\r
/// <summary>\r
/// An output stream that compresses into the BZip2 format (without the file\r
\r
static void Panic() \r
{\r
- Console.WriteLine("panic");\r
+ //Console.WriteLine("panic");\r
}\r
\r
void MakeMaps() \r
break;\r
}\r
if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) {\r
- yy++;\r
+ yy++;\r
}\r
if (weight[tmp] < weight[heap[yy]]) {\r
break;\r
tmp = heap[zz];\r
while (true) {\r
yy = zz << 1;\r
- if (yy > nHeap)\r
+ if (yy > nHeap) {\r
break;\r
- if (yy < nHeap &&\r
- weight[heap[yy+1]] < weight[heap[yy]])\r
- yy++;\r
- if (weight[tmp] < weight[heap[yy]])\r
+ }\r
+ if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) {\r
+ yy++;\r
+ }\r
+ if (weight[tmp] < weight[heap[yy]]) {\r
break;\r
+ }\r
heap[zz] = heap[yy];\r
zz = yy;\r
}\r
nNodes++;\r
parent[n1] = parent[n2] = nNodes;\r
\r
- weight[nNodes] = (int)((weight[n1] & 0xffffff00) + (weight[n2] & 0xffffff00)) |\r
+ weight[nNodes] = (int)((weight[n1] & 0xffffff00) + (weight[n2] & 0xffffff00)) | \r
(int)(1 + (((weight[n1] & 0x000000ff) > (weight[n2] & 0x000000ff)) ? (weight[n1] & 0x000000ff) : (weight[n2] & 0x000000ff)));\r
\r
parent[nNodes] = -1;\r
\r
bool blockRandomised;\r
\r
-// int bytesIn;\r
+ // int bytesIn;\r
int bytesOut;\r
int bsBuff;\r
int bsLive;\r
EndBlock();\r
EndCompression();\r
closed = true;\r
-// super.close();\r
+ // super.close();\r
Flush();\r
baseStream.Close();\r
}\r
\r
public override void Flush()\r
{\r
-// super.flush();\r
+ // super.flush();\r
baseStream.Flush();\r
}\r
\r
\r
void Initialize()\r
{\r
-// bytesIn = 0;\r
+ // bytesIn = 0;\r
bytesOut = 0;\r
nBlocksRandomised = 0;\r
\r
/*--- Write `magic' bytes h indicating file-format == huffmanised,\r
followed by a digit indicating blockSize100k.\r
---*/\r
+ BsPutUChar('B'); // -jr- 18-Nov-2003 added to match BZ2 1.02 header already in BZip class but that sux a lot\r
+ BsPutUChar('Z');\r
+ \r
BsPutUChar('h');\r
BsPutUChar('0' + blockSize100k);\r
\r
\r
void EndBlock()\r
{\r
+ if (last < 0) { //-jr- dont do anything for empty files, (makes empty files compatible with original Bzip)\r
+ return;\r
+ }\r
+ \r
blockCRC = (uint)mCrc.Value;\r
combinedCRC = (combinedCRC << 1) | (combinedCRC >> 31);\r
combinedCRC ^= blockCRC;\r
\r
void BsFinishedWithStream()\r
{\r
- while (bsLive > 0) {\r
+ while (bsLive > 0) \r
+ {\r
int ch = (bsBuff >> 24);\r
baseStream.WriteByte((byte)ch); // write 8-bit\r
bsBuff <<= 8;\r
totc = 0;\r
gs = 0;\r
while (true) {\r
- \r
/*--- Set group start & end marks. --*/\r
if (gs >= nMTF) {\r
break;\r
Panic();\r
}\r
\r
- \r
/*--- Compute MTF values for the selectors. ---*/\r
char[] pos = new char[BZip2Constants.N_GROUPS];\r
char ll_i, tmp2, tmp;\r
i++;\r
\r
/*-- copy 2 --*/\r
- if (i > hi)\r
+ if (i > hi) {\r
break;\r
+ }\r
v = zptr[i];\r
j = i;\r
while (FullGtU ( zptr[j-h]+d, v+d )) {\r
zptr[j] = zptr[j-h];\r
j = j - h;\r
- if (j <= (lo + h - 1))\r
+ if (j <= (lo + h - 1)) {\r
break;\r
+ }\r
}\r
zptr[j] = v;\r
i++;\r
\r
/*-- copy 3 --*/\r
- if (i > hi)\r
+ if (i > hi) {\r
break;\r
+ }\r
v = zptr[i];\r
j = i;\r
while (FullGtU ( zptr[j-h]+d, v+d)) {\r
zptr[j] = zptr[j-h];\r
j = j - h;\r
- if (j <= (lo + h - 1))\r
+ if (j <= (lo + h - 1)) {\r
break;\r
+ }\r
}\r
zptr[j] = v;\r
i++;\r
\r
- if (workDone > workLimit && firstAttempt)\r
+ if (workDone > workLimit && firstAttempt) {\r
return;\r
+ }\r
}\r
}\r
}\r
int unLo, unHi, ltLo, gtHi, med, n, m;\r
int sp, lo, hi, d;\r
StackElem[] stack = new StackElem[QSORT_STACK_SIZE];\r
- for(int count = 0; count < QSORT_STACK_SIZE; count++)\r
+ for (int count = 0; count < QSORT_STACK_SIZE; count++) {\r
stack[count] = new StackElem();\r
+ }\r
\r
sp = 0;\r
\r
\r
if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) {\r
SimpleSort(lo, hi, d);\r
- if (workDone > workLimit && firstAttempt)\r
+ if (workDone > workLimit && firstAttempt) {\r
return;\r
+ }\r
continue;\r
}\r
\r
unLo++;\r
}\r
while (true) {\r
- if (unLo > unHi)\r
+ if (unLo > unHi) {\r
break;\r
+ }\r
n = ((int)block[zptr[unHi]+d + 1]) - med;\r
if (n == 0) {\r
int temp = 0;\r
gtHi--;\r
unHi--;\r
continue;\r
- };\r
- if (n < 0)\r
+ }\r
+ if (n < 0) {\r
break;\r
+ }\r
unHi--;\r
}\r
- if (unLo > unHi)\r
+ if (unLo > unHi) {\r
break;\r
+ }\r
{\r
- int temp = zptr[unLo];\r
- zptr[unLo] = zptr[unHi];\r
- zptr[unHi] = temp;\r
- unLo++;\r
- unHi--;\r
+ int temp = zptr[unLo];\r
+ zptr[unLo] = zptr[unHi];\r
+ zptr[unHi] = temp;\r
+ unLo++;\r
+ unHi--;\r
}\r
}\r
\r
Use simpleSort(), since the full sorting mechanism\r
has quite a large constant overhead.\r
--*/\r
- for (i = 0; i <= last; i++)\r
+ for (i = 0; i <= last; i++) {\r
zptr[i] = i;\r
+ }\r
firstAttempt = false;\r
workDone = workLimit = 0;\r
SimpleSort(0, last, 0);\r
} else {\r
numQSorted = 0;\r
- for (i = 0; i <= 255; i++)\r
+ for (i = 0; i <= 255; i++) {\r
bigDone[i] = false;\r
- \r
- for (i = 0; i <= 65536; i++)\r
+ }\r
+ for (i = 0; i <= 65536; i++) {\r
ftab[i] = 0;\r
+ }\r
\r
c1 = block[0];\r
for (i = 0; i <= last; i++) {\r
c1 = c2;\r
}\r
\r
- for (i = 1; i <= 65536; i++)\r
+ for (i = 1; i <= 65536; i++) {\r
ftab[i] += ftab[i - 1];\r
+ }\r
\r
c1 = block[1];\r
for (i = 0; i < last; i++) {\r
while ((ftab[((runningOrder[j-h])+1) << 8] - ftab[(runningOrder[j-h]) << 8]) > (ftab[((vv)+1) << 8] - ftab[(vv) << 8])) {\r
runningOrder[j] = runningOrder[j-h];\r
j = j - h;\r
- if (j <= (h - 1))\r
+ if (j <= (h - 1)) {\r
break;\r
+ }\r
}\r
runningOrder[j] = vv;\r
}\r
--*/\r
for (j = 0; j <= 255; j++) {\r
sb = (ss << 8) + j;\r
- if(!((ftab[sb] & SETMASK) == SETMASK) ) {\r
+ if(!((ftab[sb] & SETMASK) == SETMASK)) {\r
int lo = ftab[sb] & CLEARMASK;\r
int hi = (ftab[sb+1] & CLEARMASK) - 1;\r
if (hi > lo) {\r
int i;\r
int rNToGo = 0;\r
int rTPos = 0;\r
- for (i = 0; i < 256; i++)\r
+ for (i = 0; i < 256; i++) {\r
inUse[i] = false;\r
+ }\r
\r
for (i = 0; i <= last; i++) {\r
if (rNToGo == 0) {\r
rNToGo = (int)BZip2Constants.rNums[rTPos];\r
rTPos++;\r
- if(rTPos == 512)\r
+ if (rTPos == 512) {\r
rTPos = 0;\r
+ }\r
}\r
rNToGo--;\r
block[i + 1] ^= (byte)((rNToGo == 1) ? 1 : 0);\r
\r
c1 = block[i1 + 1];\r
c2 = block[i2 + 1];\r
- if (c1 != c2)\r
+ if (c1 != c2) {\r
return c1 > c2;\r
+ }\r
i1++;\r
i2++;\r
\r
because the number of elems to sort is\r
usually small, typically <= 20.\r
--*/\r
- readonly int[] incs = new int[] { 1, 4, 13, 40, 121, 364, 1093, 3280,\r
- 9841, 29524, 88573, 265720,\r
- 797161, 2391484 };\r
+ readonly int[] incs = new int[] { \r
+ 1, 4, 13, 40, 121, 364, 1093, 3280,\r
+ 9841, 29524, 88573, 265720,\r
+ 797161, 2391484 \r
+ };\r
\r
void AllocateCompressStructures() \r
{\r
\r
j = 0;\r
tmp = yy[j];\r
- while ( ll_i != tmp ) {\r
+ while (ll_i != tmp) {\r
j++;\r
tmp2 = tmp;\r
tmp = yy[j];\r
wr++;\r
mtfFreq[BZip2Constants.RUNB]++;\r
break;\r
- };\r
- if (zPend < 2)\r
+ }\r
+ if (zPend < 2) {\r
break;\r
+ }\r
zPend = (zPend - 2) / 2;\r
- };\r
+ }\r
zPend = 0;\r
}\r
szptr[wr] = (short)(j + 1);\r
mtfFreq[BZip2Constants.RUNB]++;\r
break;\r
}\r
- if (zPend < 2)\r
+ if (zPend < 2) {\r
break;\r
+ }\r
zPend = (zPend - 2) / 2;\r
}\r
}\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Checksums {\r
+namespace ICSharpCode.SharpZipLib.Checksums \r
+{\r
\r
/// <summary>\r
/// Computes Adler32 checksum for a stream of data. An Adler32\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Checksums {\r
+namespace ICSharpCode.SharpZipLib.Checksums \r
+{\r
\r
/// <summary>\r
/// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:\r
0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6,\r
0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,\r
0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,\r
- 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, \r
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344,\r
0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,\r
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A,\r
0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,\r
0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,\r
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,\r
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8,\r
- 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, \r
+ 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,\r
0x2D02EF8D\r
};\r
\r
+ internal static uint ComputeCrc32(uint oldCrc, byte bval)\r
+ {\r
+ return (uint)(Crc32.CrcTable[(oldCrc ^ bval) & 0xFF] ^ (oldCrc >> 8));\r
+ }\r
+ \r
/// <summary>\r
/// The crc data checksum so far.\r
/// </summary>\r
get {\r
return (long)crc;\r
}\r
+ set {\r
+ crc = (uint)value;\r
+ }\r
}\r
\r
/// <summary>\r
// obligated to do so. If you do not wish to do so, delete this\r
// exception statement from your version.\r
\r
-namespace ICSharpCode.SharpZipLib.Checksums {\r
+namespace ICSharpCode.SharpZipLib.Checksums \r
+{\r
\r
/// <summary>\r
/// Interface to compute a data checksum used by checked input/output streams.\r
/// <summary>\r
/// Returns the data checksum computed so far.\r
/// </summary>\r
- long Value {\r
+ long Value \r
+ {\r
get;\r
}\r
\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Checksums {\r
+namespace ICSharpCode.SharpZipLib.Checksums \r
+{\r
\r
public class StrangeCRC : IChecksum\r
{\r
readonly static uint[] crc32Table = {\r
- 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,\r
- 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,\r
- 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,\r
- 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,\r
- 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,\r
- 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,\r
- 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,\r
- 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,\r
- 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,\r
- 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,\r
- 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,\r
- 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,\r
- 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,\r
- 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,\r
- 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,\r
- 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,\r
- 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,\r
- 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,\r
- 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,\r
- 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,\r
- 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,\r
- 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,\r
- 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,\r
- 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,\r
- 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,\r
- 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,\r
- 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,\r
- 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,\r
- 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,\r
- 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,\r
- 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,\r
- 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,\r
- 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,\r
- 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,\r
- 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,\r
- 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,\r
- 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,\r
- 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,\r
- 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,\r
- 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,\r
- 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,\r
- 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,\r
- 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,\r
- 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,\r
- 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,\r
- 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,\r
- 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,\r
- 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,\r
- 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,\r
- 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,\r
- 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,\r
- 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,\r
- 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,\r
- 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,\r
- 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,\r
- 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,\r
- 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,\r
- 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,\r
- 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,\r
- 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,\r
- 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,\r
- 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,\r
- 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,\r
- 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4\r
- };\r
+ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,\r
+ 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,\r
+ 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,\r
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,\r
+ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,\r
+ 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,\r
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,\r
+ 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,\r
+ 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,\r
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,\r
+ 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,\r
+ 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,\r
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,\r
+ 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,\r
+ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,\r
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,\r
+ 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,\r
+ 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,\r
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,\r
+ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,\r
+ 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,\r
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,\r
+ 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,\r
+ 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,\r
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,\r
+ 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,\r
+ 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,\r
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,\r
+ 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,\r
+ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,\r
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,\r
+ 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,\r
+ 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,\r
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,\r
+ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,\r
+ 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,\r
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,\r
+ 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,\r
+ 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,\r
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,\r
+ 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,\r
+ 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,\r
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,\r
+ 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,\r
+ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,\r
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,\r
+ 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,\r
+ 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,\r
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,\r
+ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,\r
+ 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,\r
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,\r
+ 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,\r
+ 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,\r
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,\r
+ 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,\r
+ 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,\r
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,\r
+ 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,\r
+ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,\r
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,\r
+ 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,\r
+ 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,\r
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4\r
+ };\r
int globalCrc;\r
\r
public StrangeCRC() \r
// obligated to do so. If you do not wish to do so, delete this\r
// exception statement from your version.\r
\r
-namespace ICSharpCode.SharpZipLib.GZip {\r
+namespace ICSharpCode.SharpZipLib.GZip \r
+{\r
\r
/// <summary>\r
/// This class contains constants used for gzip.\r
using ICSharpCode.SharpZipLib.Zip.Compression;\r
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;\r
\r
-namespace ICSharpCode.SharpZipLib.GZip {\r
+namespace ICSharpCode.SharpZipLib.GZip \r
+{\r
\r
/// <summary>\r
/// This filter stream is used to decompress a "GZIP" format stream.\r
/// </example>\r
public class GZipInputStream : InflaterInputStream \r
{\r
- \r
- //Variables\r
- \r
/// <summary>\r
/// CRC-32 value for uncompressed data\r
/// </summary>\r
/// </summary>\r
protected bool eos;\r
\r
+ // Have we read the GZIP header yet?\r
+ bool readGZIPHeader;\r
+ \r
/// <summary>\r
/// Creates a GzipInputStream with the default buffer size\r
/// </summary>\r
Crc32 headCRC = new Crc32();\r
int magic = baseInputStream.ReadByte();\r
if (magic < 0) {\r
- eos = true;\r
- return;\r
+ eos = true;\r
+ return;\r
}\r
headCRC.Update(magic);\r
if (magic != (GZipConstants.GZIP_MAGIC >> 8)) {\r
extraLen = (len1 << 8) | len2;\r
for (int i = 0; i < extraLen;i++) {\r
int readByte = baseInputStream.ReadByte();\r
- if (readByte < 0) {\r
+ if (readByte < 0) \r
+ {\r
throw new Exception("Early EOF baseInputStream GZIP header");\r
}\r
headCRC.Update(readByte);\r
*/\r
eos = true;\r
}\r
- \r
- /* Have we read the GZIP header yet? */\r
- private bool readGZIPHeader;\r
}\r
}\r
using ICSharpCode.SharpZipLib.Zip.Compression;\r
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;\r
\r
-namespace ICSharpCode.SharpZipLib.GZip {\r
+namespace ICSharpCode.SharpZipLib.GZip \r
+{\r
\r
/// <summary>\r
/// This filter stream is used to compress a stream into a "GZIP" stream.\r
/// using System;\r
/// using System.IO;\r
/// \r
- /// using NZlib.GZip;\r
+ /// using ICSharpCode.SharpZipLib.GZip; // -jr- corrected\r
/// \r
/// class MainClass\r
/// {\r
/// </param>\r
public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size)\r
{\r
- // TODO : find out correctness, orgininally this was : (int) (System.currentTimeMillis() / 1000L);\r
+ WriteHeader();\r
+ // System.err.println("wrote GZIP header (" + gzipHeader.length + " bytes )");\r
+ }\r
+ \r
+ void WriteHeader()\r
+ {\r
int mod_time = (int)(DateTime.Now.Ticks / 10000L); // Ticks give back 100ns intervals\r
byte[] gzipHeader = {\r
/* The two magic bytes */\r
/* The OS type (unknown) */\r
(byte) 255\r
};\r
- \r
baseOutputStream.Write(gzipHeader, 0, gzipHeader.Length);\r
- // System.err.println("wrote GZIP header (" + gzipHeader.length + " bytes )");\r
}\r
\r
public override void Write(byte[] buf, int off, int len)\r
(byte) totalin, (byte) (totalin >> 8),\r
(byte) (totalin >> 16), (byte) (totalin >> 24)\r
};\r
- \r
+\r
baseOutputStream.Write(gzipFooter, 0, gzipFooter.Length);\r
// System.err.println("wrote GZIP trailer (" + gzipFooter.length + " bytes )");\r
}\r
-// BZip2OutputStream.cs\r
+// InvalidHeaderException.cs\r
// Copyright (C) 2001 Mike Krueger\r
//\r
// This program is free software; you can redistribute it and/or\r
\r
namespace ICSharpCode.SharpZipLib.Tar {\r
\r
- public delegate void ProgressMessageHandler(TarArchive archive, string message);\r
+ public delegate void ProgressMessageHandler(TarArchive archive, TarEntry entry, string message);\r
\r
/// <summary>\r
/// The TarArchive class implements the concept of a\r
/// tar archive. A tar archive is a series of entries, each of\r
/// which represents a file system object. Each entry in\r
- /// the archive consists of a header record. Directory entries\r
- /// consist only of the header record, and are followed by entries\r
+ /// the archive consists of a header block. Directory entries\r
+ /// consist only of the header block, and are followed by entries\r
/// for the directory's contents. File entries consist of a\r
- /// header record followed by the number of records needed to\r
+ /// header followed by the number of blocks needed to\r
/// contain the file's contents. All entries are written on\r
- /// record boundaries. Records are 512 bytes long.\r
+ /// block boundaries. Blocks are 512 bytes long.\r
/// \r
/// TarArchives are instantiated in either read or write mode,\r
/// based upon whether they are instantiated with an InputStream\r
/// </summary>\r
public class TarArchive\r
{\r
- protected bool verbose;\r
- protected bool debug;\r
- protected bool keepOldFiles;\r
- protected bool asciiTranslate;\r
+ bool verbose;\r
+ bool debug;\r
+ bool keepOldFiles;\r
+ bool asciiTranslate;\r
\r
- protected int userId;\r
- protected string userName;\r
- protected int groupId;\r
- protected string groupName;\r
+ int userId;\r
+ string userName;\r
+ int groupId;\r
+ string groupName;\r
\r
- protected string rootPath;\r
- protected string pathPrefix;\r
+ string rootPath;\r
+ string pathPrefix;\r
\r
- protected int recordSize;\r
- protected byte[] recordBuf;\r
+ int recordSize;\r
+ byte[] recordBuf;\r
\r
- protected TarInputStream tarIn;\r
- protected TarOutputStream tarOut;\r
+ TarInputStream tarIn;\r
+ TarOutputStream tarOut;\r
\r
public event ProgressMessageHandler ProgressMessageEvent;\r
\r
- protected virtual void OnProgressMessageEvent(string message)\r
+ protected virtual void OnProgressMessageEvent(TarEntry entry, string message)\r
{\r
if (ProgressMessageEvent != null) {\r
- ProgressMessageEvent(this, message);\r
+ ProgressMessageEvent(this, entry, message);\r
}\r
}\r
\r
/// </summary>\r
public static TarArchive CreateInputTarArchive(Stream inputStream)\r
{\r
- return CreateInputTarArchive(inputStream, TarBuffer.DEFAULT_BLKSIZE);\r
+ return CreateInputTarArchive(inputStream, TarBuffer.DefaultBlockFactor);\r
}\r
\r
- public static TarArchive CreateInputTarArchive(Stream inputStream, int blockSize)\r
- {\r
- return CreateInputTarArchive(inputStream, blockSize, TarBuffer.DEFAULT_RCDSIZE);\r
- }\r
- \r
- public static TarArchive CreateInputTarArchive(Stream inputStream, int blockSize, int recordSize)\r
+ public static TarArchive CreateInputTarArchive(Stream inputStream, int blockFactor)\r
{\r
TarArchive archive = new TarArchive();\r
- archive.tarIn = new TarInputStream(inputStream, blockSize, recordSize);\r
- archive.Initialize(recordSize);\r
+ archive.tarIn = new TarInputStream(inputStream, blockFactor);\r
+ archive.Initialize(blockFactor * TarBuffer.BlockSize);\r
return archive;\r
}\r
\r
/// </summary>\r
public static TarArchive CreateOutputTarArchive(Stream outputStream)\r
{\r
- return CreateOutputTarArchive(outputStream, TarBuffer.DEFAULT_BLKSIZE);\r
+ return CreateOutputTarArchive(outputStream, TarBuffer.DefaultBlockFactor);\r
}\r
\r
- public static TarArchive CreateOutputTarArchive(Stream outputStream, int blockSize)\r
- {\r
- return CreateOutputTarArchive(outputStream, blockSize, TarBuffer.DEFAULT_RCDSIZE);\r
- }\r
- \r
- public static TarArchive CreateOutputTarArchive(Stream outputStream, int blockSize, int recordSize)\r
+ public static TarArchive CreateOutputTarArchive(Stream outputStream, int blockFactor)\r
{\r
TarArchive archive = new TarArchive();\r
- archive.tarOut = new TarOutputStream(outputStream, blockSize, recordSize);\r
- archive.Initialize(recordSize);\r
+ archive.tarOut = new TarOutputStream(outputStream, blockFactor);\r
+ archive.Initialize(blockFactor * TarBuffer.BlockSize);\r
return archive;\r
}\r
\r
- \r
/// <summary>\r
/// Common constructor initialization code.\r
/// </summary>\r
void Initialize(int recordSize)\r
{\r
+ this.recordSize = recordSize;\r
this.rootPath = null;\r
this.pathPrefix = null;\r
\r
this.recordBuf = new byte[RecordSize];\r
}\r
\r
- /**\r
- * Set the debugging flag.\r
- *\r
- * @param debugF The new debug setting.\r
- */\r
+ ///\r
+ /// <summary> Set the debugging flag. </summary>\r
+ ///\r
+ /// <param name=debugF> The new debug setting. </param>\r
+ \r
public void SetDebug(bool debugF)\r
{\r
this.debug = debugF;\r
}\r
\r
/// <summary>\r
- /// Set the ascii file translation flag. If ascii file translatio\r
+ /// Set the ascii file translation flag. If ascii file translation\r
/// is true, then the MIME file type will be consulted to determine\r
/// if the file is of type 'text/*'. If the MIME type is not found,\r
/// then the TransFileTyper is consulted if it is not null. If\r
/// file, it will be translated. The translation converts the local\r
/// operating system's concept of line ends into the UNIX line end,\r
/// '\n', which is the defacto standard for a TAR archive. This makes\r
- /// text files compatible with UNIX, and since most tar implementations\r
- /// text files compatible with UNIX, and since most tar implementations\r
+ /// text files compatible with UNIX.\r
/// </summary>\r
/// <param name= "asciiTranslate">\r
/// If true, translate ascii text files.\r
this.asciiTranslate = asciiTranslate;\r
}\r
\r
- /*\r
+/*\r
/// <summary>\r
/// Set the object that will determine if a file is of type\r
/// ascii text for translation purposes.\r
public void SetTransFileTyper(TarTransFileTyper transTyper)\r
{\r
this.transTyper = transTyper;\r
- }*/\r
+ }\r
+*/\r
\r
/// <summary>\r
/// Set user and group information that will be used to fill in the\r
\r
/// <summary>\r
/// Get the archive's record size. Because of its history, tar\r
- /// supports the concept of buffered IO consisting of BLOCKS of\r
- /// RECORDS. This allowed tar to match the IO characteristics of\r
+ /// supports the concept of buffered IO consisting of RECORDS of\r
+ /// BLOCKS. This allowed tar to match the IO characteristics of\r
/// the physical device being used. Of course, in the Java world,\r
/// this makes no sense, WITH ONE EXCEPTION - archives are expected\r
- /// to be propertly "blocked". Thus, all of the horrible TarBuffer\r
+ /// to be properly "blocked". Thus, all of the horrible TarBuffer\r
/// support boils down to simply getting the "boundaries" correct.\r
/// </summary>\r
/// <returns>\r
get {\r
if (this.tarIn != null) {\r
return this.tarIn.GetRecordSize();\r
- } else if (this.tarOut != null) {\r
+ } \r
+ else if (this.tarOut != null) {\r
return this.tarOut.GetRecordSize();\r
}\r
- return TarBuffer.DEFAULT_RCDSIZE;\r
+ return TarBuffer.DefaultRecordSize;\r
}\r
}\r
\r
{\r
if (this.tarIn != null) {\r
this.tarIn.Close();\r
- } else if (this.tarOut != null) {\r
+ } \r
+ else if (this.tarOut != null) {\r
this.tarOut.Flush();\r
this.tarOut.Close();\r
}\r
\r
if (entry == null) {\r
if (this.debug) {\r
- Console.Error.WriteLine("READ EOF RECORD");\r
+ Console.Error.WriteLine("READ EOF BLOCK");\r
}\r
break;\r
}\r
- OnProgressMessageEvent(entry.Name);\r
+ OnProgressMessageEvent(entry, null);\r
}\r
}\r
\r
\r
if (entry == null) {\r
if (this.debug) {\r
- Console.Error.WriteLine("READ EOF RECORD");\r
+ Console.Error.WriteLine("READ EOF BLOCK");\r
}\r
break;\r
}\r
if (!Directory.Exists(directoryName)) {\r
try {\r
Directory.CreateDirectory(directoryName);\r
- } catch (Exception e) {\r
+ }\r
+ catch (Exception e) {\r
throw new IOException("error making directory path '" + directoryName + "', " + e.Message);\r
}\r
}\r
}\r
\r
- \r
+ // TODO -jr- No longer reads entire file into memory but is still a weak test!\r
bool IsBinary(string filename)\r
{\r
FileStream fs = File.OpenRead(filename);\r
\r
- byte[] content = new byte[fs.Length];\r
+ int sampleSize = System.Math.Min(4096, (int)fs.Length);\r
+ byte[] content = new byte[sampleSize];\r
\r
- fs.Read(content, 0, (int)fs.Length);\r
+ fs.Read(content, 0, sampleSize);\r
fs.Close();\r
\r
// assume that ascii 0 or \r
void ExtractEntry(string destDir, TarEntry entry)\r
{\r
if (this.verbose) {\r
- OnProgressMessageEvent(entry.Name);\r
+ OnProgressMessageEvent(entry, null);\r
}\r
\r
string name = entry.Name;\r
\r
if (entry.IsDirectory) {\r
EnsureDirectoryExists(destFile);\r
- } else {\r
+ } \r
+ else {\r
string parentDirectory = Path.GetDirectoryName(destFile);\r
EnsureDirectoryExists(parentDirectory);\r
\r
if (this.keepOldFiles && File.Exists(destFile)) {\r
if (this.verbose) {\r
- OnProgressMessageEvent("not overwriting " + entry.Name);\r
+ OnProgressMessageEvent(entry, "Destination file already exists");\r
}\r
- } else {\r
+ } \r
+ else {\r
bool asciiTrans = false;\r
Stream outputStream = File.Create(destFile);\r
if (this.asciiTranslate) {\r
off = b + 1;\r
}\r
}\r
- } else {\r
+ } \r
+ else {\r
outputStream.Write(rdbuf, 0, numRead);\r
}\r
}\r
\r
if (asciiTrans) {\r
outw.Close();\r
- } else {\r
+ } \r
+ else {\r
outputStream.Close();\r
}\r
}\r
//\r
if (eFile == null || eFile.Length == 0) {\r
entry = TarEntry.CreateTarEntry(entry.Name);\r
- } else {\r
+ } \r
+ else {\r
//\r
// The user may have explicitly set the entry's name to\r
// something other than the file's path, so we must save\r
}\r
\r
if (this.verbose) {\r
- OnProgressMessageEvent(entry.Name);\r
+ OnProgressMessageEvent(entry, null);\r
}\r
\r
if (this.asciiTranslate && !entry.IsDirectory) {\r
asciiTrans = !IsBinary(eFile);\r
+\r
// original java source :\r
// MimeType mime = null;\r
// string contentType = null;\r
}\r
\r
inStream.Close();\r
+\r
outStream.Flush();\r
outStream.Close();\r
\r
this.WriteEntry(list[i], recurse);\r
}\r
}\r
- } else {\r
+ }\r
+ else {\r
Stream inputStream = File.OpenRead(eFile);\r
int numWritten = 0;\r
byte[] eBuf = new byte[32 * 1024];\r
this.tarOut.Write(eBuf, 0, numRead);\r
numWritten += numRead;\r
}\r
- Console.WriteLine("written " + numWritten + " bytes");\r
+\r
+// Console.WriteLine("written " + numWritten + " bytes");\r
\r
inputStream.Close();\r
\r
using System.IO;\r
using System.Text;\r
\r
-namespace ICSharpCode.SharpZipLib.Tar {\r
+namespace ICSharpCode.SharpZipLib.Tar \r
+{\r
\r
/// <summary>\r
/// The TarBuffer class implements the tar archive concept\r
/// of a buffered input stream. This concept goes back to the\r
/// days of blocked tape drives and special io devices. In the\r
/// C# universe, the only real function that this class\r
- /// performs is to ensure that files have the correct "block"\r
+ /// performs is to ensure that files have the correct "record"\r
/// size, or other tars will complain.\r
/// <p>\r
/// You should never have a need to access this class directly.\r
/// </summary>\r
public class TarBuffer\r
{\r
- public static readonly int DEFAULT_RCDSIZE = 512;\r
- public static readonly int DEFAULT_BLKSIZE = DEFAULT_RCDSIZE * 20;\r
+\r
+/* A quote from GNU tar man file on blocking and records\r
+ A `tar' archive file contains a series of blocks. Each block\r
+contains `BLOCKSIZE' bytes. Although this format may be thought of as\r
+being on magnetic tape, other media are often used.\r
+\r
+ Each file archived is represented by a header block which describes\r
+the file, followed by zero or more blocks which give the contents of\r
+the file. At the end of the archive file there may be a block filled\r
+with binary zeros as an end-of-file marker. A reasonable system should\r
+write a block of zeros at the end, but must not assume that such a\r
+block exists when reading an archive.\r
+\r
+ The blocks may be "blocked" for physical I/O operations. Each\r
+record of N blocks (where N is set by the `--blocking-factor=512-SIZE'\r
+(`-b 512-SIZE') option to `tar') is written with a single `write ()'\r
+operation. On magnetic tapes, the result of such a write is a single\r
+record. When writing an archive, the last record of blocks should be\r
+written at the full size, with blocks after the zero block containing\r
+all zeros. When reading an archive, a reasonable system should\r
+properly handle an archive whose last record is shorter than the rest,\r
+or which contains garbage records after a zero block.\r
+*/\r
+\r
+// public static readonly int DEFAULT_RCDSIZE = 512;\r
+// public const int DEFAULT_BLOCKFACTOR = 20;\r
+// public static readonly int DEFAULT_BLKSIZE = DEFAULT_RCDSIZE * DEFAULT_BLOCKFACTOR;\r
+\r
+ public static readonly int BlockSize = 512;\r
+ public static readonly int DefaultBlockFactor = 20;\r
+ public static readonly int DefaultRecordSize = BlockSize * DefaultBlockFactor;\r
\r
Stream inputStream;\r
Stream outputStream;\r
\r
- byte[] blockBuffer;\r
- int currBlkIdx;\r
- int currRecIdx;\r
- int blockSize;\r
- int recordSize;\r
- int recsPerBlock;\r
+ byte[] recordBuffer;\r
+ int currentBlockIndex;\r
+ int currentRecordIndex;\r
+\r
+ int recordSize = DefaultRecordSize;\r
+ public int RecordSize\r
+ {\r
+ get { return recordSize; }\r
+ }\r
+\r
+ int blockFactor = DefaultBlockFactor;\r
+\r
+ public int BlockFactor\r
+ {\r
+ get { return blockFactor; }\r
+ }\r
+\r
+ bool debug = false;\r
+\r
+ /// <summary>\r
+ /// Set the debugging flag for the buffer.\r
+ /// </summary>\r
+ public void SetDebug(bool debug)\r
+ {\r
+ this.debug = debug;\r
+ }\r
\r
- bool debug;\r
\r
protected TarBuffer()\r
{\r
\r
public static TarBuffer CreateInputTarBuffer(Stream inputStream)\r
{\r
- return CreateInputTarBuffer(inputStream, TarBuffer.DEFAULT_BLKSIZE);\r
+ return CreateInputTarBuffer(inputStream, TarBuffer.DefaultBlockFactor);\r
}\r
- public static TarBuffer CreateInputTarBuffer(Stream inputStream, int blockSize )\r
- {\r
- return CreateInputTarBuffer(inputStream, blockSize, TarBuffer.DEFAULT_RCDSIZE);\r
- }\r
- public static TarBuffer CreateInputTarBuffer(Stream inputStream, int blockSize, int recordSize)\r
+\r
+ public static TarBuffer CreateInputTarBuffer(Stream inputStream, int blockFactor)\r
{\r
TarBuffer tarBuffer = new TarBuffer();\r
tarBuffer.inputStream = inputStream;\r
tarBuffer.outputStream = null;\r
- tarBuffer.Initialize(blockSize, recordSize);\r
+ tarBuffer.Initialize(blockFactor);\r
\r
return tarBuffer;\r
}\r
\r
public static TarBuffer CreateOutputTarBuffer(Stream outputStream)\r
{\r
- return CreateOutputTarBuffer(outputStream, TarBuffer.DEFAULT_BLKSIZE);\r
+ return CreateOutputTarBuffer(outputStream, TarBuffer.DefaultBlockFactor);\r
}\r
- public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockSize )\r
- {\r
- return CreateOutputTarBuffer(outputStream, blockSize, TarBuffer.DEFAULT_RCDSIZE);\r
- }\r
- public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockSize, int recordSize)\r
+\r
+ public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockFactor)\r
{\r
TarBuffer tarBuffer = new TarBuffer();\r
tarBuffer.inputStream = null;\r
tarBuffer.outputStream = outputStream;\r
- tarBuffer.Initialize(blockSize, recordSize);\r
+ tarBuffer.Initialize(blockFactor);\r
\r
return tarBuffer;\r
}\r
/// <summary>\r
/// Initialization common to all constructors.\r
/// </summary>\r
- void Initialize(int blockSize, int recordSize)\r
+ void Initialize(int blockFactor)\r
{\r
this.debug = false;\r
- this.blockSize = blockSize;\r
- this.recordSize = recordSize;\r
- this.recsPerBlock = this.blockSize / this.recordSize;\r
- this.blockBuffer = new byte[this.blockSize];\r
+ this.blockFactor = blockFactor;\r
+ this.recordSize = blockFactor * BlockSize;\r
+\r
+ this.recordBuffer = new byte[RecordSize];\r
\r
- if (inputStream != null) {\r
- this.currBlkIdx = -1;\r
- this.currRecIdx = this.recsPerBlock;\r
- } else {\r
- this.currBlkIdx = 0;\r
- this.currRecIdx = 0;\r
+ if (inputStream != null) \r
+ {\r
+ this.currentRecordIndex = -1;\r
+ this.currentBlockIndex = BlockFactor;\r
+ } \r
+ else \r
+ {\r
+ this.currentRecordIndex = 0;\r
+ this.currentBlockIndex = 0;\r
}\r
}\r
\r
/// <summary>\r
- /// Get the TAR Buffer's block size. Blocks consist of multiple records.\r
+ /// Get the TAR Buffer's block factor\r
/// </summary>\r
- public int GetBlockSize()\r
+ public int GetBlockFactor()\r
{\r
- return this.blockSize;\r
+ return this.blockFactor;\r
}\r
\r
/// <summary>\r
}\r
\r
/// <summary>\r
- /// Set the debugging flag for the buffer.\r
+ /// Determine if an archive block indicates End of Archive. End of\r
+ /// archive is indicated by a block that consists entirely of null bytes.\r
+ /// All remaining blocks for the record should also be null's\r
+ /// However some older tars only do a couple of null blocks (Old GNU tar for one)\r
+ /// and also partial records\r
/// </summary>\r
- public void SetDebug(bool debug)\r
- {\r
- this.debug = debug;\r
- }\r
- \r
- /// <summary>\r
- /// Determine if an archive record indicate End of Archive. End of\r
- /// archive is indicated by a record that consists entirely of null bytes.\r
- /// </summary>\r
- /// <param name = "record">\r
- /// The record data to check.\r
+ /// <param name = "block">\r
+ /// The block data to check.\r
/// </param>\r
- public bool IsEOFRecord(byte[] record)\r
+ public bool IsEOFBlock(byte[] block)\r
{\r
- for (int i = 0, sz = this.GetRecordSize(); i < sz; ++i) {\r
- if (record[i] != 0) {\r
+ for (int i = 0, sz = BlockSize; i < sz; ++i) \r
+ {\r
+ if (block[i] != 0) \r
+ {\r
return false;\r
}\r
}\r
}\r
\r
/// <summary>\r
- /// Skip over a record on the input stream.\r
+ /// Skip over a block on the input stream.\r
/// </summary>\r
- public void SkipRecord()\r
+ public void SkipBlock()\r
{\r
- if (this.debug) {\r
- Console.Error.WriteLine("SkipRecord: recIdx = " + this.currRecIdx + " blkIdx = " + this.currBlkIdx);\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("SkipBlock: recIdx = " + this.currentRecordIndex + " blkIdx = " + this.currentBlockIndex);\r
}\r
\r
- if (this.inputStream == null) {\r
+ if (this.inputStream == null) \r
+ {\r
throw new System.IO.IOException("no input stream defined");\r
}\r
\r
- if (this.currRecIdx >= this.recsPerBlock) {\r
- if (!this.ReadBlock()) {\r
+ if (this.currentBlockIndex >= this.BlockFactor) \r
+ {\r
+ if (!this.ReadRecord()) \r
+ {\r
return; // UNDONE\r
}\r
}\r
\r
- this.currRecIdx++;\r
+ this.currentBlockIndex++;\r
}\r
\r
/// <summary>\r
- /// Read a record from the input stream and return the data.\r
+ /// Read a block from the input stream and return the data.\r
/// </summary>\r
/// <returns>\r
- /// The record data.\r
+ /// The block data.\r
/// </returns>\r
- public byte[] ReadRecord()\r
+ public byte[] ReadBlock()\r
{\r
- if (this.debug) {\r
- Console.Error.WriteLine( "ReadRecord: recIdx = " + this.currRecIdx + " blkIdx = " + this.currBlkIdx );\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine( "ReadBlock: blockIndex = " + this.currentBlockIndex + " recordIndex = " + this.currentRecordIndex );\r
}\r
\r
- if (this.inputStream == null) {\r
- throw new System.IO.IOException("no input stream defined");\r
+ if (this.inputStream == null) \r
+ {\r
+ throw new ApplicationException("TarBuffer.ReadBlock - no input stream defined");\r
}\r
\r
- if (this.currRecIdx >= this.recsPerBlock) {\r
- if (!this.ReadBlock()) {\r
+ if (this.currentBlockIndex >= this.BlockFactor) \r
+ {\r
+ if (!this.ReadRecord()) \r
+ {\r
return null;\r
}\r
}\r
\r
- byte[] result = new byte[this.recordSize];\r
+ byte[] result = new byte[BlockSize];\r
\r
- Array.Copy(this.blockBuffer, (this.currRecIdx * this.recordSize), result, 0, this.recordSize );\r
- this.currRecIdx++;\r
+ Array.Copy(this.recordBuffer, (this.currentBlockIndex * BlockSize), result, 0, BlockSize );\r
+ this.currentBlockIndex++;\r
return result;\r
}\r
\r
/// <returns>\r
/// false if End-Of-File, else true\r
/// </returns>\r
- bool ReadBlock()\r
+ bool ReadRecord()\r
{\r
- Console.WriteLine(this.debug);\r
- if (this.debug) {\r
- Console.Error.WriteLine("ReadBlock: blkIdx = " + this.currBlkIdx);\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("ReadRecord: recordIndex = " + this.currentRecordIndex);\r
}\r
\r
- if (this.inputStream == null) {\r
+ if (this.inputStream == null) \r
+ {\r
throw new System.IO.IOException("no input stream stream defined");\r
}\r
\r
- this.currRecIdx = 0;\r
+ this.currentBlockIndex = 0;\r
\r
int offset = 0;\r
- int bytesNeeded = this.blockSize;\r
- for (; bytesNeeded > 0 ;) {\r
- long numBytes = this.inputStream.Read(this.blockBuffer, offset, bytesNeeded);\r
+ int bytesNeeded = RecordSize;\r
+\r
+ while (bytesNeeded > 0) \r
+ {\r
+ long numBytes = this.inputStream.Read(this.recordBuffer, offset, bytesNeeded);\r
\r
//\r
// NOTE\r
- // We have fit EOF, and the block is not full!\r
+ // We have found EOF, and the record is not full!\r
//\r
// This is a broken archive. It does not follow the standard\r
// blocking algorithm. However, because we are generous, and\r
// it requires little effort, we will simply ignore the error\r
- // and continue as if the entire block were read. This does\r
+ // and continue as if the entire record were read. This does\r
// not appear to break anything upstream. We used to return\r
// false in this case.\r
//\r
// Thanks to 'Yohann.Roussel@alcatel.fr' for this fix.\r
//\r
- if (numBytes <= 0) {\r
+ if (numBytes <= 0) \r
+ {\r
break;\r
}\r
\r
offset += (int)numBytes;\r
bytesNeeded -= (int)numBytes;\r
- if (numBytes != this.blockSize) {\r
- if (this.debug) {\r
- Console.Error.WriteLine("ReadBlock: INCOMPLETE READ " + numBytes + " of " + this.blockSize + " bytes read.");\r
+ if (numBytes != RecordSize)\r
+ {\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("ReadRecord: INCOMPLETE READ " + numBytes + " of " + this.blockSize + " bytes read.");\r
}\r
}\r
}\r
\r
- this.currBlkIdx++;\r
+ this.currentRecordIndex++;\r
return true;\r
}\r
\r
/// <summary>\r
- /// Get the current block number, zero based.\r
+ /// Get the current block number, within the current record, zero based.\r
/// </summary>\r
/// <returns>\r
/// The current zero based block number.\r
/// </returns>\r
public int GetCurrentBlockNum()\r
{\r
- return this.currBlkIdx;\r
+ return this.currentBlockIndex;\r
}\r
\r
/// <summary>\r
- /// Get the current record number, within the current block, zero based.\r
- /// Thus, current offset = (currentBlockNum * recsPerBlk) + currentRecNum.\r
+ /// Get the current record number\r
+ /// Absolute block number in file = (currentRecordNum * block factor) + currentBlockNum.\r
/// </summary>\r
/// <returns>\r
/// The current zero based record number.\r
/// </returns>\r
public int GetCurrentRecordNum()\r
{\r
- return this.currRecIdx - 1;\r
+ return this.currentRecordIndex;\r
}\r
\r
/// <summary>\r
- /// Write an archive record to the archive.\r
+ /// Write an archive block to the archive.\r
/// </summary>\r
- /// <param name="record">\r
- /// The record data to write to the archive.\r
+ /// <param name="block">\r
+ /// The data to write to the archive.\r
/// </param>\r
/// \r
- public void WriteRecord(byte[] record)\r
+ public void WriteBlock(byte[] block)\r
{\r
- if (this.debug) {\r
- Console.Error.WriteLine("WriteRecord: recIdx = " + this.currRecIdx + " blkIdx = " + this.currBlkIdx );\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("WriteRecord: recIdx = " + this.currentRecordIndex + " blkIdx = " + this.currentBlockIndex );\r
}\r
\r
- if (this.outputStream == null) {\r
- throw new System.IO.IOException("no output stream defined");\r
+ if (this.outputStream == null) \r
+ {\r
+ throw new ApplicationException("TarBuffer.WriteBlock - no output stream defined");\r
}\r
\r
- if (record.Length != this.recordSize) {\r
- throw new IOException("record to write has length '" + record.Length + "' which is not the record size of '" + this.recordSize + "'" );\r
+ if (block.Length != BlockSize) \r
+ {\r
+ throw new ApplicationException("TarBuffer.WriteBlock - block to write has length '" + block.Length + "' which is not the block size of '" + BlockSize + "'" );\r
}\r
\r
- if (this.currRecIdx >= this.recsPerBlock) {\r
- this.WriteBlock();\r
+ if (this.currentBlockIndex >= BlockFactor) \r
+ {\r
+ this.WriteRecord();\r
}\r
- Array.Copy(record, 0, this.blockBuffer, (this.currRecIdx * this.recordSize), this.recordSize );\r
- this.currRecIdx++;\r
+\r
+ Array.Copy(block, 0, this.recordBuffer, (this.currentBlockIndex * BlockSize), BlockSize);\r
+ this.currentBlockIndex++;\r
}\r
\r
/// <summary>\r
/// <param name="offset">\r
/// The offset of the record data within buf.\r
/// </param>\r
- public void WriteRecord(byte[] buf, int offset)\r
+ public void WriteBlock(byte[] buf, int offset)\r
{\r
- if (this.debug) {\r
- Console.Error.WriteLine("WriteRecord: recIdx = " + this.currRecIdx + " blkIdx = " + this.currBlkIdx );\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("WriteBlock: recIdx = " + this.currentRecordIndex + " blkIdx = " + this.currentBlockIndex );\r
}\r
\r
- if (this.outputStream == null) {\r
- throw new System.IO.IOException("no output stream stream defined");\r
+ if (this.outputStream == null) \r
+ {\r
+ throw new ApplicationException("TarBuffer.WriteBlock - no output stream stream defined");\r
}\r
\r
- if ((offset + this.recordSize) > buf.Length) {\r
- throw new IOException("record has length '" + buf.Length + "' with offset '" + offset + "' which is less than the record size of '" + this.recordSize + "'" );\r
+ if ((offset + BlockSize) > buf.Length) \r
+ {\r
+ throw new ApplicationException("TarBuffer.WriteBlock - record has length '" + buf.Length + "' with offset '" + offset + "' which is less than the record size of '" + this.recordSize + "'" );\r
}\r
\r
- if (this.currRecIdx >= this.recsPerBlock) {\r
- this.WriteBlock();\r
+ if (this.currentBlockIndex >= this.BlockFactor) \r
+ {\r
+ this.WriteRecord();\r
}\r
\r
- Array.Copy(buf, offset, this.blockBuffer, (this.currRecIdx * this.recordSize), this.recordSize );\r
+ Array.Copy(buf, offset, this.recordBuffer, (this.currentBlockIndex * BlockSize), BlockSize);\r
\r
- this.currRecIdx++;\r
+ this.currentBlockIndex++;\r
}\r
\r
/// <summary>\r
- /// Write a TarBuffer block to the archive.\r
+ /// Write a TarBuffer record to the archive.\r
/// </summary>\r
- void WriteBlock()\r
+ void WriteRecord()\r
{\r
- if (this.debug) {\r
- Console.Error.WriteLine("WriteBlock: blkIdx = " + this.currBlkIdx);\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("Writerecord: record index = " + this.currentRecordIndex);\r
}\r
\r
- if (this.outputStream == null) {\r
- throw new System.IO.IOException("no output stream defined");\r
+ if (this.outputStream == null) \r
+ {\r
+ throw new ApplicationException("TarBuffer.WriteRecord no output stream defined");\r
}\r
\r
- this.outputStream.Write(this.blockBuffer, 0, this.blockSize);\r
+ this.outputStream.Write(this.recordBuffer, 0, RecordSize);\r
this.outputStream.Flush();\r
\r
- this.currRecIdx = 0;\r
- this.currBlkIdx++;\r
+ this.currentBlockIndex = 0;\r
+ this.currentRecordIndex++;\r
}\r
\r
/// <summary>\r
/// </summary>\r
void Flush()\r
{\r
- if (this.debug) {\r
- Console.Error.WriteLine("TarBuffer.FlushBlock() called.");\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("TarBuffer.FlushBlock() called.");\r
}\r
\r
- if (this.outputStream == null) {\r
- throw new System.IO.IOException("no output base stream defined");\r
+ if (this.outputStream == null) \r
+ {\r
+ throw new ApplicationException("TarBuffer.Flush no output stream defined");\r
}\r
\r
- if (this.currRecIdx > 0) {\r
- this.WriteBlock();\r
+ if (this.currentBlockIndex > 0) \r
+ {\r
+ this.WriteRecord();\r
}\r
outputStream.Flush();\r
}\r
/// </summary>\r
public void Close()\r
{\r
- if (this.debug) {\r
- Console.Error.WriteLine("TarBuffer.Close().");\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("TarBuffer.Close().");\r
}\r
\r
- if (outputStream != null ) {\r
+ if (outputStream != null)\r
+ {\r
Flush();\r
\r
-// if ( this.outStream != System.out\r
-// && this.outStream != System.err ) {\r
outputStream.Close();\r
outputStream = null;\r
- } else if (inputStream != null) {\r
-// if (this.inStream != System.in ) {\r
+ } \r
+ else if (inputStream != null) \r
+ {\r
inputStream.Close();\r
inputStream = null;\r
}\r
}\r
}\r
}\r
+\r
/* The original Java file had this header:\r
*\r
** Authored by Timothy Gerard Endres\r
using System.IO;\r
using System.Text;\r
\r
-namespace ICSharpCode.SharpZipLib.Tar {\r
+namespace ICSharpCode.SharpZipLib.Tar \r
+{\r
\r
/// <summary>\r
/// This class represents an entry in a Tar archive. It consists\r
/// other information. In this case the header fields are set to\r
/// defaults and the File is set to null.</p>\r
/// \r
- /// <p>\r
- /// The C structure for a Tar Entry's header is:\r
- /// <pre>\r
- /// struct header {\r
- /// char name[NAMSIZ];\r
- /// char mode[8];\r
- /// char uid[8];\r
- /// char gid[8];\r
- /// char size[12];\r
- /// char mtime[12];\r
- /// char chksum[8];\r
- /// char linkflag;\r
- /// char linkname[NAMSIZ];\r
- /// char magic[8];\r
- /// char uname[TUNMLEN];\r
- /// char gname[TGNMLEN];\r
- /// char devmajor[8];\r
- /// char devminor[8];\r
- /// } header;\r
- /// </pre>\r
- /// </p>\r
/// <see cref="TarHeader"/>\r
/// </summary>\r
public class TarEntry\r
/// <summary>\r
/// If this entry represents a File, this references it.\r
/// </summary>\r
- protected string file;\r
+ string file;\r
\r
/// <summary>\r
/// This is the entry's header information.\r
/// </summary>\r
- protected TarHeader header;\r
+ TarHeader header;\r
\r
/// <summary>\r
/// Only Create Entries with the static CreateXYZ methods or a headerBuffer.\r
public TarEntry(byte[] headerBuf)\r
{\r
this.Initialize();\r
- this.ParseTarHeader(this.header, headerBuf);\r
+ this.header.ParseBuffer(headerBuf);\r
}\r
\r
- \r
+\r
+ public TarEntry(TarHeader header)\r
+ {\r
+ file = null;\r
+ this.header = header;\r
+ }\r
\r
/// <summary>\r
/// Construct an entry with only a name. This allows the programmer\r
}\r
\r
/// <summary>\r
- /// Initialization code common to all constructors.\r
+ /// Initialization code common to all pseudo constructors.\r
/// </summary>\r
void Initialize()\r
{\r
/// </returns>\r
public override bool Equals(object it)\r
{\r
- if (!(it is TarEntry)) {\r
+ if (!(it is TarEntry)) \r
+ {\r
return false;\r
}\r
return this.header.name.ToString().Equals(((TarEntry)it).header.name.ToString());\r
/// <returns>\r
/// This entry's TarHeader.\r
/// </returns>\r
- public TarHeader TarHeader {\r
- get {\r
+ public TarHeader TarHeader \r
+ {\r
+ get \r
+ {\r
return this.header;\r
}\r
}\r
/// <summary>\r
/// Get/Set this entry's name.\r
/// </summary>\r
- public string Name {\r
- get {\r
+ public string Name \r
+ {\r
+ get \r
+ {\r
return this.header.name.ToString();\r
}\r
- set {\r
+ set \r
+ {\r
this.header.name = new StringBuilder(value);\r
}\r
}\r
/// <summary>\r
/// Get/set this entry's user id.\r
/// </summary>\r
- public int UserId {\r
- get {\r
+ public int UserId \r
+ {\r
+ get \r
+ {\r
return this.header.userId;\r
}\r
- set {\r
+ set \r
+ {\r
this.header.userId = value;\r
}\r
}\r
/// <summary>\r
/// Get/set this entry's group id.\r
/// </summary>\r
- public int GroupId {\r
- get {\r
+ public int GroupId \r
+ {\r
+ get \r
+ {\r
return this.header.groupId;\r
}\r
- set {\r
+ set \r
+ {\r
this.header.groupId = value;\r
}\r
}\r
/// <summary>\r
/// Get/set this entry's user name.\r
/// </summary>\r
- public string UserName {\r
- get {\r
+ public string UserName \r
+ {\r
+ get \r
+ {\r
return this.header.userName.ToString();\r
}\r
- set {\r
+ set \r
+ {\r
this.header.userName = new StringBuilder(value);\r
}\r
}\r
/// <summary>\r
/// Get/set this entry's group name.\r
/// </summary>\r
- public string GroupName {\r
- get {\r
+ public string GroupName \r
+ {\r
+ get \r
+ {\r
return this.header.groupName.ToString();\r
}\r
- set {\r
+ set \r
+ {\r
this.header.groupName = new StringBuilder(value);\r
}\r
}\r
GroupName = groupName;\r
}\r
\r
-// TODO :\r
-// /**\r
-// * Set this entry's modification time. The parameter passed\r
-// * to this method is in "Java time".\r
-// *\r
-// * @param time This entry's new modification time.\r
-// */\r
-// public void setModTime( long time )\r
-// {\r
-// this.header.modTime = time / 1000;\r
-// }\r
+ // TODO :\r
+ // /**\r
+ // * Set this entry's modification time. The parameter passed\r
+ // * to this method is in "Java time".\r
+ // *\r
+ // * @param time This entry's new modification time.\r
+ // */\r
+ // public void setModTime( long time )\r
+ // {\r
+ // this.header.modTime = time / 1000;\r
+ // }\r
\r
/// Convert time to DateTimes\r
/**\r
*\r
* @param time This entry's new modification time.\r
*/\r
- public DateTime ModTime {\r
- get {\r
+ public DateTime ModTime \r
+ {\r
+ get \r
+ {\r
return this.header.modTime;\r
}\r
- set {\r
+ set \r
+ {\r
this.header.modTime = value;\r
}\r
}\r
/// <returns>\r
/// This entry's file.\r
/// </returns>\r
- public string File {\r
- get {\r
+ public string File \r
+ {\r
+ get \r
+ {\r
return this.file;\r
}\r
}\r
/// <summary>\r
/// Get/set this entry's file size.\r
/// </summary>\r
- public long Size {\r
- get {\r
+ public long Size \r
+ {\r
+ get \r
+ {\r
return this.header.size;\r
}\r
- set {\r
+ set \r
+ {\r
this.header.size = value;\r
}\r
}\r
/// </returns>\r
public bool IsDirectory\r
{\r
- get {\r
- if (this.file != null) {\r
+ get \r
+ {\r
+ if (this.file != null) \r
+ {\r
return Directory.Exists(file);\r
}\r
\r
- if (this.header != null) {\r
- if (this.header.linkFlag == TarHeader.LF_DIR || this.header.name.ToString().EndsWith( "/" )) {\r
+ if (this.header != null) \r
+ {\r
+ if (this.header.typeFlag == TarHeader.LF_DIR || this.header.name.ToString().EndsWith( "/" )) \r
+ {\r
return true;\r
}\r
}\r
public void GetFileTarHeader(TarHeader hdr, string file)\r
{\r
this.file = file;\r
- \r
- string name = Path.GetDirectoryName(file);\r
- \r
- if (Path.DirectorySeparatorChar == '\\') { // check if the OS is a windows\r
+\r
+ // bugfix from torhovl from #D forum:\r
+ string name = file;\r
+\r
+ // -jr- 23-Jan-2004 HAK HAK HAK, GnuTar allows device names in path where the name is not local to the current directory\r
+ if (Environment.CurrentDirectory == Path.GetDirectoryName(name))\r
+ {\r
+ name = Path.GetFileName(name);\r
+ }\r
+/* \r
+ if (Path.DirectorySeparatorChar == '\\') \r
+ { // check if the OS is Windows\r
// Strip off drive letters!\r
- if (name.Length > 2) {\r
+ if (name.Length > 2) \r
+ {\r
char ch1 = name[0];\r
char ch2 = name[1];\r
\r
- if (ch2 == ':' && Char.IsLetter(ch1)) {\r
+ if (ch2 == ':' && Char.IsLetter(ch1)) \r
+ {\r
name = name.Substring(2);\r
}\r
}\r
}\r
+*/\r
\r
- name = name.Replace(Path.DirectorySeparatorChar, '/');\r
- \r
+ name = name.Replace(Path.DirectorySeparatorChar, '/').ToLower();\r
+\r
// No absolute pathnames\r
- // Windows (and Posix?) paths can start with "\\NetworkDrive\",\r
+ // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\",\r
// so we loop on starting /'s.\r
while (name.StartsWith("/")) {\r
name = name.Substring(1);\r
}\r
- \r
+\r
hdr.linkName = new StringBuilder(String.Empty);\r
hdr.name = new StringBuilder(name);\r
\r
if (Directory.Exists(file)) {\r
- hdr.mode = 040755; // TODO : what does this magic number ?? Mike\r
- hdr.linkFlag = TarHeader.LF_DIR;\r
- if (hdr.name[hdr.name.Length - 1] != '/') {\r
+ hdr.mode = 1003; // 01753 -jr- no octal constants!! 040755; // Magic number for security access for a UNIX filesystem\r
+ hdr.typeFlag = TarHeader.LF_DIR;\r
+ if (hdr.name.Length == 0 || hdr.name[hdr.name.Length - 1] != '/') {\r
hdr.name.Append("/");\r
}\r
+ \r
hdr.size = 0;\r
} else {\r
- hdr.mode = 0100644; // TODO : again a magic number\r
- hdr.linkFlag = TarHeader.LF_NORMAL;\r
- Console.WriteLine(file.Replace('/', Path.DirectorySeparatorChar));\r
+ hdr.mode = 33216; // 0100700 -jr- // 0100644; // Magic number for security access for a UNIX filesystem\r
+ hdr.typeFlag = TarHeader.LF_NORMAL;\r
hdr.size = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;\r
}\r
\r
// UNDONE When File lets us get the userName, use it!\r
- hdr.modTime = System.IO.File.GetLastAccessTime(file.Replace('/', Path.DirectorySeparatorChar));\r
- hdr.checkSum = 0;\r
+ hdr.modTime = System.IO.File.GetLastWriteTimeUtc(file.Replace('/', Path.DirectorySeparatorChar)); // -jr- Unix times are in UTC\r
+ hdr.checkSum = 0;\r
hdr.devMajor = 0;\r
hdr.devMinor = 0;\r
}\r
/// </returns>\r
public TarEntry[] GetDirectoryEntries()\r
{\r
- if (this.file == null || !Directory.Exists(this.file)) {\r
+ if (this.file == null || !Directory.Exists(this.file)) \r
+ {\r
return new TarEntry[0];\r
}\r
\r
string[] list = Directory.GetFileSystemEntries(this.file);\r
TarEntry[] result = new TarEntry[list.Length];\r
- \r
- string dirName = file;\r
- if (!dirName.EndsWith(Path.DirectorySeparatorChar.ToString())) {\r
- dirName += Path.DirectorySeparatorChar;\r
- }\r
- \r
- for (int i = 0; i < list.Length; ++i) {\r
+\r
+ for (int i = 0; i < list.Length; ++i) \r
+ {\r
result[i] = TarEntry.CreateEntryFromFile(list[i]);\r
}\r
\r
return result;\r
}\r
\r
- /// <summary>\r
- /// Compute the checksum of a tar entry header.\r
- /// </summary>\r
- /// <param name = "buf">\r
- /// The tar entry's header buffer.\r
- /// </param>\r
- /// <returns>\r
- /// The computed checksum.\r
- /// </returns>\r
- public long ComputeCheckSum(byte[] buf)\r
- {\r
- long sum = 0;\r
- for (int i = 0; i < buf.Length; ++i) {\r
- sum += 255 & buf[i]; // TODO : I think the 255 & x isn't neccessary += buf[i] should be enough. CHECK IT!\r
- }\r
- return sum;\r
- }\r
- \r
- /// <summary>\r
+ /// <summary>\r
/// Write an entry's header information to a header buffer.\r
/// </summary>\r
/// <param name = "outbuf">\r
/// </param>\r
public void WriteEntryHeader(byte[] outbuf)\r
{\r
- int offset = 0;\r
- \r
- offset = TarHeader.GetNameBytes(this.header.name, outbuf, offset, TarHeader.NAMELEN);\r
- offset = TarHeader.GetOctalBytes(this.header.mode, outbuf, offset, TarHeader.MODELEN);\r
- offset = TarHeader.GetOctalBytes(this.header.userId, outbuf, offset, TarHeader.UIDLEN);\r
- offset = TarHeader.GetOctalBytes(this.header.groupId, outbuf, offset, TarHeader.GIDLEN);\r
- \r
- long size = this.header.size;\r
- \r
- offset = TarHeader.GetLongOctalBytes(size, outbuf, offset, TarHeader.SIZELEN);\r
- offset = TarHeader.GetLongOctalBytes(GetCTime(this.header.modTime), outbuf, offset, TarHeader.MODTIMELEN);\r
- \r
- int csOffset = offset;\r
- for (int c = 0; c < TarHeader.CHKSUMLEN; ++c) {\r
- outbuf[offset++] = (byte)' ';\r
- }\r
- \r
- outbuf[offset++] = this.header.linkFlag;\r
- \r
- offset = TarHeader.GetNameBytes(this.header.linkName, outbuf, offset, TarHeader.NAMELEN);\r
- offset = TarHeader.GetNameBytes(this.header.magic, outbuf, offset, TarHeader.MAGICLEN);\r
- offset = TarHeader.GetNameBytes(this.header.userName, outbuf, offset, TarHeader.UNAMELEN);\r
- offset = TarHeader.GetNameBytes(this.header.groupName, outbuf, offset, TarHeader.GNAMELEN);\r
- \r
- offset = TarHeader.GetOctalBytes(this.header.devMajor, outbuf, offset, TarHeader.DEVLEN);\r
- offset = TarHeader.GetOctalBytes(this.header.devMinor, outbuf, offset, TarHeader.DEVLEN);\r
- \r
- for (; offset < outbuf.Length;) {\r
- outbuf[offset++] = 0;\r
- }\r
- \r
- long checkSum = this.ComputeCheckSum(outbuf);\r
- \r
- TarHeader.GetCheckSumOctalBytes(checkSum, outbuf, csOffset, TarHeader.CHKSUMLEN);\r
- }\r
- \r
- // time conversion functions\r
- readonly static long timeConversionFactor = 10000000L;\r
- readonly static DateTime datetTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0);\r
- \r
- static int GetCTime(System.DateTime dateTime)\r
- {\r
- return (int)((dateTime.Ticks - datetTime1970.Ticks) / timeConversionFactor);\r
- }\r
- \r
- static DateTime GetDateTimeFromCTime(long ticks)\r
- {\r
- return new DateTime(datetTime1970.Ticks + ticks * timeConversionFactor);\r
- }\r
- \r
- /// <summary>\r
- /// Parse an entry's TarHeader information from a header buffer.\r
- /// </summary>\r
- /// <param name ="hdr">\r
- /// Parse an entry's TarHeader information from a header buffer.\r
- /// </param>\r
- /// <param name = "header">\r
- /// The tar entry header buffer to get information from.\r
- /// </param>\r
- public void ParseTarHeader(TarHeader hdr, byte[] header)\r
- {\r
- int offset = 0;\r
- \r
- hdr.name = TarHeader.ParseName(header, offset, TarHeader.NAMELEN);\r
- \r
- offset += TarHeader.NAMELEN;\r
- \r
- hdr.mode = (int)TarHeader.ParseOctal(header, offset, TarHeader.MODELEN);\r
- \r
- offset += TarHeader.MODELEN;\r
- \r
- hdr.userId = (int)TarHeader.ParseOctal(header, offset, TarHeader.UIDLEN);\r
- \r
- offset += TarHeader.UIDLEN;\r
- \r
- hdr.groupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN);\r
- \r
- offset += TarHeader.GIDLEN;\r
- \r
- hdr.size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN);\r
- \r
- offset += TarHeader.SIZELEN;\r
- \r
- hdr.modTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN));\r
- \r
- offset += TarHeader.MODTIMELEN;\r
- \r
- hdr.checkSum = (int)TarHeader.ParseOctal(header, offset, TarHeader.CHKSUMLEN);\r
- \r
- offset += TarHeader.CHKSUMLEN;\r
- \r
- hdr.linkFlag = header[ offset++ ];\r
- \r
- hdr.linkName = TarHeader.ParseName(header, offset, TarHeader.NAMELEN);\r
- \r
- offset += TarHeader.NAMELEN;\r
- \r
- hdr.magic = TarHeader.ParseName(header, offset, TarHeader.MAGICLEN);\r
- \r
- offset += TarHeader.MAGICLEN;\r
- \r
- hdr.userName = TarHeader.ParseName(header, offset, TarHeader.UNAMELEN);\r
- \r
- offset += TarHeader.UNAMELEN;\r
- \r
- hdr.groupName = TarHeader.ParseName(header, offset, TarHeader.GNAMELEN);\r
- \r
- offset += TarHeader.GNAMELEN;\r
- \r
- hdr.devMajor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN);\r
- \r
- offset += TarHeader.DEVLEN;\r
- \r
- hdr.devMinor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN);\r
+ this.header.WriteHeader(outbuf);\r
}\r
\r
/// <summary>\r
/// </param>\r
public void NameTarHeader(TarHeader hdr, string name)\r
{\r
- bool isDir = name.EndsWith("/");\r
+ bool isDir = name.EndsWith("/"); // -jr- this is true for BSD tar but not all others I think?\r
\r
hdr.checkSum = 0;\r
- hdr.devMajor = 0;\r
- hdr.devMinor = 0;\r
\r
hdr.name = new StringBuilder(name);\r
- hdr.mode = isDir ? 040755 : 0100644; // TODO : I think I've seen these magics before ...\r
- hdr.userId = 0;\r
+// hdr.mode = isDir ? 040755 : 0100644; // TODO : I think I've seen these magics before ...\r
+ hdr.mode = isDir ? 1003 : 33216;\r
+ hdr.userId = 0;\r
hdr.groupId = 0;\r
hdr.size = 0;\r
hdr.checkSum = 0;\r
\r
- hdr.modTime = DateTime.Now;//(new java.util.Date()).getTime() / 1000;\r
+ hdr.modTime = DateTime.UtcNow; // -jr- 24-Jan-2004 Unix times are in utc!\r
+// hdr.modTime = DateTime.Now; // (new java.util.Date()).getTime() / 1000;\r
\r
- hdr.linkFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;\r
+ hdr.typeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;\r
\r
hdr.linkName = new StringBuilder(String.Empty);\r
hdr.userName = new StringBuilder(String.Empty);\r
}\r
}\r
}\r
+\r
+\r
+\r
/* The original Java file had this header:\r
*\r
** Authored by Timothy Gerard Endres\r
// TarHeader.cs\r
+//\r
// Copyright (C) 2001 Mike Krueger\r
//\r
// This program is free software; you can redistribute it and/or\r
// obligated to do so. If you do not wish to do so, delete this\r
// exception statement from your version.\r
\r
+\r
+/* The tar format and its POSIX successor PAX have a long history which makes for compatability\r
+ issues when creating and reading files...\r
+ \r
+This is the ustar (Posix 1003.1) header.\r
+\r
+struct header \r
+{\r
+ char t_name[100]; // 0 Filename \r
+ char t_mode[8]; // 100 Permissions \r
+ char t_uid[8]; // 108 Numerical User ID \r
+ char t_gid[8]; // 116 Numerical Group ID \r
+ char t_size[12]; // 124 Filesize \r
+ char t_mtime[12]; // 136 st_mtime \r
+ char t_chksum[8]; // 148 Checksum \r
+ char t_typeflag; // 156 Type of File \r
+ char t_linkname[100]; // 157 Target of Links \r
+ char t_magic[6]; // 257 "ustar" \r
+ char t_version[2]; // 263 Version fixed to 00 \r
+ char t_uname[32]; // 265 User Name \r
+ char t_gname[32]; // 297 Group Name \r
+ char t_devmajor[8]; // 329 Major for devices \r
+ char t_devminor[8]; // 337 Minor for devices \r
+ char t_prefix[155]; // 345 Prefix for t_name \r
+ // 500 End \r
+ char t_mfill[12]; // 500 Filler up to 512 \r
+};\r
+\r
+*/\r
+\r
using System;\r
using System.Text;\r
\r
-namespace ICSharpCode.SharpZipLib.Tar {\r
+namespace ICSharpCode.SharpZipLib.Tar \r
+{\r
\r
\r
/// <summary>\r
/// <summary>\r
/// The length of the magic field in a header buffer.\r
/// </summary>\r
- public readonly static int MAGICLEN = 8;\r
+ public readonly static int MAGICLEN = 6;\r
\r
+ /// <summary>\r
+ /// The length of the version field in a header buffer.\r
+ /// </summary>\r
+ public readonly static int VERSIONLEN = 2;\r
+\r
/// <summary>\r
/// The length of the modification time field in a header buffer.\r
/// </summary>\r
public readonly static int DEVLEN = 8;\r
\r
/// <summary>\r
- /// LF_ constants represent the "link flag" of an entry, or more commonly,\r
- /// the "entry type". This is the "old way" of indicating a normal file.\r
+ /// LF_ constants represents the "type" of an entry\r
/// </summary>\r
- public readonly static byte LF_OLDNORM = 0;\r
+ /// \r
+\r
+ /// <summary>\r
+ /// This is the "old way" of indicating a normal file.\r
+ /// </summary>\r
+ public const byte LF_OLDNORM = 0;\r
\r
/// <summary>\r
/// Normal file type.\r
/// </summary>\r
- public readonly static byte LF_NORMAL = (byte) '0';\r
+ public const byte LF_NORMAL = (byte) '0';\r
\r
/// <summary>\r
/// Link file type.\r
/// </summary>\r
- public readonly static byte LF_LINK = (byte) '1';\r
+ public const byte LF_LINK = (byte) '1';\r
\r
/// <summary>\r
/// Symbolic link file type.\r
/// </summary>\r
- public readonly static byte LF_SYMLINK = (byte) '2';\r
+ public const byte LF_SYMLINK = (byte) '2';\r
\r
/// <summary>\r
/// Character device file type.\r
/// </summary>\r
- public readonly static byte LF_CHR = (byte) '3';\r
+ public const byte LF_CHR = (byte) '3';\r
\r
/// <summary>\r
/// Block device file type.\r
/// </summary>\r
- public readonly static byte LF_BLK = (byte) '4';\r
+ public const byte LF_BLK = (byte) '4';\r
\r
/// <summary>\r
/// Directory file type.\r
/// </summary>\r
- public readonly static byte LF_DIR = (byte) '5';\r
+ public const byte LF_DIR = (byte) '5';\r
\r
/// <summary>\r
/// FIFO (pipe) file type.\r
/// </summary>\r
- public readonly static byte LF_FIFO = (byte) '6';\r
+ public const byte LF_FIFO = (byte) '6';\r
\r
/// <summary>\r
/// Contiguous file type.\r
/// </summary>\r
- public readonly static byte LF_CONTIG = (byte) '7';\r
+ public const byte LF_CONTIG = (byte) '7';\r
+ \r
+ /// <summary>\r
+ /// Posix.1 2001 global extended header\r
+ /// </summary>\r
+ ///\r
+ public const byte LF_GHDR = (byte) 'g';\r
+ \r
+ /// <summary>\r
+ /// Posix.1 2001 extended header\r
+ /// </summary>\r
+ public readonly static byte LF_XHDR = (byte) 'x';\r
+ \r
+ \r
+ \r
+ \r
+ // POSIX allows for upper case ascii type as extensions\r
+ \r
+ // Solaris access control list\r
+ public const byte LF_ACL = (byte) 'A';\r
+ \r
+ // This is a dir entry that contains the names of files that were in the\r
+ // dir at the time the dump was made\r
+ public const byte LF_GNU_DUMPDIR = (byte) 'D';\r
+ \r
+ // Solaris Extended Attribute File\r
+ public const byte LF_EXTATTR = (byte) 'E' ;\r
+ \r
+ // Inode (metadata only) no file content\r
+ public const byte LF_META = (byte) 'I';\r
+ \r
+ // Identifies the next file on the tape as having a long link name\r
+ public const byte LF_GNU_LONGLINK = (byte) 'K';\r
+ \r
+ // Identifies the next file on the tape as having a long name\r
+ public const byte LF_GNU_LONGNAME = (byte) 'L';\r
+ \r
+ // Continuation of a file that began on another volume\r
+ public const byte LF_GNU_MULTIVOL = (byte) 'M';\r
+ \r
+ // For storing filenames that dont fit in the main header (old GNU)\r
+ public const byte LF_GNU_NAMES = (byte) 'N';\r
+ \r
+ // Sparse file\r
+ public const byte LF_GNU_SPARSE = (byte) 'S';\r
+ \r
+ // Tape/volume header ignore on extraction\r
+ public const byte LF_GNU_VOLHDR = (byte) 'V';\r
\r
/// <summary>\r
- /// The magic tag representing a POSIX tar archive.\r
+ /// The magic tag representing a POSIX tar archive. (includes trailing NULL)\r
/// </summary>\r
- public readonly static string TMAGIC = "ustar";\r
+ public readonly static string TMAGIC = "ustar ";\r
\r
/// <summary>\r
- /// The magic tag representing a GNU tar archive.\r
+ /// The magic tag representing an old GNU tar archive where version is included in magic and overwrites it\r
/// </summary>\r
public readonly static string GNU_TMAGIC = "ustar ";\r
\r
public int checkSum;\r
\r
/// <summary>\r
- /// The entry's link flag.\r
+ /// The entry's type flag.\r
/// </summary>\r
- public byte linkFlag;\r
+ public byte typeFlag;\r
\r
/// <summary>\r
/// The entry's link name.\r
/// </summary>\r
public StringBuilder magic;\r
\r
+ /// <summary>\r
+ /// The entry's version.\r
+ /// </summary>\r
+ public StringBuilder version;\r
+ \r
/// <summary>\r
/// The entry's user name.\r
/// </summary>\r
public TarHeader()\r
{\r
this.magic = new StringBuilder(TarHeader.TMAGIC);\r
+ this.version = new StringBuilder(" ");\r
\r
this.name = new StringBuilder();\r
this.linkName = new StringBuilder();\r
\r
string user = Environment.UserName;\r
+ // string user = "PocketPC";\r
+ // string user = "Everyone";\r
\r
if (user.Length > 31) {\r
user = user.Substring(0, 31);\r
}\r
\r
- this.userId = 0;\r
- this.groupId = 0;\r
+ this.userId = 1003; // -jr- was 0\r
+ this.groupId = 513; // -jr- was 0\r
this.userName = new StringBuilder(user);\r
- this.groupName = new StringBuilder(String.Empty);\r
+// -jr-\r
+// this.groupName = new StringBuilder(String.Empty);\r
+// this.groupName = new StringBuilder("Everyone"); Attempt2\r
+ this.groupName = new StringBuilder("None"); // Gnu compatible\r
+ this.size = 0;\r
}\r
\r
/// <summary>\r
hdr.size = this.size;\r
hdr.modTime = this.modTime;\r
hdr.checkSum = this.checkSum;\r
- hdr.linkFlag = this.linkFlag;\r
+ hdr.typeFlag = this.typeFlag;\r
hdr.linkName = (this.linkName == null) ? null : new StringBuilder(this.linkName.ToString());\r
hdr.magic = (this.magic == null) ? null : new StringBuilder(this.magic.ToString());\r
+ hdr.version = (this.version == null) ? null : new StringBuilder(this.version.ToString());\r
hdr.userName = (this.userName == null) ? null : new StringBuilder(this.userName.ToString());\r
hdr.groupName = (this.groupName == null) ? null : new StringBuilder(this.groupName.ToString());\r
hdr.devMajor = this.devMajor;\r
bool stillPadding = true;\r
\r
int end = offset + length;\r
- for (int i = offset; i < end ; ++i) {\r
- if (header[i] == 0) {\r
+ for (int i = offset; i < end ; ++i) \r
+ {\r
+ if (header[i] == 0) \r
+ {\r
break;\r
}\r
\r
- if (header[i] == (byte)' ' || header[i] == '0') {\r
- if (stillPadding) {\r
+ if (header[i] == (byte)' ' || header[i] == '0') \r
+ {\r
+ if (stillPadding) \r
+ {\r
continue;\r
}\r
\r
- if (header[i] == (byte)' ') {\r
+ if (header[i] == (byte)' ') \r
+ {\r
break;\r
}\r
}\r
{\r
StringBuilder result = new StringBuilder(length);\r
\r
- for (int i = offset; i < offset + length; ++i) {\r
- if (header[i] == 0) {\r
+ for (int i = offset; i < offset + length; ++i) \r
+ {\r
+ if (header[i] == 0) \r
+ {\r
break;\r
}\r
result.Append((char)header[i]);\r
return result;\r
}\r
\r
- /// <summary>\r
+ public static int GetNameBytes(StringBuilder name, int nameOffset, byte[] buf, int bufferOffset, int length)\r
+ {\r
+ int i;\r
+ \r
+ for (i = 0 ; i < length && nameOffset + i < name.Length; ++i) \r
+ {\r
+ buf[bufferOffset + i] = (byte)name[nameOffset + i];\r
+ }\r
+ \r
+ for (; i < length ; ++i) \r
+ {\r
+ buf[bufferOffset + i] = 0;\r
+ }\r
+ \r
+ return bufferOffset + length;\r
+ }\r
+\r
+ /// <summary>\r
/// Determine the number of bytes in an entry name.\r
/// </summary>\r
/// <param name="name">\r
/// </returns>\r
public static int GetNameBytes(StringBuilder name, byte[] buf, int offset, int length)\r
{\r
- int i;\r
- \r
- for (i = 0 ; i < length && i < name.Length; ++i) {\r
- buf[offset + i] = (byte)name[i];\r
- }\r
- \r
- for (; i < length ; ++i) {\r
- buf[offset + i] = 0;\r
- }\r
- \r
- return offset + length;\r
+ return GetNameBytes(name, 0, buf, offset, length);\r
}\r
\r
/// <summary>\r
/// </returns>\r
public static int GetOctalBytes(long val, byte[] buf, int offset, int length)\r
{\r
- byte[] result = new byte[length];\r
- \r
+ // TODO check for values too large...\r
+\r
int idx = length - 1;\r
- \r
+\r
+ // Either a space or null is valid here. We use NULL as per GNUTar\r
buf[offset + idx] = 0;\r
--idx;\r
- buf[offset + idx] = (byte)' ';\r
- --idx;\r
- \r
- if (val == 0) {\r
- buf[offset + idx] = (byte)'0';\r
- --idx;\r
- } else {\r
- for (long v = val; idx >= 0 && v > 0; --idx) {\r
+\r
+ if (val > 0)\r
+ {\r
+ for (long v = val; idx >= 0 && v > 0; --idx) \r
+ {\r
buf[offset + idx] = (byte)((byte)'0' + (byte)(v & 7));\r
v >>= 3;\r
}\r
}\r
\r
- for (; idx >= 0; --idx) {\r
- buf[offset + idx] = (byte)' ';\r
+ for (; idx >= 0; --idx) \r
+ {\r
+ buf[offset + idx] = (byte)'0';\r
}\r
\r
return offset + length;\r
/// </returns>\r
public static int GetLongOctalBytes(long val, byte[] buf, int offset, int length)\r
{\r
- byte[] temp = new byte[length + 1];\r
- TarHeader.GetOctalBytes(val, temp, 0, length + 1);\r
- Array.Copy(temp, 0, buf, offset, length);\r
- return offset + length;\r
+ return GetOctalBytes(val, buf, offset, length);\r
}\r
\r
/// <summary>\r
- /// Parse the checksum octal integer from a header buffer.\r
+ /// Add the checksum octal integer to header buffer.\r
/// </summary>\r
/// <param name = "val">\r
/// </param>\r
/// <param name = "buf">\r
- /// The header buffer from which to parse.\r
+ /// The header buffer to set the checksum for\r
/// </param>\r
/// <param name = "offset">\r
- /// The offset into the buffer from which to parse.\r
+ /// The offset into the buffer for the checksum\r
/// </param>\r
/// <param name = "length">\r
- /// The number of header bytes to parse.\r
+ /// The number of header bytes to update.\r
+ /// It's formatted differently from the other fields: it has 6 digits, a\r
+ /// null, then a space -- rather than digits, a space, then a null.\r
+ /// The final space is already there, from checksumming\r
+\r
/// </param>\r
/// <returns>\r
- /// The integer value of the entry's checksum.\r
+ /// The modified buffer offset\r
/// </returns>\r
- public static int GetCheckSumOctalBytes(long val, byte[] buf, int offset, int length)\r
+ private static int GetCheckSumOctalBytes(long val, byte[] buf, int offset, int length)\r
{\r
- TarHeader.GetOctalBytes(val, buf, offset, length);\r
- buf[offset + length - 1] = (byte)' ';\r
- buf[offset + length - 2] = 0;\r
+ TarHeader.GetOctalBytes(val, buf, offset, length - 1);\r
+// buf[offset + length - 1] = (byte)' '; -jr- 23-Jan-2004 this causes failure!!!\r
+// buf[offset + length - 2] = 0;\r
return offset + length;\r
}\r
- }\r
+ \r
+ /// <summary>\r
+ /// Compute the checksum for a tar entry header. \r
+ /// The checksum field must be all spaces prior to this happening\r
+ /// </summary>\r
+ /// <param name = "buf">\r
+ /// The tar entry's header buffer.\r
+ /// </param>\r
+ /// <returns>\r
+ /// The computed checksum.\r
+ /// </returns>\r
+ private static long ComputeCheckSum(byte[] buf)\r
+ {\r
+ long sum = 0;\r
+ for (int i = 0; i < buf.Length; ++i) \r
+ {\r
+ sum += buf[i];\r
+ }\r
+ return sum;\r
+ }\r
+\r
+ readonly static long timeConversionFactor = 10000000L; // -jr- 1 tick == 100 nanoseconds\r
+ readonly static DateTime datetTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0); \r
+// readonly static DateTime datetTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToUniversalTime(); // -jr- Should be UTC? doesnt match Gnutar if this is so though, why?\r
+ \r
+ static int GetCTime(System.DateTime dateTime)\r
+ {\r
+ return (int)((dateTime.Ticks - datetTime1970.Ticks) / timeConversionFactor);\r
+ }\r
+ \r
+ static DateTime GetDateTimeFromCTime(long ticks)\r
+ {\r
+ return new DateTime(datetTime1970.Ticks + ticks * timeConversionFactor);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Parse TarHeader information from a header buffer.\r
+ /// </summary>\r
+ /// <param name = "header">\r
+ /// The tar entry header buffer to get information from.\r
+ /// </param>\r
+ public void ParseBuffer(byte[] header)\r
+ {\r
+ int offset = 0;\r
+ \r
+ name = TarHeader.ParseName(header, offset, TarHeader.NAMELEN);\r
+ offset += TarHeader.NAMELEN;\r
+ \r
+ mode = (int)TarHeader.ParseOctal(header, offset, TarHeader.MODELEN);\r
+ offset += TarHeader.MODELEN;\r
+ \r
+ userId = (int)TarHeader.ParseOctal(header, offset, TarHeader.UIDLEN);\r
+ offset += TarHeader.UIDLEN;\r
+ \r
+ groupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN);\r
+ offset += TarHeader.GIDLEN;\r
+ \r
+ size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN);\r
+ offset += TarHeader.SIZELEN;\r
+ \r
+ modTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN));\r
+ offset += TarHeader.MODTIMELEN;\r
+ \r
+ checkSum = (int)TarHeader.ParseOctal(header, offset, TarHeader.CHKSUMLEN);\r
+ offset += TarHeader.CHKSUMLEN;\r
+ \r
+ typeFlag = header[ offset++ ];\r
+\r
+ linkName = TarHeader.ParseName(header, offset, TarHeader.NAMELEN);\r
+ offset += TarHeader.NAMELEN;\r
+ \r
+ magic = TarHeader.ParseName(header, offset, TarHeader.MAGICLEN);\r
+ offset += TarHeader.MAGICLEN;\r
+\r
+ version = TarHeader.ParseName(header, offset, TarHeader.VERSIONLEN);\r
+ offset += TarHeader.VERSIONLEN;\r
+ \r
+ userName = TarHeader.ParseName(header, offset, TarHeader.UNAMELEN);\r
+ offset += TarHeader.UNAMELEN;\r
+ \r
+ groupName = TarHeader.ParseName(header, offset, TarHeader.GNAMELEN);\r
+ offset += TarHeader.GNAMELEN;\r
+ \r
+ devMajor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN);\r
+ offset += TarHeader.DEVLEN;\r
+ \r
+ devMinor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN);\r
+\r
+ // Fields past this point not currently parsed or used...\r
+ }\r
+\r
+ /// <summary>\r
+ /// 'Write' header information to buffer provided\r
+ /// </summary>\r
+ /// <param name="outbuf">output buffer for header information</param>\r
+ public void WriteHeader(byte[] outbuf)\r
+ {\r
+ int offset = 0;\r
+ \r
+ offset = GetNameBytes(this.name, outbuf, offset, TarHeader.NAMELEN);\r
+ offset = GetOctalBytes(this.mode, outbuf, offset, TarHeader.MODELEN);\r
+ offset = GetOctalBytes(this.userId, outbuf, offset, TarHeader.UIDLEN);\r
+ offset = GetOctalBytes(this.groupId, outbuf, offset, TarHeader.GIDLEN);\r
+ \r
+ long size = this.size;\r
+ \r
+ offset = GetLongOctalBytes(size, outbuf, offset, TarHeader.SIZELEN);\r
+ offset = GetLongOctalBytes(GetCTime(this.modTime), outbuf, offset, TarHeader.MODTIMELEN);\r
+ \r
+ int csOffset = offset;\r
+ for (int c = 0; c < TarHeader.CHKSUMLEN; ++c) \r
+ {\r
+ outbuf[offset++] = (byte)' ';\r
+ }\r
+ \r
+ outbuf[offset++] = this.typeFlag;\r
+ \r
+ offset = GetNameBytes(this.linkName, outbuf, offset, NAMELEN);\r
+ offset = GetNameBytes(this.magic, outbuf, offset, MAGICLEN);\r
+ offset = GetNameBytes(this.version, outbuf, offset, VERSIONLEN);\r
+ offset = GetNameBytes(this.userName, outbuf, offset, UNAMELEN);\r
+ offset = GetNameBytes(this.groupName, outbuf, offset, GNAMELEN);\r
+\r
+ if (this.typeFlag == LF_CHR || this.typeFlag == LF_BLK)\r
+ {\r
+ offset = GetOctalBytes(this.devMajor, outbuf, offset, DEVLEN);\r
+ offset = GetOctalBytes(this.devMinor, outbuf, offset, DEVLEN);\r
+ }\r
+ \r
+ for ( ; offset < outbuf.Length; ) \r
+ {\r
+ outbuf[offset++] = 0;\r
+ }\r
+ \r
+ long checkSum = ComputeCheckSum(outbuf);\r
+ \r
+ GetCheckSumOctalBytes(checkSum, outbuf, csOffset, CHKSUMLEN);\r
+ }\r
+ }\r
}\r
\r
/* The original Java file had this header:\r
using System.IO;\r
using System.Text;\r
\r
-namespace ICSharpCode.SharpZipLib.Tar {\r
+namespace ICSharpCode.SharpZipLib.Tar \r
+{\r
\r
/// <summary>\r
/// The TarInputStream reads a UNIX tar archive as an InputStream.\r
protected IEntryFactory eFactory;\r
\r
Stream inputStream;\r
+\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override bool CanRead {\r
- get {\r
+ public override bool CanRead \r
+ {\r
+ get \r
+ {\r
return inputStream.CanRead;\r
}\r
}\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override bool CanSeek {\r
- get {\r
+ public override bool CanSeek \r
+ {\r
+ // TODO is this valid? should it return false?\r
+ get \r
+ {\r
return inputStream.CanSeek;\r
}\r
}\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override bool CanWrite {\r
- get {\r
+ public override bool CanWrite \r
+ {\r
+ get \r
+ {\r
return inputStream.CanWrite;\r
}\r
}\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override long Length {\r
- get {\r
+ public override long Length \r
+ {\r
+ get \r
+ {\r
return inputStream.Length;\r
}\r
}\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override long Position {\r
- get {\r
+ public override long Position \r
+ {\r
+ get \r
+ {\r
return inputStream.Position;\r
}\r
- set {\r
+ set \r
+ {\r
inputStream.Position = value;\r
}\r
}\r
/// </summary>\r
public override long Seek(long offset, SeekOrigin origin)\r
{\r
+ // TODO allow this?\r
return inputStream.Seek(offset, origin);\r
}\r
\r
}\r
\r
\r
- public TarInputStream(Stream inputStream) : this(inputStream, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE)\r
- {\r
- }\r
- \r
- public TarInputStream(Stream inputStream, int blockSize) : this(inputStream, blockSize, TarBuffer.DEFAULT_RCDSIZE)\r
+ public TarInputStream(Stream inputStream) : this(inputStream, TarBuffer.DefaultBlockFactor)\r
{\r
}\r
\r
- public TarInputStream(Stream inputStream, int blockSize, int recordSize)\r
+ public TarInputStream(Stream inputStream, int blockFactor)\r
{\r
this.inputStream = inputStream;\r
- this.buffer = TarBuffer.CreateInputTarBuffer(inputStream, blockSize, recordSize);\r
+ this.buffer = TarBuffer.CreateInputTarBuffer(inputStream, blockFactor);\r
\r
- this.readBuf = null;\r
+ this.readBuf = null;\r
this.debug = false;\r
this.hasHitEOF = false;\r
this.eFactory = null;\r
}\r
\r
- public void SetDebug(bool debugF)\r
+ public void SetDebug(bool debugFlag)\r
{\r
- this.debug = debugF;\r
- SetBufferDebug(debugF);\r
+ this.debug = debugFlag;\r
+ SetBufferDebug(debugFlag);\r
}\r
+\r
public void SetBufferDebug(bool debug)\r
{\r
this.buffer.SetDebug(debug);\r
/// <returns>\r
/// The number of available bytes for the current entry.\r
/// </returns>\r
- public int Available {\r
- get {\r
+ public int Available \r
+ {\r
+ get \r
+ {\r
return this.entrySize - this.entryOffset;\r
}\r
}\r
/// </param>\r
public void Skip(int numToSkip)\r
{\r
- // REVIEW\r
+ // TODO REVIEW\r
// This is horribly inefficient, but it ensures that we\r
// properly skip over bytes via the TarBuffer...\r
//\r
byte[] skipBuf = new byte[8 * 1024];\r
\r
- for (int num = numToSkip; num > 0;){\r
+ for (int num = numToSkip; num > 0;)\r
+ {\r
int numRead = this.Read(skipBuf, 0, (num > skipBuf.Length ? skipBuf.Length : num));\r
\r
- if (numRead == -1) {\r
+ if (numRead == -1) \r
+ {\r
break;\r
}\r
\r
/// <summary>\r
/// Since we do not support marking just yet, we return false.\r
/// </summary>\r
- public bool IsMarkSupported {\r
- get {\r
+ public bool IsMarkSupported \r
+ {\r
+ get \r
+ {\r
return false;\r
}\r
}\r
public void Reset()\r
{\r
}\r
- \r
+\r
+ void SkipToNextEntry()\r
+ {\r
+ int numToSkip = this.entrySize - this.entryOffset;\r
+ \r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("TarInputStream: SKIP currENTRY '" + this.currEntry.Name + "' SZ " + this.entrySize + " OFF " + this.entryOffset + " skipping " + numToSkip + " bytes");\r
+ }\r
+ \r
+ if (numToSkip > 0) \r
+ {\r
+ this.Skip(numToSkip);\r
+ }\r
+ \r
+ this.readBuf = null;\r
+ }\r
+\r
/// <summary>\r
/// Get the next entry in this tar archive. This will skip\r
/// over any remaining data in the current entry, if there\r
/// </returns>\r
public TarEntry GetNextEntry()\r
{\r
- if (this.hasHitEOF) {\r
+ if (this.hasHitEOF) \r
+ {\r
return null;\r
}\r
\r
- if (this.currEntry != null) {\r
- int numToSkip = this.entrySize - this.entryOffset;\r
- \r
- if (this.debug) {\r
- Console.Error.WriteLine("TarInputStream: SKIP currENTRY '" + this.currEntry.Name + "' SZ " + this.entrySize + " OFF " + this.entryOffset + " skipping " + numToSkip + " bytes");\r
- }\r
- \r
- if (numToSkip > 0) {\r
- this.Skip(numToSkip);\r
- }\r
- \r
- this.readBuf = null;\r
+ if (this.currEntry != null) \r
+ {\r
+ SkipToNextEntry();\r
}\r
\r
- byte[] headerBuf = this.buffer.ReadRecord();\r
+ byte[] headerBuf = this.buffer.ReadBlock();\r
\r
- if (headerBuf == null) {\r
- if (this.debug) {\r
- Console.Error.WriteLine("READ NULL RECORD");\r
+ if (headerBuf == null) \r
+ {\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("READ NULL BLOCK");\r
}\r
\r
this.hasHitEOF = true;\r
- } else if (this.buffer.IsEOFRecord(headerBuf)) {\r
- if (this.debug) {\r
- Console.Error.WriteLine( "READ EOF RECORD" );\r
+ } \r
+ else if (this.buffer.IsEOFBlock(headerBuf)) \r
+ {\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine( "READ EOF BLOCK" );\r
}\r
\r
this.hasHitEOF = true;\r
}\r
\r
- if (this.hasHitEOF) {\r
+ if (this.hasHitEOF) \r
+ {\r
this.currEntry = null;\r
- } else {\r
- try {\r
- if (this.eFactory == null) {\r
- this.currEntry = new TarEntry(headerBuf);\r
- } else {\r
- this.currEntry = this.eFactory.CreateEntry(headerBuf);\r
+ } \r
+ else \r
+ {\r
+ try \r
+ {\r
+ TarHeader header = new TarHeader();\r
+ header.ParseBuffer(headerBuf);\r
+ this.entryOffset = 0;\r
+ this.entrySize = (int)header.size;\r
+\r
+ StringBuilder longName = null;\r
+\r
+ if (header.typeFlag == TarHeader.LF_GNU_LONGNAME)\r
+ {\r
+ Console.WriteLine("TarInputStream: Long name found '" + header.name + "' size = " + header.size); // DEBUG\r
+\r
+ byte[] nameBuffer = new byte[TarBuffer.BlockSize];\r
+\r
+ int numToRead = this.entrySize;\r
+\r
+ longName = new StringBuilder();\r
+\r
+ while (numToRead > 0)\r
+ {\r
+ int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : numToRead));\r
+ \r
+ if (numRead == -1) \r
+ {\r
+ throw new InvalidHeaderException("Failed to read long name entry");\r
+ }\r
+ \r
+ longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString());\r
+ numToRead -= numRead;\r
+ }\r
+\r
+ Console.WriteLine("TarInputStream: Long name is '" + longName.ToString()); // DEBUG\r
+\r
+ SkipToNextEntry();\r
+ headerBuf = this.buffer.ReadBlock();\r
+ }\r
+ else if (header.typeFlag == TarHeader.LF_GHDR) // POSIX global extended header\r
+ {\r
+ // Ignore things we dont understand completely for now\r
+ SkipToNextEntry();\r
+ headerBuf = this.buffer.ReadBlock();\r
+ }\r
+ else if (header.typeFlag == TarHeader.LF_XHDR) // POSIX extended header\r
+ {\r
+ // Ignore things we dont understand completely for now\r
+ SkipToNextEntry();\r
+ headerBuf = this.buffer.ReadBlock();\r
+ }\r
+ else if (header.typeFlag == TarHeader.LF_GNU_VOLHDR)\r
+ {\r
+ // TODO could show volume name when verbose?\r
+ SkipToNextEntry();\r
+ headerBuf = this.buffer.ReadBlock();\r
+ }\r
+ else if (header.typeFlag != TarHeader.LF_NORMAL\r
+ && header.typeFlag != TarHeader.LF_OLDNORM)\r
+ {\r
+ // Ignore things we dont understand completely for now\r
+ SkipToNextEntry();\r
+ headerBuf = this.buffer.ReadBlock();\r
+ }\r
+\r
+ if (this.eFactory == null) \r
+ {\r
+ this.currEntry = new TarEntry(headerBuf);\r
+ if (longName != null)\r
+ {\r
+ this.currEntry.TarHeader.name.Length = 0;\r
+ this.currEntry.TarHeader.name.Append(longName.ToString());\r
+ }\r
+ } \r
+ else \r
+ {\r
+ this.currEntry = this.eFactory.CreateEntry(headerBuf);\r
}\r
- \r
- if (!(headerBuf[257] == 'u' && headerBuf[258] == 's' && headerBuf[259] == 't' && headerBuf[260] == 'a' && headerBuf[261] == 'r')) {\r
+\r
+ // TODO -jr- ustar is not the only magic possible by any means\r
+ // tar, xtar, ... \r
+ if (!(headerBuf[257] == 'u' && headerBuf[258] == 's' && headerBuf[259] == 't' && headerBuf[260] == 'a' && headerBuf[261] == 'r')) \r
+ {\r
throw new InvalidHeaderException("header magic is not 'ustar', but '" + headerBuf[257] + headerBuf[258] + headerBuf[259] + headerBuf[260] + headerBuf[261] + \r
- "', or (dec) " + ((int)headerBuf[257]) + ", " + ((int)headerBuf[258]) + ", " + ((int)headerBuf[259]) + ", " + ((int)headerBuf[260]) + ", " + ((int)headerBuf[261]));\r
+ "', or (dec) " + ((int)headerBuf[257]) + ", " + ((int)headerBuf[258]) + ", " + ((int)headerBuf[259]) + ", " + ((int)headerBuf[260]) + ", " + ((int)headerBuf[261]));\r
}\r
\r
- if (this.debug) {\r
- Console.Error.WriteLine("TarInputStream: SET CURRENTRY '" + this.currEntry.Name + "' size = " + this.currEntry.Size);\r
+ if (this.debug) \r
+ {\r
+ //Console.WriteLine.WriteLine("TarInputStream: SET CURRENTRY '" + this.currEntry.Name + "' size = " + this.currEntry.Size);\r
}\r
\r
this.entryOffset = 0;\r
\r
- // REVIEW How do we resolve this discrepancy?!\r
+ // TODO REVIEW How do we resolve this discrepancy?!\r
this.entrySize = (int) this.currEntry.Size;\r
- } catch (InvalidHeaderException ex) {\r
+ } \r
+ catch (InvalidHeaderException ex) \r
+ {\r
this.entrySize = 0;\r
this.entryOffset = 0;\r
this.currEntry = null;\r
- throw new InvalidHeaderException("bad header in block " + this.buffer.GetCurrentBlockNum() + " record " + this.buffer.GetCurrentRecordNum() + ", " + ex.Message);\r
+ throw new InvalidHeaderException("bad header in record " + this.buffer.GetCurrentBlockNum() + " block " + this.buffer.GetCurrentBlockNum() + ", " + ex.Message);\r
}\r
}\r
return this.currEntry;\r
{\r
byte[] oneByteBuffer = new byte[1];\r
int num = this.Read(oneByteBuffer, 0, 1);\r
- if (num <= 0) { // return -1 to indicate that no byte was read.\r
+ if (num <= 0) // return -1 to indicate that no byte was read.\r
+ {\r
return -1;\r
}\r
return (int)oneByteBuffer[0];\r
/// Reads bytes from the current tar archive entry.\r
/// \r
/// This method is aware of the boundaries of the current\r
- /// entry in the archive and will deal with them as if they\r
- /// entry in the archive and will deal with them as if they\r
+ /// entry in the archive and will deal with them appropriately\r
/// </summary>\r
- /// <param name="buf">\r
+ /// <param name="outputBuffer">\r
/// The buffer into which to place bytes read.\r
/// </param>\r
/// <param name="offset">\r
/// The number of bytes to read.\r
/// </param>\r
/// <returns>\r
- /// The number of bytes read, or -1 at EOF.\r
+ /// The number of bytes read, or 0 at end of stream/EOF.\r
/// </returns>\r
- public override int Read(byte[] buf, int offset, int numToRead)\r
+ public override int Read(byte[] outputBuffer, int offset, int numToRead)\r
{\r
int totalRead = 0;\r
\r
- if (this.entryOffset >= this.entrySize) {\r
- return -1;\r
+ if (this.entryOffset >= this.entrySize) \r
+ {\r
+ return 0;\r
}\r
\r
- if ((numToRead + this.entryOffset) > this.entrySize) {\r
+ if ((numToRead + this.entryOffset) > this.entrySize) \r
+ {\r
numToRead = this.entrySize - this.entryOffset;\r
}\r
\r
- if (this.readBuf != null) {\r
+ if (this.readBuf != null) \r
+ {\r
int sz = (numToRead > this.readBuf.Length) ? this.readBuf.Length : numToRead;\r
\r
- Array.Copy(this.readBuf, 0, buf, offset, sz);\r
+ Array.Copy(this.readBuf, 0, outputBuffer, offset, sz);\r
\r
- if (sz >= this.readBuf.Length) {\r
+ if (sz >= this.readBuf.Length) \r
+ {\r
this.readBuf = null;\r
- } else {\r
+ } \r
+ else \r
+ {\r
int newLen = this.readBuf.Length - sz;\r
- byte[] newBuf = new byte[ newLen ];\r
+ byte[] newBuf = new byte[newLen];\r
Array.Copy(this.readBuf, sz, newBuf, 0, newLen);\r
this.readBuf = newBuf;\r
}\r
offset += sz;\r
}\r
\r
- while (numToRead > 0) {\r
- byte[] rec = this.buffer.ReadRecord();\r
- if (rec == null) {\r
+ while (numToRead > 0) \r
+ {\r
+ byte[] rec = this.buffer.ReadBlock();\r
+ if (rec == null) \r
+ {\r
// Unexpected EOF!\r
throw new IOException("unexpected EOF with " + numToRead + " bytes unread");\r
}\r
int sz = numToRead;\r
int recLen = rec.Length;\r
\r
- if (recLen > sz) {\r
- Array.Copy(rec, 0, buf, offset, sz);\r
+ if (recLen > sz) \r
+ {\r
+ Array.Copy(rec, 0, outputBuffer, offset, sz);\r
this.readBuf = new byte[recLen - sz];\r
Array.Copy(rec, sz, this.readBuf, 0, recLen - sz);\r
- } else {\r
+ } \r
+ else \r
+ {\r
sz = recLen;\r
- Array.Copy(rec, 0, buf, offset, recLen);\r
+ Array.Copy(rec, 0, outputBuffer, offset, recLen);\r
}\r
\r
totalRead += sz;\r
{\r
byte[] buf = new byte[32 * 1024];\r
\r
- while (true) {\r
+ while (true) \r
+ {\r
int numRead = this.Read(buf, 0, buf.Length);\r
- if (numRead <= 0) {\r
+ if (numRead <= 0) \r
+ {\r
break;\r
}\r
outputStream.Write(buf, 0, numRead);\r
using System.IO;\r
using System.Text;\r
\r
-namespace ICSharpCode.SharpZipLib.Tar {\r
+namespace ICSharpCode.SharpZipLib.Tar \r
+{\r
\r
/// <summary>\r
/// The TarOutputStream writes a UNIX tar archive as an OutputStream.\r
protected bool debug;\r
protected int currSize;\r
protected int currBytes;\r
- protected byte[] recordBuf;\r
+ protected byte[] blockBuf; \r
protected int assemLen;\r
protected byte[] assemBuf;\r
\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override bool CanRead {\r
- get {\r
+ public override bool CanRead \r
+ {\r
+ get \r
+ {\r
return outputStream.CanRead;\r
}\r
}\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override bool CanSeek {\r
- get {\r
- return outputStream.CanSeek;\r
+ public override bool CanSeek \r
+ {\r
+ get \r
+ {\r
+ return outputStream.CanSeek; // -jr- Should be false?\r
}\r
}\r
\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override bool CanWrite {\r
- get {\r
+ public override bool CanWrite \r
+ {\r
+ get \r
+ {\r
return outputStream.CanWrite;\r
}\r
}\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override long Length {\r
- get {\r
+ public override long Length \r
+ {\r
+ get \r
+ {\r
return outputStream.Length;\r
}\r
}\r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
- public override long Position {\r
- get {\r
+ public override long Position \r
+ {\r
+ get \r
+ {\r
return outputStream.Position;\r
}\r
- set {\r
+ set \r
+ {\r
outputStream.Position = value;\r
}\r
}\r
outputStream.Flush();\r
}\r
\r
- public TarOutputStream(Stream outputStream) : this(outputStream, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE)\r
+ public TarOutputStream(Stream outputStream) : this(outputStream, TarBuffer.DefaultBlockFactor)\r
{\r
}\r
\r
- public TarOutputStream(Stream outputStream, int blockSize) : this(outputStream, blockSize, TarBuffer.DEFAULT_RCDSIZE)\r
- {\r
- }\r
- \r
- public TarOutputStream(Stream outputStream, int blockSize, int recordSize)\r
+ public TarOutputStream(Stream outputStream, int blockFactor)\r
{\r
this.outputStream = outputStream;\r
- this.buffer = TarBuffer.CreateOutputTarBuffer(outputStream, blockSize, recordSize);\r
+ this.buffer = TarBuffer.CreateOutputTarBuffer(outputStream, blockFactor);\r
\r
this.debug = false;\r
this.assemLen = 0;\r
- this.assemBuf = new byte[recordSize];\r
- this.recordBuf = new byte[recordSize];\r
+ this.assemBuf = new byte[TarBuffer.BlockSize];\r
+ this.blockBuf = new byte[TarBuffer.BlockSize];\r
}\r
\r
/// <summary>\r
/// Sets the debugging flag.\r
/// </summary>\r
- /// <param name = "debugF">\r
+ /// <param name = "debugFlag">\r
/// True to turn on debugging.\r
/// </param>\r
- public void SetDebug(bool debugF)\r
+ public void SetDebug(bool debugFlag)\r
{\r
- this.debug = debugF;\r
- SetBufferDebug(debugF);\r
+ this.debug = debugFlag;\r
+ SetBufferDebug(debugFlag);\r
}\r
\r
public void SetBufferDebug(bool debug)\r
\r
/// <summary>\r
/// Put an entry on the output stream. This writes the entry's\r
- /// header record and positions the output stream for writing\r
+ /// header and positions the output stream for writing\r
/// the contents of the entry. Once this method is called, the\r
/// stream is ready for calls to write() to write the entry's\r
/// contents. Once the contents are written, closeEntry()\r
/// </param>\r
public void PutNextEntry(TarEntry entry)\r
{\r
- if (entry.TarHeader.name.Length > TarHeader.NAMELEN) {\r
- throw new InvalidHeaderException("file name '" + entry.TarHeader.name + "' is too long ( > " + TarHeader.NAMELEN + " bytes )");\r
+ if (entry.TarHeader.name.Length > TarHeader.NAMELEN) \r
+ {\r
+ TarHeader longHeader = new TarHeader();\r
+ longHeader.typeFlag = TarHeader.LF_GNU_LONGNAME;\r
+ longHeader.name.Append("././@LongLink");\r
+ longHeader.userId = 0;\r
+ longHeader.groupId = 0;\r
+ longHeader.groupName.Length = 0;\r
+ longHeader.userName.Length = 0;\r
+ longHeader.linkName.Length = 0;\r
+\r
+ longHeader.size = entry.TarHeader.name.Length;\r
+\r
+ Console.WriteLine("TarOutputStream: PutNext entry Long name found size = " + longHeader.size); // DEBUG\r
+\r
+ longHeader.WriteHeader(this.blockBuf);\r
+ this.buffer.WriteBlock(this.blockBuf); // Add special long filename header block\r
+\r
+ int nameCharIndex = 0;\r
+\r
+ while (nameCharIndex < entry.TarHeader.name.Length)\r
+ {\r
+ TarHeader.GetNameBytes(entry.TarHeader.name, nameCharIndex, this.blockBuf, 0, TarBuffer.BlockSize);\r
+ nameCharIndex += TarBuffer.BlockSize;\r
+ this.buffer.WriteBlock(this.blockBuf);\r
+ }\r
}\r
\r
- entry.WriteEntryHeader(this.recordBuf);\r
- this.buffer.WriteRecord(this.recordBuf);\r
+ entry.WriteEntryHeader(this.blockBuf);\r
+ this.buffer.WriteBlock(this.blockBuf);\r
\r
this.currBytes = 0;\r
\r
/// Close an entry. This method MUST be called for all file\r
/// entries that contain data. The reason is that we must\r
/// buffer data written to the stream in order to satisfy\r
- /// the buffer's record based writes. Thus, there may be\r
+ /// the buffer's block based writes. Thus, there may be\r
/// data fragments still being assembled that must be written\r
/// to the output stream before this entry is closed and the\r
/// next entry written.\r
/// </summary>\r
public void CloseEntry()\r
{\r
- if (this.assemLen > 0) {\r
- for (int i = this.assemLen; i < this.assemBuf.Length; ++i) {\r
+ if (this.assemLen > 0) \r
+ {\r
+ for (int i = this.assemLen; i < this.assemBuf.Length; ++i) \r
+ {\r
this.assemBuf[i] = 0;\r
}\r
\r
- this.buffer.WriteRecord(this.assemBuf);\r
+ this.buffer.WriteBlock(this.assemBuf);\r
\r
this.currBytes += this.assemLen;\r
this.assemLen = 0;\r
}\r
\r
- if (this.currBytes < this.currSize) {\r
+ if (this.currBytes < this.currSize) \r
+ {\r
throw new IOException("entry closed at '" + this.currBytes + "' before the '" + this.currSize + "' bytes specified in the header were written");\r
}\r
}\r
/// </param>\r
public override void Write(byte[] wBuf, int wOffset, int numToWrite)\r
{\r
- if ((this.currBytes + numToWrite) > this.currSize) {\r
+ if ((this.currBytes + numToWrite) > this.currSize) \r
+ {\r
throw new IOException("request to write '" + numToWrite + "' bytes exceeds size in header of '" + this.currSize + "' bytes");\r
}\r
\r
// REVIEW Maybe this should be in TarBuffer? Could that help to\r
// eliminate some of the buffer copying.\r
//\r
- if (this.assemLen > 0) {\r
- if ((this.assemLen + numToWrite ) >= this.recordBuf.Length) {\r
- int aLen = this.recordBuf.Length - this.assemLen;\r
+ if (this.assemLen > 0) \r
+ {\r
+ if ((this.assemLen + numToWrite ) >= this.blockBuf.Length) \r
+ {\r
+ int aLen = this.blockBuf.Length - this.assemLen;\r
\r
- Array.Copy(this.assemBuf, 0, this.recordBuf, 0, this.assemLen);\r
+ Array.Copy(this.assemBuf, 0, this.blockBuf, 0, this.assemLen);\r
\r
- Array.Copy(wBuf, wOffset, this.recordBuf, this.assemLen, aLen);\r
+ Array.Copy(wBuf, wOffset, this.blockBuf, this.assemLen, aLen);\r
\r
- this.buffer.WriteRecord(this.recordBuf);\r
+ this.buffer.WriteBlock(this.blockBuf);\r
\r
- this.currBytes += this.recordBuf.Length;\r
+ this.currBytes += this.blockBuf.Length;\r
\r
wOffset += aLen;\r
numToWrite -= aLen;\r
\r
this.assemLen = 0;\r
- } else {// ( (this.assemLen + numToWrite ) < this.recordBuf.length )\r
+ } \r
+ else \r
+ {// ( (this.assemLen + numToWrite ) < this.blockBuf.length )\r
Array.Copy(wBuf, wOffset, this.assemBuf, this.assemLen, numToWrite);\r
wOffset += numToWrite;\r
this.assemLen += numToWrite;\r
// o An empty "assemble" buffer.\r
// o No bytes to write (numToWrite == 0)\r
//\r
- while (numToWrite > 0) {\r
- if (numToWrite < this.recordBuf.Length) {\r
+ while (numToWrite > 0) \r
+ {\r
+ if (numToWrite < this.blockBuf.Length) \r
+ {\r
Array.Copy(wBuf, wOffset, this.assemBuf, this.assemLen, numToWrite);\r
this.assemLen += numToWrite;\r
break;\r
}\r
\r
- this.buffer.WriteRecord(wBuf, wOffset);\r
+ this.buffer.WriteBlock(wBuf, wOffset);\r
\r
- int num = this.recordBuf.Length;\r
+ int num = this.blockBuf.Length;\r
this.currBytes += num;\r
numToWrite -= num;\r
wOffset += num;\r
/// </summary>\r
void WriteEOFRecord()\r
{\r
- for (int i = 0; i < this.recordBuf.Length; ++i) {\r
- this.recordBuf[i] = 0;\r
+ for (int i = 0; i < this.blockBuf.Length; ++i) \r
+ {\r
+ this.blockBuf[i] = 0;\r
}\r
- this.buffer.WriteRecord(this.recordBuf);\r
+ this.buffer.WriteBlock(this.blockBuf);\r
}\r
}\r
}\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
/// <summary>\r
/// This is the Deflater class. The deflater class compresses input\r
\r
private static int INIT_STATE = 0x00;\r
private static int SETDICT_STATE = 0x01;\r
-// private static int INIT_FINISHING_STATE = 0x08;\r
-// private static int SETDICT_FINISHING_STATE = 0x09;\r
+ // private static int INIT_FINISHING_STATE = 0x08;\r
+ // private static int SETDICT_FINISHING_STATE = 0x09;\r
private static int BUSY_STATE = 0x10;\r
private static int FLUSHING_STATE = 0x14;\r
private static int FINISHING_STATE = 0x1c;\r
/// </summary>\r
private bool noHeader;\r
\r
-// /// <summary>\r
-// /// Compression strategy.\r
-// /// </summary>\r
-// private int strategy;\r
+ // /// <summary>\r
+ // /// Compression strategy.\r
+ // /// </summary>\r
+ // private int strategy;\r
\r
/// <summary>\r
/// The current state.\r
throw new ArgumentOutOfRangeException("lvl");\r
}\r
\r
- \r
if (level != lvl) {\r
level = lvl;\r
engine.SetLevel(lvl);\r
if (state < BUSY_STATE) {\r
/* output header */\r
int header = (DEFLATED +\r
- ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;\r
+ ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;\r
int level_flags = (level - 1) >> 1;\r
if (level_flags < 0 || level_flags > 3) {\r
level_flags = 3;\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
/// <summary>\r
/// This class contains constants used for the deflater.\r
\r
using ICSharpCode.SharpZipLib.Checksums;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
- public enum DeflateStrategy {\r
+ public enum DeflateStrategy \r
+ {\r
// The default strategy.\r
Default = 0,\r
\r
static int TOO_FAR = 4096;\r
\r
int ins_h;\r
-// private byte[] buffer;\r
+ // private byte[] buffer;\r
short[] head;\r
short[] prev;\r
\r
max_chain = DeflaterConstants.MAX_CHAIN[lvl];\r
\r
if (DeflaterConstants.COMPR_FUNC[lvl] != comprFunc) {\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("Change from "+comprFunc +" to "\r
-// + DeflaterConstants.COMPR_FUNC[lvl]);\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("Change from "+comprFunc +" to "\r
+ // + DeflaterConstants.COMPR_FUNC[lvl]);\r
+ // }\r
switch (comprFunc) {\r
case DEFLATE_STORED:\r
if (strstart > blockStart) {\r
huffman.FlushStoredBlock(window, blockStart,\r
- strstart - blockStart, false);\r
+ strstart - blockStart, false);\r
blockStart = strstart;\r
}\r
UpdateHash();\r
case DEFLATE_FAST:\r
if (strstart > blockStart) {\r
huffman.FlushBlock(window, blockStart, strstart - blockStart,\r
- false);\r
+ false);\r
blockStart = strstart;\r
}\r
break;\r
huffman.TallyLit(window[strstart-1] & 0xff);\r
}\r
if (strstart > blockStart) {\r
- huffman.FlushBlock(window, blockStart, strstart - blockStart,\r
- false);\r
+ huffman.FlushBlock(window, blockStart, strstart - blockStart, false);\r
blockStart = strstart;\r
}\r
prevAvailable = false;\r
}\r
}\r
\r
- private void UpdateHash() \r
+ void UpdateHash() \r
{\r
-// if (DEBUGGING) {\r
-// Console.WriteLine("updateHash: "+strstart);\r
-// }\r
+ // if (DEBUGGING) {\r
+ // //Console.WriteLine("updateHash: "+strstart);\r
+ // }\r
ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1];\r
}\r
\r
- private int InsertString() \r
+ int InsertString() \r
{\r
short match;\r
int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)]) & HASH_MASK;\r
\r
-// if (DEBUGGING) {\r
-// if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^ \r
-// (window[strstart + 1] << HASH_SHIFT) ^ \r
-// (window[strstart + 2])) & HASH_MASK)) {\r
-// throw new Exception("hash inconsistent: "+hash+"/"\r
-// +window[strstart]+","\r
-// +window[strstart+1]+","\r
-// +window[strstart+2]+","+HASH_SHIFT);\r
-// }\r
-// }\r
+ // if (DEBUGGING) {\r
+ // if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^ \r
+ // (window[strstart + 1] << HASH_SHIFT) ^ \r
+ // (window[strstart + 2])) & HASH_MASK)) {\r
+ // throw new Exception("hash inconsistent: "+hash+"/"\r
+ // +window[strstart]+","\r
+ // +window[strstart+1]+","\r
+ // +window[strstart+2]+","+HASH_SHIFT);\r
+ // }\r
+ // }\r
\r
prev[strstart & WMASK] = match = head[hash];\r
head[hash] = (short)strstart;\r
}\r
}\r
\r
- private bool FindLongestMatch(int curMatch) \r
+ bool FindLongestMatch(int curMatch) \r
{\r
int chainLength = this.max_chain;\r
int niceLength = this.niceLength;\r
}\r
\r
if (DeflaterConstants.DEBUGGING && strstart > 2 * WSIZE - MIN_LOOKAHEAD) {\r
- throw new InvalidOperationException("need lookahead");\r
+ throw new InvalidOperationException("need lookahead");\r
}\r
\r
do {\r
throw new InvalidOperationException("future match");\r
}\r
if (window[curMatch + best_len] != scan_end || \r
- window[curMatch + best_len - 1] != scan_end1 || \r
- window[curMatch] != window[scan] || \r
- window[curMatch + 1] != window[scan + 1]) {\r
- continue;\r
+ window[curMatch + best_len - 1] != scan_end1 || \r
+ window[curMatch] != window[scan] || \r
+ window[curMatch + 1] != window[scan + 1]) {\r
+ continue;\r
}\r
\r
match = curMatch + 2;\r
/* We check for insufficient lookahead only every 8th comparison;\r
* the 256th check will be made at strstart+258.\r
*/\r
- while (window[++scan] == window[++match] && \r
- window[++scan] == window[++match] && \r
- window[++scan] == window[++match] && \r
- window[++scan] == window[++match] && \r
- window[++scan] == window[++match] && \r
- window[++scan] == window[++match] && \r
- window[++scan] == window[++match] && \r
- window[++scan] == window[++match] && scan < strend) ;\r
+ while (window[++scan] == window[++match] && \r
+ window[++scan] == window[++match] && \r
+ window[++scan] == window[++match] && \r
+ window[++scan] == window[++match] && \r
+ window[++scan] == window[++match] && \r
+ window[++scan] == window[++match] && \r
+ window[++scan] == window[++match] && \r
+ window[++scan] == window[++match] && scan < strend) ;\r
\r
if (scan > best_end) {\r
// if (DeflaterConstants.DEBUGGING && ins_h == 0)\r
matchStart = curMatch;\r
best_end = scan;\r
best_len = scan - strstart;\r
+ \r
if (best_len >= niceLength) {\r
break;\r
}\r
blockStart = strstart;\r
}\r
\r
- private bool DeflateStored(bool flush, bool finish)\r
+ bool DeflateStored(bool flush, bool finish)\r
{\r
if (!flush && lookahead == 0) {\r
return false;\r
lastBlock = false;\r
}\r
\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("storedBlock["+storedLen+","+lastBlock+"]");\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("storedBlock["+storedLen+","+lastBlock+"]");\r
+ // }\r
\r
huffman.FlushStoredBlock(window, blockStart, storedLen, lastBlock);\r
blockStart += storedLen;\r
return false;\r
}\r
\r
- if (strstart > 2 * WSIZE - MIN_LOOKAHEAD)\r
- {\r
+ if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) {\r
/* slide window, as findLongestMatch need this.\r
* This should only happen when flushing and the window\r
* is almost full.\r
\r
int hashHead;\r
if (lookahead >= MIN_MATCH && \r
- (hashHead = InsertString()) != 0 && \r
- strategy != DeflateStrategy.HuffmanOnly &&\r
- strstart - hashHead <= MAX_DIST && \r
- FindLongestMatch(hashHead)) {\r
+ (hashHead = InsertString()) != 0 && \r
+ strategy != DeflateStrategy.HuffmanOnly &&\r
+ strstart - hashHead <= MAX_DIST && \r
+ FindLongestMatch(hashHead)) {\r
/* longestMatch sets matchStart and matchLen */\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// for (int i = 0 ; i < matchLen; i++) {\r
-// if (window[strstart+i] != window[matchStart + i]) {\r
-// throw new Exception();\r
-// }\r
-// }\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // for (int i = 0 ; i < matchLen; i++) {\r
+ // if (window[strstart+i] != window[matchStart + i]) {\r
+ // throw new Exception();\r
+ // }\r
+ // }\r
+ // }\r
\r
- huffman.TallyDist(strstart - matchStart, matchLen);\r
+ // -jr- Hak hak hak this stops problems with fast/low compression and index out of range\r
+ if (huffman.TallyDist(strstart - matchStart, matchLen)) {\r
+ bool lastBlock = finish && lookahead == 0;\r
+ huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock);\r
+ blockStart = strstart;\r
+ }\r
\r
lookahead -= matchLen;\r
if (matchLen <= max_lazy && lookahead >= MIN_MATCH) {\r
\r
if (huffman.IsFull()) {\r
bool lastBlock = finish && lookahead == 0;\r
- huffman.FlushBlock(window, blockStart, strstart - blockStart,\r
- lastBlock);\r
+ huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock);\r
blockStart = strstart;\r
return !lastBlock;\r
}\r
return true;\r
}\r
\r
- private bool DeflateSlow(bool flush, bool finish)\r
+ bool DeflateSlow(bool flush, bool finish)\r
{\r
if (lookahead < MIN_LOOKAHEAD && !flush) {\r
return false;\r
throw new Exception("Not flushing, but no lookahead");\r
}\r
huffman.FlushBlock(window, blockStart, strstart - blockStart,\r
- finish);\r
+ finish);\r
blockStart = strstart;\r
return false;\r
}\r
\r
- if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD)\r
- {\r
+ if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) {\r
/* slide window, as findLongestMatch need this.\r
* This should only happen when flushing and the window\r
* is almost full.\r
*/\r
- SlideWindow();\r
+ SlideWindow();\r
}\r
\r
int prevMatch = matchStart;\r
int prevLen = matchLen;\r
if (lookahead >= MIN_MATCH) {\r
int hashHead = InsertString();\r
- if (strategy != DeflateStrategy.HuffmanOnly && hashHead != 0 && strstart - hashHead <= MAX_DIST && FindLongestMatch(hashHead))\r
- {\r
- /* longestMatch sets matchStart and matchLen */\r
+ if (strategy != DeflateStrategy.HuffmanOnly && hashHead != 0 && strstart - hashHead <= MAX_DIST && FindLongestMatch(hashHead)) {\r
+ /* longestMatch sets matchStart and matchLen */\r
\r
- /* Discard match if too small and too far away */\r
- if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TOO_FAR))) {\r
- matchLen = MIN_MATCH - 1;\r
- }\r
+ /* Discard match if too small and too far away */\r
+ if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TOO_FAR))) {\r
+ matchLen = MIN_MATCH - 1;\r
}\r
+ }\r
}\r
\r
/* previous match was better */\r
if (prevLen >= MIN_MATCH && matchLen <= prevLen) {\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// for (int i = 0 ; i < matchLen; i++) {\r
-// if (window[strstart-1+i] != window[prevMatch + i])\r
-// throw new Exception();\r
-// }\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // for (int i = 0 ; i < matchLen; i++) {\r
+ // if (window[strstart-1+i] != window[prevMatch + i])\r
+ // throw new Exception();\r
+ // }\r
+ // }\r
huffman.TallyDist(strstart - 1 - prevMatch, prevLen);\r
prevLen -= 2;\r
do {\r
do {\r
FillWindow();\r
bool canFlush = flush && inputOff == inputEnd;\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("window: ["+blockStart+","+strstart+","\r
-// +lookahead+"], "+comprFunc+","+canFlush);\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("window: ["+blockStart+","+strstart+","\r
+ // +lookahead+"], "+comprFunc+","+canFlush);\r
+ // }\r
switch (comprFunc) {\r
case DEFLATE_STORED:\r
progress = DeflateStored(canFlush, finish);\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
/// <summary>\r
/// This is the DeflaterHuffman class.\r
15\r
};\r
\r
- \r
public class Tree \r
{\r
public short[] freqs;\r
- public short[] codes;\r
public byte[] length;\r
- public int[] bl_counts;\r
public int minNumCodes, numCodes;\r
- public int maxLength;\r
+ \r
+ short[] codes;\r
+ int[] bl_counts;\r
+ int maxLength;\r
DeflaterHuffman dh;\r
\r
public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength) \r
\r
public void WriteSymbol(int code)\r
{\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// freqs[code]--;\r
-// // Console.Write("writeSymbol("+freqs.length+","+code+"): ");\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // freqs[code]--;\r
+ // // Console.Write("writeSymbol("+freqs.length+","+code+"): ");\r
+ // }\r
dh.pending.WriteBits(codes[code] & 0xffff, length[code]);\r
}\r
\r
bool empty = true;\r
for (int i = 0; i < freqs.Length; i++) {\r
if (freqs[i] != 0) {\r
- Console.WriteLine("freqs["+i+"] == "+freqs[i]);\r
+ //Console.WriteLine("freqs["+i+"] == "+freqs[i]);\r
empty = false;\r
}\r
}\r
if (!empty) {\r
throw new Exception();\r
}\r
- Console.WriteLine("checkEmpty suceeded!");\r
+ //Console.WriteLine("checkEmpty suceeded!");\r
}\r
\r
public void SetStaticCodes(short[] stCodes, byte[] stLength)\r
int code = 0;\r
codes = new short[freqs.Length];\r
\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("buildCodes: "+freqs.Length);\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("buildCodes: "+freqs.Length);\r
+ // }\r
\r
for (int bits = 0; bits < maxLength; bits++) {\r
nextCode[bits] = code;\r
code += bl_counts[bits] << (15 - bits);\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("bits: "+(bits+1)+" count: "+bl_counts[bits]\r
-// +" nextCode: "+code); // HACK : Integer.toHexString(\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("bits: "+(bits+1)+" count: "+bl_counts[bits]\r
+ // +" nextCode: "+code); // HACK : Integer.toHexString(\r
+ // }\r
}\r
if (DeflaterConstants.DEBUGGING && code != 65536) {\r
throw new Exception("Inconsistent bl_counts!");\r
for (int i=0; i < numCodes; i++) {\r
int bits = length[i];\r
if (bits > 0) {\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+")," // HACK : Integer.toHexString(\r
-// +bits);\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+")," // HACK : Integer.toHexString(\r
+ // +bits);\r
+ // }\r
codes[i] = BitReverse(nextCode[bits-1]);\r
nextCode[bits-1] += 1 << (16 - bits);\r
}\r
}\r
}\r
\r
- private void BuildLength(int[] childs)\r
+ void BuildLength(int[] childs)\r
{\r
this.length = new byte [freqs.Length];\r
int numNodes = childs.Length / 2;\r
}\r
}\r
\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("Tree "+freqs.Length+" lengths:");\r
-// for (int i=0; i < numLeafs; i++) {\r
-// Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]\r
-// + " len: "+length[childs[2*i]]);\r
-// }\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("Tree "+freqs.Length+" lengths:");\r
+ // for (int i=0; i < numLeafs; i++) {\r
+ // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]\r
+ // + " len: "+length[childs[2*i]]);\r
+ // }\r
+ // }\r
\r
if (overflow == 0) {\r
return;\r
}\r
}\r
}\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("*** After overflow elimination. ***");\r
-// for (int i=0; i < numLeafs; i++) {\r
-// Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]\r
-// + " len: "+length[childs[2*i]]);\r
-// }\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("*** After overflow elimination. ***");\r
+ // for (int i=0; i < numLeafs; i++) {\r
+ // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]\r
+ // + " len: "+length[childs[2*i]]);\r
+ // }\r
+ // }\r
}\r
\r
public void BuildTree()\r
/* Propagate the hole to the leafs of the heap */\r
int ppos = 0;\r
int path = 1;\r
+ \r
while (path < heapLen) {\r
if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) {\r
path++;\r
}\r
- \r
+ \r
heap[ppos] = heap[path];\r
ppos = path;\r
path = path * 2 + 1;\r
}\r
- \r
+ \r
/* Now propagate the last element down along path. Normally\r
* it shouldn't go too deep.\r
*/\r
/* Again, propagate the hole to the leafs */\r
ppos = 0;\r
path = 1;\r
+ \r
while (path < heapLen) {\r
if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) {\r
path++;\r
}\r
- \r
+ \r
heap[ppos] = heap[path];\r
ppos = path;\r
path = ppos * 2 + 1;\r
}\r
- \r
+ \r
/* Now propagate the new element down along path */\r
while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) {\r
heap[path] = heap[ppos];\r
while (count-- > 0) {\r
blTree.WriteSymbol(curlen);\r
}\r
- }\r
- else if (curlen != 0) {\r
+ } else if (curlen != 0) {\r
blTree.WriteSymbol(REP_3_6);\r
dh.pending.WriteBits(count - 3, 2);\r
} else if (count <= 10) {\r
/// </summary>\r
public static short BitReverse(int value) \r
{\r
- return (short) (bit4Reverse[value & 0xF] << 12\r
- | bit4Reverse[(value >> 4) & 0xF] << 8\r
- | bit4Reverse[(value >> 8) & 0xF] << 4\r
- | bit4Reverse[value >> 12]);\r
+ return (short) (bit4Reverse[value & 0xF] << 12 | \r
+ bit4Reverse[(value >> 4) & 0xF] << 8 | \r
+ bit4Reverse[(value >> 8) & 0xF] << 4 |\r
+ bit4Reverse[value >> 12]);\r
}\r
\r
\r
blTree.Reset();\r
}\r
\r
- private int L_code(int len) \r
+ int Lcode(int len) \r
{\r
if (len == 255) {\r
return 285;\r
return code + len;\r
}\r
\r
- private int D_code(int distance) \r
+ int Dcode(int distance) \r
{\r
int code = 0;\r
while (distance >= 4) {\r
}\r
literalTree.WriteTree(blTree);\r
distTree.WriteTree(blTree);\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// blTree.CheckEmpty();\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // blTree.CheckEmpty();\r
+ // }\r
}\r
\r
public void CompressBlock()\r
int litlen = l_buf[i] & 0xff;\r
int dist = d_buf[i];\r
if (dist-- != 0) {\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");\r
+ // }\r
\r
- int lc = L_code(litlen);\r
+ int lc = Lcode(litlen);\r
literalTree.WriteSymbol(lc);\r
\r
int bits = (lc - 261) / 4;\r
pending.WriteBits(litlen & ((1 << bits) - 1), bits);\r
}\r
\r
- int dc = D_code(dist);\r
+ int dc = Dcode(dist);\r
distTree.WriteSymbol(dc);\r
\r
bits = dc / 2 - 1;\r
pending.WriteBits(dist & ((1 << bits) - 1), bits);\r
}\r
} else {\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// if (litlen > 32 && litlen < 127) {\r
-// Console.Write("("+(char)litlen+"): ");\r
-// } else {\r
-// Console.Write("{"+litlen+"}: ");\r
-// }\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // if (litlen > 32 && litlen < 127) {\r
+ // Console.Write("("+(char)litlen+"): ");\r
+ // } else {\r
+ // Console.Write("{"+litlen+"}: ");\r
+ // }\r
+ // }\r
literalTree.WriteSymbol(litlen);\r
}\r
}\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.Write("EOF: ");\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // Console.Write("EOF: ");\r
+ // }\r
literalTree.WriteSymbol(EOF_SYMBOL);\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// literalTree.CheckEmpty();\r
-// distTree.CheckEmpty();\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // literalTree.CheckEmpty();\r
+ // distTree.CheckEmpty();\r
+ // }\r
}\r
\r
- public void FlushStoredBlock(byte[] stored, int stored_offset, int stored_len, bool lastBlock)\r
+ public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)\r
{\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("Flushing stored block "+ stored_len);\r
-// }\r
- pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1)\r
- + (lastBlock ? 1 : 0), 3);\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("Flushing stored block "+ storedLength);\r
+ // }\r
+ pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3);\r
pending.AlignToByte();\r
- pending.WriteShort(stored_len);\r
- pending.WriteShort(~stored_len);\r
- pending.WriteBlock(stored, stored_offset, stored_len);\r
+ pending.WriteShort(storedLength);\r
+ pending.WriteShort(~storedLength);\r
+ pending.WriteBlock(stored, storedOffset, storedLength);\r
Reset();\r
}\r
\r
- public void FlushBlock(byte[] stored, int stored_offset, int stored_len, bool lastBlock)\r
+ public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)\r
{\r
literalTree.freqs[EOF_SYMBOL]++;\r
\r
}\r
}\r
int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() + \r
- literalTree.GetEncodedLength() + distTree.GetEncodedLength() + \r
- extra_bits;\r
+ literalTree.GetEncodedLength() + distTree.GetEncodedLength() + \r
+ extra_bits;\r
\r
int static_len = extra_bits;\r
for (int i = 0; i < LITERAL_NUM; i++) {\r
opt_len = static_len;\r
}\r
\r
- if (stored_offset >= 0 && stored_len+4 < (opt_len >> 3)) {\r
+ if (storedOffset >= 0 && storedLength+4 < opt_len >> 3) {\r
/* Store Block */\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("Storing, since " + stored_len + " < " + opt_len\r
-// + " <= " + static_len);\r
-// }\r
- FlushStoredBlock(stored, stored_offset, stored_len, lastBlock);\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len\r
+ // + " <= " + static_len);\r
+ // }\r
+ FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);\r
} else if (opt_len == static_len) {\r
/* Encode with static tree */\r
pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);\r
\r
public bool IsFull()\r
{\r
- return last_lit + 16 >= BUFSIZE; // HACK: This was == 'last_lit == BUFSIZE', but errors occured with DeflateFast\r
+// return last_lit + 16 >= BUFSIZE; // HACK: This was == 'last_lit == BUFSIZE', but errors occured with DeflateFast\r
+ return last_lit >= BUFSIZE; // -jr- This is the correct form!\r
}\r
\r
public bool TallyLit(int lit)\r
{\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// if (lit > 32 && lit < 127) {\r
-// Console.WriteLine("("+(char)lit+")");\r
-// } else {\r
-// Console.WriteLine("{"+lit+"}");\r
-// }\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // if (lit > 32 && lit < 127) {\r
+ // //Console.WriteLine("("+(char)lit+")");\r
+ // } else {\r
+ // //Console.WriteLine("{"+lit+"}");\r
+ // }\r
+ // }\r
d_buf[last_lit] = 0;\r
l_buf[last_lit++] = (byte)lit;\r
literalTree.freqs[lit]++;\r
\r
public bool TallyDist(int dist, int len)\r
{\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("["+dist+","+len+"]");\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("["+dist+","+len+"]");\r
+ // }\r
\r
d_buf[last_lit] = (short)dist;\r
l_buf[last_lit++] = (byte)(len - 3);\r
\r
- int lc = L_code(len - 3);\r
+ int lc = Lcode(len - 3);\r
literalTree.freqs[lc]++;\r
if (lc >= 265 && lc < 285) {\r
extra_bits += (lc - 261) / 4;\r
}\r
\r
- int dc = D_code(dist - 1);\r
+ int dc = Dcode(dist - 1);\r
distTree.freqs[dc]++;\r
if (dc >= 4) {\r
extra_bits += dc / 2 - 1;\r
// obligated to do so. If you do not wish to do so, delete this\r
// exception statement from your version.\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
/// <summary>\r
/// This class stores the pending output of the Deflater.\r
using ICSharpCode.SharpZipLib.Checksums;\r
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
/// <summary>\r
/// Inflater is used to decompress data that has been compressed according\r
/// Copy lengths for literal codes 257..285\r
/// </summary>\r
private static int[] CPLENS = {\r
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\r
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258\r
- };\r
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\r
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258\r
+ };\r
\r
/// <summary>\r
/// Extra bits for literal codes 257..285\r
/// </summary>\r
private static int[] CPLEXT = {\r
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,\r
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0\r
- };\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,\r
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0\r
+ };\r
\r
/// <summary>\r
/// Copy offsets for distance codes 0..29\r
/// </summary>\r
private static int[] CPDIST = {\r
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\r
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\r
- 8193, 12289, 16385, 24577\r
- };\r
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\r
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\r
+ 8193, 12289, 16385, 24577\r
+ };\r
\r
/// <summary>\r
/// Extra bits for distance codes\r
/// </summary>\r
private static int[] CPDEXT = {\r
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,\r
- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,\r
- 12, 12, 13, 13\r
- };\r
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,\r
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,\r
+ 12, 12, 13, 13\r
+ };\r
\r
/// <summary>\r
/// This are the state in which the inflater can be.\r
neededBits -= 8;\r
}\r
if ((int) adler.Value != readAdler) {\r
- throw new FormatException("Adler chksum doesn't match: "\r
- + (int)adler.Value\r
- + " vs. " + readAdler);\r
+ throw new FormatException("Adler chksum doesn't match: " + (int)adler.Value + " vs. " + readAdler);\r
}\r
mode = FINISHED;\r
return false;\r
if ((type & 1) != 0) {\r
isLastBlock = true;\r
}\r
- switch (type >> 1) {\r
+ switch (type >> 1){\r
case DeflaterConstants.STORED_BLOCK:\r
input.SkipToByteBoundary();\r
mode = DECODE_STORED_LEN1;\r
}\r
return true;\r
\r
- case DECODE_STORED_LEN1: {\r
+ case DECODE_STORED_LEN1: \r
+ {\r
if ((uncomprLen = input.PeekBits(16)) < 0) {\r
return false;\r
}\r
input.DropBits(16);\r
mode = DECODE_STORED_LEN2;\r
}\r
- goto case DECODE_STORED_LEN2; /* fall through */\r
- case DECODE_STORED_LEN2: {\r
+ goto case DECODE_STORED_LEN2; /* fall through */\r
+ case DECODE_STORED_LEN2: \r
+ {\r
int nlen = input.PeekBits(16);\r
if (nlen < 0) {\r
return false;\r
}\r
mode = DECODE_STORED;\r
}\r
- goto case DECODE_STORED;/* fall through */\r
- case DECODE_STORED: {\r
+ goto case DECODE_STORED;/* fall through */\r
+ case DECODE_STORED: \r
+ {\r
int more = outputWindow.CopyStored(input, uncomprLen);\r
uncomprLen -= more;\r
if (uncomprLen == 0) {\r
}\r
\r
adler.Update(buffer, off, len);\r
- if ((int) adler.Value != readAdler) {\r
+ if ((int)adler.Value != readAdler) {\r
throw new ArgumentException("Wrong adler checksum");\r
}\r
adler.Reset();\r
}\r
// Special case: len may be zero\r
if (len == 0) {\r
+ if (IsFinished == false) {// -jr- 08-Nov-2003 INFLATE_BUG fix..\r
+ Decode();\r
+ }\r
return 0;\r
}\r
-/* // Check for correct buff, off, len triple\r
- if (off < 0 || off + len >= buf.Length) {\r
- throw new ArgumentException("off/len outside buf bounds");\r
- }*/\r
+ /* // Check for correct buff, off, len triple\r
+ if (off < 0 || off + len >= buf.Length) {\r
+ throw new ArgumentException("off/len outside buf bounds");\r
+ }*/\r
int count = 0;\r
int more;\r
do {\r
return count;\r
}\r
}\r
- } while (Decode() || (outputWindow.GetAvailable() > 0 &&\r
- mode != DECODE_CHKSUM));\r
+ } while (Decode() || (outputWindow.GetAvailable() > 0 && mode != DECODE_CHKSUM));\r
return count;\r
}\r
\r
\r
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
class InflaterDynHeader\r
{\r
byte lastLen;\r
int ptr;\r
\r
- static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };\r
+ static readonly int[] BL_ORDER = \r
+ { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };\r
\r
public InflaterDynHeader()\r
{\r
public bool Decode(StreamManipulator input)\r
{\r
decode_loop:\r
- for (;;) {\r
- switch (mode) {\r
- case LNUM:\r
- lnum = input.PeekBits(5);\r
- if (lnum < 0) {\r
- return false;\r
- }\r
- lnum += 257;\r
- input.DropBits(5);\r
- // System.err.println("LNUM: "+lnum);\r
- mode = DNUM;\r
- goto case DNUM; // fall through\r
- case DNUM:\r
- dnum = input.PeekBits(5);\r
- if (dnum < 0) {\r
- return false;\r
- }\r
- dnum++;\r
- input.DropBits(5);\r
- // System.err.println("DNUM: "+dnum);\r
- num = lnum+dnum;\r
- litdistLens = new byte[num];\r
- mode = BLNUM;\r
- goto case BLNUM; // fall through\r
- case BLNUM:\r
- blnum = input.PeekBits(4);\r
- if (blnum < 0) {\r
- return false;\r
- }\r
- blnum += 4;\r
- input.DropBits(4);\r
- blLens = new byte[19];\r
- ptr = 0;\r
- // System.err.println("BLNUM: "+blnum);\r
- mode = BLLENS;\r
- goto case BLLENS; // fall through\r
- case BLLENS:\r
- while (ptr < blnum) {\r
- int len = input.PeekBits(3);\r
- if (len < 0) {\r
+ for (;;) {\r
+ switch (mode) {\r
+ case LNUM:\r
+ lnum = input.PeekBits(5);\r
+ if (lnum < 0) {\r
return false;\r
}\r
- input.DropBits(3);\r
- // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);\r
- blLens[BL_ORDER[ptr]] = (byte) len;\r
- ptr++;\r
- }\r
- blTree = new InflaterHuffmanTree(blLens);\r
- blLens = null;\r
- ptr = 0;\r
- mode = LENS;\r
- goto case LENS; // fall through\r
- case LENS: {\r
- int symbol;\r
- while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) {\r
- /* Normal case: symbol in [0..15] */\r
+ lnum += 257;\r
+ input.DropBits(5);\r
+ // System.err.println("LNUM: "+lnum);\r
+ mode = DNUM;\r
+ goto case DNUM; // fall through\r
+ case DNUM:\r
+ dnum = input.PeekBits(5);\r
+ if (dnum < 0) {\r
+ return false;\r
+ }\r
+ dnum++;\r
+ input.DropBits(5);\r
+ // System.err.println("DNUM: "+dnum);\r
+ num = lnum+dnum;\r
+ litdistLens = new byte[num];\r
+ mode = BLNUM;\r
+ goto case BLNUM; // fall through\r
+ case BLNUM:\r
+ blnum = input.PeekBits(4);\r
+ if (blnum < 0) {\r
+ return false;\r
+ }\r
+ blnum += 4;\r
+ input.DropBits(4);\r
+ blLens = new byte[19];\r
+ ptr = 0;\r
+ // System.err.println("BLNUM: "+blnum);\r
+ mode = BLLENS;\r
+ goto case BLLENS; // fall through\r
+ case BLLENS:\r
+ while (ptr < blnum) {\r
+ int len = input.PeekBits(3);\r
+ if (len < 0) {\r
+ return false;\r
+ }\r
+ input.DropBits(3);\r
+ // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);\r
+ blLens[BL_ORDER[ptr]] = (byte) len;\r
+ ptr++;\r
+ }\r
+ blTree = new InflaterHuffmanTree(blLens);\r
+ blLens = null;\r
+ ptr = 0;\r
+ mode = LENS;\r
+ goto case LENS; // fall through\r
+ case LENS: \r
+ {\r
+ int symbol;\r
+ while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) {\r
+ /* Normal case: symbol in [0..15] */\r
\r
- // System.err.println("litdistLens["+ptr+"]: "+symbol);\r
- litdistLens[ptr++] = lastLen = (byte)symbol;\r
+ // System.err.println("litdistLens["+ptr+"]: "+symbol);\r
+ litdistLens[ptr++] = lastLen = (byte)symbol;\r
\r
- if (ptr == num) {\r
- /* Finished */\r
- return true;\r
+ if (ptr == num) {\r
+ /* Finished */\r
+ return true;\r
+ }\r
}\r
- }\r
\r
- /* need more input ? */\r
- if (symbol < 0)\r
- return false;\r
+ /* need more input ? */\r
+ if (symbol < 0) {\r
+ return false;\r
+ }\r
\r
- /* otherwise repeat code */\r
- if (symbol >= 17) {\r
- /* repeat zero */\r
- // System.err.println("repeating zero");\r
- lastLen = 0;\r
- } else {\r
- if (ptr == 0) {\r
- throw new Exception();\r
+ /* otherwise repeat code */\r
+ if (symbol >= 17) {\r
+ /* repeat zero */\r
+ // System.err.println("repeating zero");\r
+ lastLen = 0;\r
+ } else {\r
+ if (ptr == 0) {\r
+ throw new Exception();\r
+ }\r
}\r
+ repSymbol = symbol-16;\r
}\r
- repSymbol = symbol-16;\r
- }\r
- mode = REPS;\r
- goto case REPS; // fall through\r
- case REPS:\r
+ mode = REPS;\r
+ goto case REPS; // fall through\r
+ case REPS:\r
{\r
int bits = repBits[repSymbol];\r
int count = input.PeekBits(bits);\r
return true;\r
}\r
}\r
- mode = LENS;\r
- goto decode_loop;\r
+ mode = LENS;\r
+ goto decode_loop;\r
+ }\r
}\r
- }\r
}\r
\r
public InflaterHuffmanTree BuildLitLenTree()\r
\r
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
public class InflaterHuffmanTree \r
{\r
\r
for (int i = 0; i < codeLengths.Length; i++) {\r
int bits = codeLengths[i];\r
- if (bits > 0)\r
+ if (bits > 0) {\r
blCount[bits]++;\r
+ }\r
}\r
\r
int code = 0;\r
treeSize += (end - start) >> (16 - bits);\r
}\r
}\r
- if (code != 65536) {\r
+/* -jr comment this out! doesnt work for dynamic trees and pkzip 2.04g\r
+ if (code != 65536) \r
+ {\r
throw new Exception("Code lengths don't add up properly.");\r
}\r
+*/\r
/* Now create and fill the extra tables from longest to shortest\r
* bit len. This way the sub trees will be aligned.\r
*/\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression \r
+{\r
\r
/// <summary>\r
/// This class is general purpose class for writing data to a buffer.\r
\r
public void WriteByte(int b)\r
{\r
- if (DeflaterConstants.DEBUGGING && start != 0)\r
+ if (DeflaterConstants.DEBUGGING && start != 0) {\r
throw new Exception();\r
+ }\r
buf[end++] = (byte) b;\r
}\r
\r
if (DeflaterConstants.DEBUGGING && start != 0) {\r
throw new Exception();\r
}\r
-// if (DeflaterConstants.DEBUGGING) {\r
-// Console.WriteLine("writeBits("+b+","+count+")");\r
-// }\r
+ // if (DeflaterConstants.DEBUGGING) {\r
+ // //Console.WriteLine("writeBits("+b+","+count+")");\r
+ // }\r
bits |= (uint)(b << bitCount);\r
bitCount += count;\r
if (bitCount >= 16) {\r
\r
public byte[] ToByteArray()\r
{\r
- byte[] ret = new byte[ end - start ];\r
+ byte[] ret = new byte[end - start];\r
System.Array.Copy(buf, start, ret, 0, ret.Length);\r
start = 0;\r
end = 0;\r
\r
using System;\r
using System.IO;\r
-\r
+using ICSharpCode.SharpZipLib.Checksums;\r
using ICSharpCode.SharpZipLib.Zip.Compression;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams \r
+{\r
\r
/// <summary>\r
/// This is a special FilterOutputStream deflating the bytes that are\r
/// </summary>\r
public override bool CanSeek {\r
get {\r
- return baseOutputStream.CanSeek;\r
+ return false;\r
+// return baseOutputStream.CanSeek;\r
}\r
}\r
\r
/// </summary>\r
public override long Seek(long offset, SeekOrigin origin)\r
{\r
- return baseOutputStream.Seek(offset, origin);\r
+ throw new NotSupportedException("Seek not supported"); // -jr- 01-Dec-2003\r
+// return baseOutputStream.Seek(offset, origin);\r
}\r
\r
/// <summary>\r
{\r
return baseOutputStream.Read(b, off, len);\r
}\r
+ // -jr- 01-Dec-2003\r
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)\r
+ {\r
+ throw new NotSupportedException("Asynch read not currently supported");\r
+ }\r
\r
+ // -jr- 01-Dec-2003\r
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)\r
+ {\r
+ throw new NotSupportedException("Asynch write not currently supported");\r
+ }\r
\r
/// <summary>\r
/// Deflates everything in the def's input buffers. This will call\r
/// <code>def.deflate()</code> until all bytes from the input buffers\r
/// are processed.\r
/// </summary>\r
- protected void deflate()\r
+ protected void Deflate()\r
{\r
while (!def.IsNeedingInput) {\r
int len = def.Deflate(buf, 0, buf.Length);\r
/// </param>\r
public DeflaterOutputStream(Stream baseOutputStream) : this(baseOutputStream, new Deflater(), 512)\r
{\r
- \r
}\r
\r
/// <summary>\r
public override void Flush()\r
{\r
def.Flush();\r
- deflate();\r
+ Deflate();\r
baseOutputStream.Flush();\r
}\r
\r
public virtual void Finish()\r
{\r
def.Finish();\r
- while (!def.IsFinished) {\r
+ while (!def.IsFinished) {\r
int len = def.Deflate(buf, 0, buf.Length);\r
if (len <= 0) {\r
break;\r
}\r
+ \r
+ // kidnthrain encryption alteration\r
+ if (this.Password != null) {\r
+ // plain data has been deflated. Now encrypt result\r
+ this.EncryptBlock(buf, 0, len);\r
+ }\r
+ \r
baseOutputStream.Write(buf, 0, len);\r
}\r
if (!def.IsFinished) {\r
{\r
// System.err.println("DOS with off " + off + " and len " + len);\r
def.SetInput(buf, off, len);\r
- deflate();\r
+ Deflate();\r
}\r
\r
+ #region Encryption\r
+ string password = null;\r
+ uint[] keys = null;\r
+ \r
+ public string Password {\r
+ get { \r
+ return password; \r
+ }\r
+ set { \r
+ password = value; \r
+ }\r
+ }\r
+ \r
+ \r
+ //The beauty of xor-ing bits is that\r
+ //plain ^ key = enc\r
+ //and enc ^ key = plain\r
+ //accordingly, this is the exact same as the decrypt byte\r
+ //function in InflaterInputStream\r
+ protected byte EncryptByte()\r
+ {\r
+ uint temp = ((keys[2] & 0xFFFF) | 2);\r
+ return (byte)((temp * (temp ^ 1)) >> 8);\r
+ }\r
+ \r
+ \r
+ /// <summary>\r
+ /// Takes a buffer of data and uses the keys\r
+ /// that have been previously initialized from a\r
+ /// password and then updated via a random encryption header\r
+ /// to encrypt that data\r
+ /// </summary>\r
+ protected void EncryptBlock(byte[] buf, int off, int len)\r
+ {\r
+ for (int i = off; i < off + len; ++i) {\r
+ byte oldbyte = buf[i];\r
+ buf[i] ^= EncryptByte();\r
+ UpdateKeys(oldbyte);\r
+ }\r
+ }\r
+ \r
+ /// <summary>\r
+ /// Initializes our encryption keys using a given password\r
+ /// </summary>\r
+ protected void InitializePassword(string password) {\r
+ keys = new uint[] {\r
+ 0x12345678,\r
+ 0x23456789,\r
+ 0x34567890\r
+ };\r
+ \r
+ for (int i = 0; i < password.Length; ++i) {\r
+ UpdateKeys((byte)password[i]);\r
+ }\r
+ }\r
+ \r
+ protected void UpdateKeys(byte ch)\r
+ {\r
+ keys[0] = Crc32.ComputeCrc32(keys[0], ch);\r
+ keys[1] = keys[1] + (byte)keys[0];\r
+ keys[1] = keys[1] * 134775813 + 1;\r
+ keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24));\r
+ }\r
+ #endregion\r
}\r
}\r
using System.IO;\r
\r
using ICSharpCode.SharpZipLib.Zip.Compression;\r
+using ICSharpCode.SharpZipLib.Checksums;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams \r
+{\r
\r
/// <summary>\r
/// This filter stream is used to decompress data compressed baseInputStream the "deflate"\r
/// </summary>\r
protected Inflater inf;\r
\r
- \r
/// <summary>\r
/// Byte array used as a buffer\r
/// </summary>\r
/// </summary>\r
protected Stream baseInputStream;\r
\r
+ protected long csize;\r
+ \r
/// <summary>\r
/// I needed to implement the abstract member.\r
/// </summary>\r
/// </summary>\r
public override bool CanSeek {\r
get {\r
- return baseInputStream.CanSeek;\r
+ return false;\r
+ // return baseInputStream.CanSeek;\r
}\r
}\r
\r
/// </summary>\r
public override long Seek(long offset, SeekOrigin origin)\r
{\r
- return baseInputStream.Seek(offset, origin);\r
+ throw new NotSupportedException("Seek not supported"); // -jr- 01-Dec-2003\r
}\r
\r
/// <summary>\r
baseInputStream.WriteByte(val);\r
}\r
\r
+ // -jr- 01-Dec-2003 This may be flawed for some base streams? Depends on implementation of BeginWrite\r
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)\r
+ {\r
+ throw new NotSupportedException("Asynch write not currently supported");\r
+ }\r
+ \r
//Constructors\r
\r
/// <summary>\r
/// </param>\r
public InflaterInputStream(Stream baseInputStream, Inflater inf) : this(baseInputStream, inf, 4096)\r
{\r
- \r
}\r
\r
/// <summary>\r
this.inf = inf;\r
try {\r
this.len = (int)baseInputStream.Length;\r
- } catch (Exception) { // the stream may not support .Length\r
+ } catch (Exception) {\r
+ // the stream may not support .Length\r
this.len = 0;\r
}\r
\r
/// </summary>\r
public override void Close()\r
{\r
- // Do not close the parent, it might be used by a ZipFile, and\r
- // we do not want to close the "master" source.\r
- // baseInputStream.Close();\r
+ baseInputStream.Close();\r
}\r
\r
/// <summary>\r
protected void Fill()\r
{\r
len = baseInputStream.Read(buf, 0, buf.Length);\r
+ // decrypting crypted data\r
+ if (cryptbuffer != null) {\r
+ DecryptBlock(buf, 0, System.Math.Min((int)(csize - inf.TotalIn), buf.Length));\r
+ }\r
\r
- if (len < 0) {\r
+ if (len <= 0) {\r
throw new ApplicationException("Deflated stream ends early.");\r
}\r
inf.SetInput(buf, 0, len);\r
if (nread > 0) {\r
return onebytebuffer[0] & 0xff;\r
}\r
- return -1;\r
+ return -1; // ok\r
}\r
\r
/// <summary>\r
if (n < len) {\r
len = (int) n;\r
}\r
- if (false && baseInputStream.CanSeek){\r
- baseInputStream.Seek (len, SeekOrigin.Current);\r
- } else {\r
- byte[] tmp = new byte[8192];\r
-\r
- for (long i = 0; i < len; ){\r
- long left = len - i;\r
- int count = left < 8192 ? ((int) left) : 8192;\r
- \r
- baseInputStream.Read (tmp, 0, count);\r
- i += count;\r
- }\r
+ byte[] tmp = new byte[len];\r
+ return (long)baseInputStream.Read(tmp, 0, tmp.Length);\r
+ }\r
+ \r
+ #region Encryption stuff\r
+ protected byte[] cryptbuffer = null;\r
+ \r
+ uint[] keys = null;\r
+ protected byte DecryptByte()\r
+ {\r
+ uint temp = ((keys[2] & 0xFFFF) | 2);\r
+ return (byte)((temp * (temp ^ 1)) >> 8);\r
+ }\r
+ \r
+ protected void DecryptBlock(byte[] buf, int off, int len)\r
+ {\r
+ for (int i = off; i < off + len; ++i) {\r
+ buf[i] ^= DecryptByte();\r
+ UpdateKeys(buf[i]);\r
}\r
- return (long) len;\r
}\r
+ \r
+ protected void InitializePassword(string password)\r
+ {\r
+ keys = new uint[] {\r
+ 0x12345678,\r
+ 0x23456789,\r
+ 0x34567890\r
+ };\r
+ for (int i = 0; i < password.Length; ++i) {\r
+ UpdateKeys((byte)password[i]);\r
+ }\r
+ }\r
+ \r
+ protected void UpdateKeys(byte ch)\r
+ {\r
+ keys[0] = Crc32.ComputeCrc32(keys[0], ch);\r
+ keys[1] = keys[1] + (byte)keys[0];\r
+ keys[1] = keys[1] * 134775813 + 1;\r
+ keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24));\r
+ }\r
+ #endregion\r
}\r
}\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams \r
+{\r
\r
/// <summary>\r
/// Contains the output from the Inflation process.\r
private static int WINDOW_MASK = WINDOW_SIZE - 1;\r
\r
private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes\r
- private int window_end = 0;\r
- private int window_filled = 0;\r
+ private int windowEnd = 0;\r
+ private int windowFilled = 0;\r
\r
public void Write(int abyte)\r
{\r
- if (window_filled++ == WINDOW_SIZE) {\r
+ if (windowFilled++ == WINDOW_SIZE) {\r
throw new InvalidOperationException("Window full");\r
}\r
- window[window_end++] = (byte) abyte;\r
- window_end &= WINDOW_MASK;\r
+ window[windowEnd++] = (byte) abyte;\r
+ windowEnd &= WINDOW_MASK;\r
}\r
\r
\r
- private void SlowRepeat(int rep_start, int len, int dist)\r
+ private void SlowRepeat(int repStart, int len, int dist)\r
{\r
while (len-- > 0) {\r
- window[window_end++] = window[rep_start++];\r
- window_end &= WINDOW_MASK;\r
- rep_start &= WINDOW_MASK;\r
+ window[windowEnd++] = window[repStart++];\r
+ windowEnd &= WINDOW_MASK;\r
+ repStart &= WINDOW_MASK;\r
}\r
}\r
\r
public void Repeat(int len, int dist)\r
{\r
- if ((window_filled += len) > WINDOW_SIZE) {\r
+ if ((windowFilled += len) > WINDOW_SIZE) {\r
throw new InvalidOperationException("Window full");\r
}\r
\r
- int rep_start = (window_end - dist) & WINDOW_MASK;\r
+ int rep_start = (windowEnd - dist) & WINDOW_MASK;\r
int border = WINDOW_SIZE - len;\r
- if (rep_start <= border && window_end < border) {\r
+ if (rep_start <= border && windowEnd < border) {\r
if (len <= dist) {\r
- System.Array.Copy(window, rep_start, window, window_end, len);\r
- window_end += len;\r
- } else {\r
+ System.Array.Copy(window, rep_start, window, windowEnd, len);\r
+ windowEnd += len;\r
+ } else {\r
/* We have to copy manually, since the repeat pattern overlaps.\r
*/\r
while (len-- > 0) {\r
- window[window_end++] = window[rep_start++];\r
+ window[windowEnd++] = window[rep_start++];\r
}\r
}\r
} else {\r
\r
public int CopyStored(StreamManipulator input, int len)\r
{\r
- len = Math.Min(Math.Min(len, WINDOW_SIZE - window_filled), input.AvailableBytes);\r
+ len = Math.Min(Math.Min(len, WINDOW_SIZE - windowFilled), input.AvailableBytes);\r
int copied;\r
\r
- int tailLen = WINDOW_SIZE - window_end;\r
+ int tailLen = WINDOW_SIZE - windowEnd;\r
if (len > tailLen) {\r
- copied = input.CopyBytes(window, window_end, tailLen);\r
+ copied = input.CopyBytes(window, windowEnd, tailLen);\r
if (copied == tailLen) {\r
copied += input.CopyBytes(window, 0, len - tailLen);\r
}\r
} else {\r
- copied = input.CopyBytes(window, window_end, len);\r
+ copied = input.CopyBytes(window, windowEnd, len);\r
}\r
\r
- window_end = (window_end + copied) & WINDOW_MASK;\r
- window_filled += copied;\r
+ windowEnd = (windowEnd + copied) & WINDOW_MASK;\r
+ windowFilled += copied;\r
return copied;\r
}\r
\r
public void CopyDict(byte[] dict, int offset, int len)\r
{\r
- if (window_filled > 0) {\r
+ if (windowFilled > 0) {\r
throw new InvalidOperationException();\r
}\r
\r
len = WINDOW_SIZE;\r
}\r
System.Array.Copy(dict, offset, window, 0, len);\r
- window_end = len & WINDOW_MASK;\r
+ windowEnd = len & WINDOW_MASK;\r
}\r
\r
public int GetFreeSpace()\r
{\r
- return WINDOW_SIZE - window_filled;\r
+ return WINDOW_SIZE - windowFilled;\r
}\r
\r
public int GetAvailable()\r
{\r
- return window_filled;\r
+ return windowFilled;\r
}\r
\r
public int CopyOutput(byte[] output, int offset, int len)\r
{\r
- int copy_end = window_end;\r
- if (len > window_filled) {\r
- len = window_filled;\r
+ int copy_end = windowEnd;\r
+ if (len > windowFilled) {\r
+ len = windowFilled;\r
} else {\r
- copy_end = (window_end - window_filled + len) & WINDOW_MASK;\r
+ copy_end = (windowEnd - windowFilled + len) & WINDOW_MASK;\r
}\r
\r
int copied = len;\r
int tailLen = len - copy_end;\r
\r
if (tailLen > 0) {\r
- System.Array.Copy(window, WINDOW_SIZE - tailLen,\r
- output, offset, tailLen);\r
+ System.Array.Copy(window, WINDOW_SIZE - tailLen, output, offset, tailLen);\r
offset += tailLen;\r
len = copy_end;\r
}\r
System.Array.Copy(window, copy_end - len, output, offset, len);\r
- window_filled -= copied;\r
- if (window_filled < 0) {\r
+ windowFilled -= copied;\r
+ if (windowFilled < 0) {\r
throw new InvalidOperationException();\r
}\r
return copied;\r
\r
public void Reset()\r
{\r
- window_filled = window_end = 0;\r
+ windowFilled = windowEnd = 0;\r
}\r
}\r
}\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams {\r
+namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams \r
+{\r
\r
/// <summary>\r
/// This class allows us to retrieve a specified amount of bits from\r
{\r
if (bits_in_buffer < n) {\r
if (window_start == window_end) {\r
- return -1;\r
+ return -1; // ok\r
}\r
buffer |= (uint)((window[window_start++] & 0xff |\r
(window[window_start++] & 0xff) << 8) << bits_in_buffer);\r
if (length < 0) {\r
throw new ArgumentOutOfRangeException("length negative");\r
}\r
- if ((bits_in_buffer & 7) != 0) {\r
+ if ((bits_in_buffer & 7) != 0) {\r
/* bits_in_buffer may only be 0 or 8 */\r
throw new InvalidOperationException("Bit buffer is not aligned!");\r
}\r
\r
using System.Text;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip {\r
+namespace ICSharpCode.SharpZipLib.Zip \r
+{\r
\r
/// <summary>\r
/// This class contains constants used for zip.\r
public const int LOCNAM = 26;\r
public const int LOCEXT = 28;\r
\r
+ public const int SPANNINGSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24);\r
+ public const int SPANTEMPSIG = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24);\r
+ \r
/* The Data descriptor */\r
public const int EXTSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24);\r
public const int EXTHDR = 16;\r
public const int CENSIG = 'P' | ('K' << 8) | (1 << 16) | (2 << 24);\r
\r
/* The central directory file header for 64bit ZIP*/\r
- public const int CENSIG64 = 0x06064b50;\r
+ public const int CENSIG64 = 'P' | ('K' << 8) | (6 << 16) | (6 << 24);\r
\r
public const int CENHDR = 46;\r
\r
public const int ENDSIG = 'P' | ('K' << 8) | (5 << 16) | (6 << 24);\r
public const int ENDHDR = 22;\r
\r
+ public const int HDRDIGITALSIG = 'P' | ('K' << 8) | (5 << 16) | (5 << 24);\r
+ public const int CENDIGITALSIG = 'P' | ('K' << 8) | (5 << 16) | (5 << 24);\r
+ \r
/* The following two fields are missing in SUN JDK */\r
public const int ENDNRD = 4;\r
public const int ENDDCD = 6;\r
public const int ENDOFF = 16;\r
public const int ENDCOM = 20;\r
\r
- /* Using the codepage 1252 doesn't solve the 8bit ASCII problem :/\r
- any help would be appreciated.\r
- \r
- // get encoding for latin characters (like ö, ü, ß or ô)\r
- static Encoding ecp1252 = Encoding.GetEncoding(1252);\r
- */\r
+ \r
+ static int defaultCodePage = 0; // 0 gives default code page, set it to whatever you like or alternatively alter it via property at runtime for more flexibility\r
+ // Some care for compatability purposes is required as you can specify unicode code pages here.... if this way of working seems ok\r
+ // then some protection may be added to make the interface a bit more robust perhaps.\r
+ \r
+ public static int DefaultCodePage {\r
+ get {\r
+ return defaultCodePage; \r
+ }\r
+ set {\r
+ defaultCodePage = value; \r
+ }\r
+ }\r
+ \r
public static string ConvertToString(byte[] data)\r
{\r
- \r
- return Encoding.ASCII.GetString(data);\r
+#if COMACT_FRAMEWORK \r
+ return Encoding.ASCII.GetString(data,0, data.Length);\r
+#else\r
+ return Encoding.GetEncoding(DefaultCodePage).GetString(data, 0, data.Length);\r
+#endif\r
}\r
\r
public static byte[] ConvertToArray(string str)\r
{\r
+#if COMACT_FRAMEWORK \r
return Encoding.ASCII.GetBytes(str);\r
+#else\r
+ return Encoding.GetEncoding(DefaultCodePage).GetBytes(str);\r
+#endif\r
}\r
}\r
}\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip {\r
+namespace ICSharpCode.SharpZipLib.Zip \r
+{\r
\r
public enum CompressionMethod\r
{\r
static int KNOWN_CRC = 4;\r
static int KNOWN_TIME = 8;\r
\r
- DateTime cal = DateTime.Now;\r
- \r
string name;\r
uint size;\r
ushort version;\r
uint compressedSize;\r
- int crc;\r
+ uint crc;\r
+ uint dosTime;\r
\r
ushort known = 0;\r
CompressionMethod method = CompressionMethod.Deflated;\r
byte[] extra = null;\r
string comment = null;\r
+ bool isCrypted;\r
+ \r
+ int zipFileIndex = -1; /* used by ZipFile */\r
+ int flags; /* used by ZipOutputStream */\r
+ int offset; /* used by ZipFile and ZipOutputStream */\r
+ \r
+ public bool IsEncrypted {\r
+ get {\r
+ return (flags & 1) != 0; \r
+ }\r
+ set {\r
+ if (value) {\r
+ flags |= 1;\r
+ } else {\r
+ flags &= ~1;\r
+ }\r
+ }\r
+ }\r
+ \r
+ public int ZipFileIndex {\r
+ get {\r
+ return zipFileIndex;\r
+ }\r
+ set {\r
+ zipFileIndex = value;\r
+ }\r
+ }\r
+ \r
+ public int Offset {\r
+ get {\r
+ return offset;\r
+ }\r
+ set {\r
+ offset = value;\r
+ }\r
+ }\r
+ \r
+ public int Flags { // Stops having two things represent same concept in class (flag isCrypted removed)\r
+ get { \r
+ return flags; \r
+ }\r
+ set {\r
+ flags = value; \r
+ }\r
+ }\r
\r
- public int zipFileIndex = -1; /* used by ZipFile */\r
- public int flags; /* used by ZipOutputStream */\r
- public int offset; /* used by ZipFile and ZipOutputStream */\r
\r
/// <summary>\r
/// Creates a zip entry with the given name.\r
/// </param>\r
public ZipEntry(string name)\r
{\r
- if (name == null) {\r
+ if (name == null) {\r
throw new System.ArgumentNullException("name");\r
}\r
+ this.DateTime = System.DateTime.Now;\r
this.name = name;\r
}\r
\r
/// </param>\r
public ZipEntry(ZipEntry e)\r
{\r
- name = e.name;\r
- known = e.known;\r
- size = e.size;\r
+ name = e.name;\r
+ known = e.known;\r
+ size = e.size;\r
compressedSize = e.compressedSize;\r
- crc = e.crc;\r
-// time = e.time;\r
- method = e.method;\r
- extra = e.extra;\r
- comment = e.comment;\r
+ crc = e.crc;\r
+ dosTime = e.dosTime;\r
+ method = e.method;\r
+ extra = e.extra;\r
+ comment = e.comment;\r
}\r
\r
- public ushort Version {\r
+ public int Version {\r
get {\r
return version;\r
}\r
set {\r
- version = value;\r
+ version = (ushort)value;\r
}\r
}\r
\r
- public int DosTime {\r
+ public long DosTime {\r
get {\r
-// if ((known & KNOWN_TIME) == 0) {\r
-// return 0;\r
-// }\r
- lock (this) {\r
- return (cal.Year - 1980 & 0x7f) << 25 |\r
- (cal.Month + 1) << 21 | \r
- (cal.Day ) << 16 | \r
- (cal.Hour) << 11 |\r
- (cal.Minute) << 5 |\r
- (cal.Second) >> 1;\r
+ if ((known & KNOWN_TIME) == 0) {\r
+ return 0;\r
+ } else {\r
+ return dosTime;\r
}\r
}\r
set {\r
- // Guard against invalid or missing date causing\r
- // IndexOutOfBoundsException.\r
- try {\r
- lock (this) {\r
- cal = CalculateDateTime(value);\r
-// time = (int) (cal.Millisecond / 1000L);\r
- }\r
- known |= (ushort)KNOWN_TIME;\r
- } catch (Exception) {\r
- /* Ignore illegal time stamp */\r
- known &= (ushort)~KNOWN_TIME;\r
- }\r
+ this.dosTime = (uint)value;\r
+ known |= (ushort)KNOWN_TIME;\r
}\r
}\r
\r
+ \r
/// <summary>\r
/// Gets/Sets the time of last modification of the entry.\r
/// </summary>\r
public DateTime DateTime {\r
get {\r
- return cal;\r
+ uint sec = 2 * (dosTime & 0x1f);\r
+ uint min = (dosTime >> 5) & 0x3f;\r
+ uint hrs = (dosTime >> 11) & 0x1f;\r
+ uint day = (dosTime >> 16) & 0x1f;\r
+ uint mon = ((dosTime >> 21) & 0xf);\r
+ uint year = ((dosTime >> 25) & 0x7f) + 1980; /* since 1900 */\r
+ return new System.DateTime((int)year, (int)mon, (int)day, (int)hrs, (int)min, (int)sec);\r
}\r
set {\r
- lock (this) {\r
- cal = value;\r
-// time = (int) (cal.Millisecond / 1000L); \r
- }\r
- known |= (ushort)KNOWN_TIME;\r
+ DosTime = ((uint)value.Year - 1980 & 0x7f) << 25 | \r
+ ((uint)value.Month) << 21 |\r
+ ((uint)value.Day) << 16 |\r
+ ((uint)value.Hour) << 11 |\r
+ ((uint)value.Minute) << 5 |\r
+ ((uint)value.Second) >> 1;\r
}\r
}\r
- \r
+ \r
/// <summary>\r
/// Returns the entry name. The path components in the entry are\r
/// always separated by slashes ('/').\r
}\r
}\r
\r
-// /// <summary>\r
-// /// Gets/Sets the time of last modification of the entry.\r
-// /// </summary>\r
-// /// <returns>\r
-// /// the time of last modification of the entry, or -1 if unknown.\r
-// /// </returns>\r
-// public long Time {\r
-// get {\r
-// return (known & KNOWN_TIME) != 0 ? time * 1000L : -1;\r
-// }\r
-// set {\r
-// this.time = (int) (value / 1000L);\r
-// this.known |= (ushort)KNOWN_TIME;\r
-// }\r
-// }\r
+ // /// <summary>\r
+ // /// Gets/Sets the time of last modification of the entry.\r
+ // /// </summary>\r
+ // /// <returns>\r
+ // /// the time of last modification of the entry, or -1 if unknown.\r
+ // /// </returns>\r
+ // public long Time {\r
+ // get {\r
+ // return (known & KNOWN_TIME) != 0 ? time * 1000L : -1;\r
+ // }\r
+ // set {\r
+ // this.time = (int) (value / 1000L);\r
+ // this.known |= (ushort)KNOWN_TIME;\r
+ // }\r
+ // }\r
\r
/// <summary>\r
/// Gets/Sets the size of the uncompressed data.\r
get {\r
return (known & KNOWN_SIZE) != 0 ? (long)size : -1L;\r
}\r
- set {\r
+ set {\r
if (((ulong)value & 0xFFFFFFFF00000000L) != 0) {\r
throw new ArgumentOutOfRangeException("size");\r
}\r
return (known & KNOWN_CRC) != 0 ? crc & 0xffffffffL : -1L;\r
}\r
set {\r
- if (((ulong)crc & 0xffffffff00000000L) != 0) {\r
+ if (((ulong)crc & 0xffffffff00000000L) != 0) \r
+ {\r
throw new Exception();\r
}\r
- this.crc = (int)value;\r
+ this.crc = (uint)value;\r
this.known |= (ushort)KNOWN_CRC;\r
}\r
}\r
return method;\r
}\r
set {\r
- this.method = value;\r
+ this.method = value;\r
}\r
}\r
\r
/* extended time stamp, unix format by Rainer Prem <Rainer@Prem.de> */\r
int flags = extra[pos];\r
if ((flags & 1) != 0) {\r
- int iTime = ((extra[pos+1] & 0xff) |\r
- (extra[pos+2] & 0xff) << 8 |\r
- (extra[pos+3] & 0xff) << 16 |\r
- (extra[pos+4] & 0xff) << 24);\r
+ int iTime = ((extra[pos+1] & 0xff) |\r
+ (extra[pos+2] & 0xff) << 8 |\r
+ (extra[pos+3] & 0xff) << 16 |\r
+ (extra[pos+4] & 0xff) << 24);\r
\r
- cal = (new DateTime ( 1970, 1, 1, 0, 0, 0 ) + \r
- new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime ();\r
+ DateTime = (new DateTime ( 1970, 1, 1, 0, 0, 0 ) + new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime ();\r
known |= (ushort)KNOWN_TIME;\r
}\r
}\r
return comment;\r
}\r
set {\r
- if (value.Length > 0xffff) {\r
+ if (value.Length > 0xffff) \r
+ {\r
throw new ArgumentOutOfRangeException();\r
}\r
this.comment = value;\r
}\r
}\r
\r
+ /// <value>\r
+ /// True, if the entry is encrypted.\r
+ /// </value>\r
+ public bool IsCrypted {\r
+ get {\r
+ return isCrypted;\r
+ }\r
+ set {\r
+ isCrypted = value;\r
+ }\r
+ }\r
+ \r
/// <summary>\r
/// Creates a copy of this zip entry.\r
/// </summary>\r
{\r
return name;\r
}\r
- \r
- DateTime CalculateDateTime(int dosTime)\r
- {\r
- int sec = 2 * (dosTime & 0x1f);\r
- int min = (dosTime >> 5) & 0x3f;\r
- int hrs = (dosTime >> 11) & 0x1f;\r
- int day = (dosTime >> 16) & 0x1f;\r
- int mon = ((dosTime >> 21) & 0xf);\r
- int year = ((dosTime >> 25) & 0x7f) + 1980; /* since 1900 */\r
- \r
- return new DateTime(year, mon, day, hrs, min, sec);\r
- }\r
- \r
}\r
}\r
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;\r
using ICSharpCode.SharpZipLib.Zip.Compression;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip {\r
+namespace ICSharpCode.SharpZipLib.Zip \r
+{\r
\r
/// <summary>\r
/// This class represents a Zip archive. You can ask for the contained\r
/// static public void Main(string[] args)\r
/// {\r
/// ZipFile zFile = new ZipFile(args[0]);\r
- /// Console.WriteLine("Listing of : " + zFile.Name);\r
- /// Console.WriteLine("");\r
- /// Console.WriteLine("Raw Size Size Date Time Name");\r
- /// Console.WriteLine("-------- -------- -------- ------ ---------");\r
+ /// //Console.WriteLine("Listing of : " + zFile.Name);\r
+ /// //Console.WriteLine("");\r
+ /// //Console.WriteLine("Raw Size Size Date Time Name");\r
+ /// //Console.WriteLine("-------- -------- -------- ------ ---------");\r
/// foreach (ZipEntry e in zFile) {\r
/// DateTime d = e.DateTime;\r
- /// Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize,\r
+ /// //Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize,\r
/// d.ToString("dd-MM-yy"), d.ToString("t"),\r
/// e.Name);\r
/// }\r
public class ZipFile : IEnumerable\r
{\r
string name;\r
+ string comment;\r
Stream baseStream;\r
ZipEntry[] entries;\r
\r
\r
int centralOffset = ReadLeInt();\r
\r
+ // GET COMMENT SIZE (COMES AFTER CENTRALOFFSET) \r
+ int commentSize = ReadLeShort(); \r
+ byte[] zipComment = new byte[commentSize]; \r
+ baseStream.Read(zipComment, 0, zipComment.Length); \r
+ comment = ZipConstants.ConvertToString(zipComment); \r
+ \r
entries = new ZipEntry[count];\r
baseStream.Seek(centralOffset, SeekOrigin.Begin);\r
for (int i = 0; i < count; i++) {\r
entry.Crc = crc & 0xffffffffL;\r
entry.Size = size & 0xffffffffL;\r
entry.CompressedSize = csize & 0xffffffffL;\r
- entry.DosTime = dostime;\r
+ entry.DosTime = (uint)dostime;\r
if (extraLen > 0) {\r
byte[] extra = new byte[extraLen];\r
baseStream.Read(extra, 0, extraLen);\r
baseStream.Read(buffer, 0, commentLen);\r
entry.Comment = ZipConstants.ConvertToString(buffer);\r
}\r
- entry.zipFileIndex = i;\r
- entry.offset = offset;\r
+ entry.ZipFileIndex = i;\r
+ entry.Offset = offset;\r
entries[i] = entry;\r
}\r
}\r
return i;\r
}\r
}\r
- return -1;\r
+ return -1; // ok\r
}\r
\r
/// <summary>\r
long CheckLocalHeader(ZipEntry entry)\r
{\r
lock(baseStream) {\r
- baseStream.Seek(entry.offset, SeekOrigin.Begin);\r
+ baseStream.Seek(entry.Offset, SeekOrigin.Begin);\r
if (ReadLeInt() != ZipConstants.LOCSIG) {\r
throw new ZipException("Wrong Local header signature");\r
}\r
}\r
\r
int extraLen = entry.Name.Length + ReadLeShort();\r
- return entry.offset + ZipConstants.LOCHDR + extraLen;\r
+ return entry.Offset + ZipConstants.LOCHDR + extraLen;\r
}\r
}\r
\r
throw new InvalidOperationException("ZipFile has closed");\r
}\r
\r
- int index = entry.zipFileIndex;\r
+ int index = entry.ZipFileIndex;\r
if (index < 0 || index >= entries.Length || entries[index].Name != entry.Name) {\r
index = GetEntryIndex(entry.Name);\r
if (index < 0) {\r
}\r
}\r
\r
+ /// <summary>\r
+ /// The comment for the whole zip file.\r
+ /// </summary>\r
+ public string ZipFileComment {\r
+ get {\r
+ return comment;\r
+ }\r
+ }\r
+ \r
/// <summary>\r
/// Returns the name of this zip file.\r
/// </summary>\r
end = start + len;\r
}\r
\r
- public override int Available {\r
+ public override int Available \r
+ {\r
get {\r
long amount = end - filepos;\r
if (amount > Int32.MaxValue) {\r
public override int ReadByte()\r
{\r
if (filepos == end) {\r
- return -1;\r
+ return -1; //ok\r
}\r
+ \r
lock(baseStream) {\r
baseStream.Seek(filepos++, SeekOrigin.Begin);\r
return baseStream.ReadByte();\r
if (len > end - filepos) {\r
len = (int) (end - filepos);\r
if (len == 0) {\r
- return -1;\r
+ return 0;\r
}\r
}\r
lock(baseStream) {\r
using ICSharpCode.SharpZipLib.Zip.Compression;\r
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip {\r
- \r
+namespace ICSharpCode.SharpZipLib.Zip \r
+{\r
/// <summary>\r
/// This is a FilterInputStream that reads the files baseInputStream an zip archive\r
/// one after another. It has a special method to get the zip entry of\r
/// author of the original java version : Jochen Hoenicke\r
/// </summary>\r
/// <example> This sample shows how to read a zip file\r
- /// <code>\r
+ /// <code lang="C#">\r
/// using System;\r
/// using System.Text;\r
/// using System.IO;\r
/// \r
/// ZipEntry theEntry;\r
/// while ((theEntry = s.GetNextEntry()) != null) {\r
- /// Console.WriteLine("File " + theEntry.Name);\r
/// int size = 2048;\r
/// byte[] data = new byte[2048];\r
/// \r
/// }\r
/// }\r
/// }\r
- /// Console.WriteLine();\r
/// }\r
/// s.Close();\r
/// }\r
/// </example>\r
public class ZipInputStream : InflaterInputStream\r
{\r
- private Crc32 crc = new Crc32();\r
- private ZipEntry entry = null;\r
+ Crc32 crc = new Crc32();\r
+ ZipEntry entry = null;\r
\r
- private long csize;\r
- private long size;\r
- private int method;\r
- private int flags;\r
- private long avail;\r
+ long size;\r
+ int method;\r
+ int flags;\r
+ long avail;\r
+ string password = null;\r
+ \r
+ public string Password {\r
+ get {\r
+ return password;\r
+ }\r
+ set {\r
+ password = value;\r
+ }\r
+ }\r
\r
/// <summary>\r
/// Creates a new Zip input stream, reading a zip archive.\r
/// </summary>\r
public ZipInputStream(Stream baseInputStream) : base(baseInputStream, new Inflater(true))\r
{\r
- \r
}\r
\r
- private void FillBuf()\r
+ void FillBuf()\r
{\r
avail = len = baseInputStream.Read(buf, 0, buf.Length);\r
}\r
\r
- private int ReadBuf(byte[] outBuf, int offset, int length)\r
+ int ReadBuf(byte[] outBuf, int offset, int length)\r
{\r
if (avail <= 0) {\r
FillBuf();\r
if (avail <= 0) {\r
- return -1;\r
+ return 0;\r
}\r
}\r
if (length > avail) {\r
return length;\r
}\r
\r
- private void ReadFully(byte[] outBuf)\r
+ void ReadFully(byte[] outBuf)\r
{\r
int off = 0;\r
int len = outBuf.Length;\r
}\r
}\r
\r
- private int ReadLeByte()\r
+ int ReadLeByte()\r
{\r
if (avail <= 0) {\r
FillBuf();\r
/// <summary>\r
/// Read an unsigned short baseInputStream little endian byte order.\r
/// </summary>\r
- private int ReadLeShort()\r
+ int ReadLeShort()\r
{\r
return ReadLeByte() | (ReadLeByte() << 8);\r
}\r
/// <summary>\r
/// Read an int baseInputStream little endian byte order.\r
/// </summary>\r
- private int ReadLeInt()\r
+ int ReadLeInt()\r
{\r
return ReadLeShort() | (ReadLeShort() << 16);\r
}\r
/// <summary>\r
/// Read an int baseInputStream little endian byte order.\r
/// </summary>\r
- private long ReadLeLong()\r
+ long ReadLeLong()\r
{\r
return ReadLeInt() | (ReadLeInt() << 32);\r
}\r
CloseEntry();\r
}\r
\r
+ if (this.cryptbuffer != null) {\r
+ if (avail == 0 && inf.RemainingInput != 0) {\r
+ avail = inf.RemainingInput - 16;\r
+ inf.Reset();\r
+ }\r
+ baseInputStream.Position -= this.len;\r
+ baseInputStream.Read(this.buf, 0, this.len);\r
+ }\r
+ \r
int header = ReadLeInt();\r
- if (header == ZipConstants.CENSIG) {\r
- /* Central Header reached. */\r
+ \r
+ // -jr- added end sig for empty zip files, Zip64 end sig and digital sig for files that have them...\r
+ if (header == ZipConstants.CENSIG || \r
+ header == ZipConstants.ENDSIG || \r
+ header == ZipConstants.CENDIGITALSIG || \r
+ header == ZipConstants.CENSIG64) {\r
+ // Central Header reached or end of empty zip file\r
Close();\r
return null;\r
}\r
+ // -jr- 07-Dec-2003 ignore spanning temporary signatures if found\r
+ // SPANNINGSIG is same as descriptor signature and is untested as yet.\r
+ if (header == ZipConstants.SPANTEMPSIG || header == ZipConstants.SPANNINGSIG) {\r
+ header = ReadLeInt();\r
+ }\r
+ \r
if (header != ZipConstants.LOCSIG) {\r
- throw new ZipException("Wrong Local header signature" + header);\r
+ throw new ZipException("Wrong Local header signature: 0x" + String.Format("{0:X}", header));\r
}\r
\r
short version = (short)ReadLeShort();\r
\r
flags = ReadLeShort();\r
method = ReadLeShort();\r
- int dostime = ReadLeInt();\r
+ uint dostime = (uint)ReadLeInt();\r
int crc2 = ReadLeInt();\r
csize = ReadLeInt();\r
size = ReadLeInt();\r
int nameLen = ReadLeShort();\r
int extraLen = ReadLeShort();\r
- \r
- if (method == ZipOutputStream.STORED && csize != size) {\r
+ bool isCrypted = (flags & 1) == 1;\r
+ if (method == ZipOutputStream.STORED && (!isCrypted && csize != size || (isCrypted && csize - 12 != size))) {\r
throw new ZipException("Stored, but compressed != uncompressed");\r
}\r
\r
string name = ZipConstants.ConvertToString(buffer);\r
\r
entry = new ZipEntry(name);\r
- \r
+ entry.IsCrypted = isCrypted;\r
entry.Version = (ushort)version;\r
if (method != 0 && method != 8) {\r
throw new ZipException("unknown compression method " + method);\r
entry.Size = size & 0xFFFFFFFFL;\r
entry.CompressedSize = csize & 0xFFFFFFFFL;\r
}\r
+ \r
entry.DosTime = dostime;\r
+ \r
if (extraLen > 0) {\r
byte[] extra = new byte[extraLen];\r
ReadFully(extra);\r
entry.ExtraData = extra;\r
}\r
\r
+ // test for encryption\r
+ if (isCrypted) {\r
+ if (password == null) {\r
+ throw new ZipException("No password set.");\r
+ }\r
+ InitializePassword(password);\r
+ cryptbuffer = new byte[12];\r
+ ReadFully(cryptbuffer);\r
+ DecryptBlock(cryptbuffer, 0, cryptbuffer.Length);\r
+ if ((flags & 8) == 0) {// -jr- 10-Feb-2004 Dont yet know correct size here....\r
+ csize -= 12;\r
+ }\r
+ } else {\r
+ cryptbuffer = null;\r
+ }\r
+ \r
if (method == ZipOutputStream.DEFLATED && avail > 0) {\r
System.Array.Copy(buf, len - (int)avail, buf, 0, (int)avail);\r
len = (int)avail;\r
avail = 0;\r
+ if (isCrypted) {\r
+ DecryptBlock(buf, 0, Math.Min((int)csize, len));\r
+ }\r
inf.SetInput(buf, 0, len);\r
}\r
+ \r
return entry;\r
}\r
- \r
private void ReadDataDescr()\r
{\r
if (ReadLeInt() != ZipConstants.EXTSIG) {\r
if (crc == null) {\r
throw new InvalidOperationException("Closed.");\r
}\r
+ \r
if (entry == null) {\r
return;\r
}\r
{\r
byte[] b = new byte[1];\r
if (Read(b, 0, 1) <= 0) {\r
- return -1;\r
+ return -1; // ok\r
}\r
return b[0] & 0xff;\r
}\r
if (crc == null) {\r
throw new InvalidOperationException("Closed.");\r
}\r
+ \r
if (entry == null) {\r
- return -1;\r
+ return 0;\r
}\r
bool finished = false;\r
\r
switch (method) {\r
case ZipOutputStream.DEFLATED:\r
len = base.Read(b, off, len);\r
- if (len < 0) {\r
+ if (len <= 0) { // TODO BUG1 -jr- Check this was < 0 but avail was not adjusted causing failure in later calls\r
if (!inf.IsFinished) {\r
throw new ZipException("Inflater not finished!?");\r
}\r
avail = inf.RemainingInput;\r
- if ((flags & 8) != 0) {\r
- ReadDataDescr();\r
- }\r
\r
- if (inf.TotalIn != csize || inf.TotalOut != size) {\r
+ // BUG1 -jr- With bit 3 set you dont yet know the size\r
+ if ((flags & 8) == 0 && (inf.TotalIn != csize || inf.TotalOut != size)) {\r
throw new ZipException("size mismatch: " + csize + ";" + size + " <-> " + inf.TotalIn + ";" + inf.TotalOut);\r
}\r
inf.Reset();\r
break;\r
\r
case ZipOutputStream.STORED:\r
- \r
if (len > csize && csize >= 0) {\r
len = (int)csize;\r
}\r
throw new ZipException("EOF in stored block");\r
}\r
}\r
+ \r
+ // decrypting crypted data\r
+ if (cryptbuffer != null) {\r
+ DecryptBlock(b, off, len);\r
+ }\r
+ \r
break;\r
}\r
- \r
+ \r
if (len > 0) {\r
crc.Update(b, off, len);\r
}\r
\r
if (finished) {\r
- if ((crc.Value & 0xFFFFFFFFL) != entry.Crc) {\r
+ if ((flags & 8) != 0) {\r
+ ReadDataDescr();\r
+ }\r
+ \r
+ if ((crc.Value & 0xFFFFFFFFL) != entry.Crc && entry.Crc != -1) {\r
throw new ZipException("CRC mismatch");\r
}\r
crc.Reset();\r
crc = null;\r
entry = null;\r
}\r
+ \r
}\r
}\r
using ICSharpCode.SharpZipLib.Zip.Compression;\r
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;\r
\r
-namespace ICSharpCode.SharpZipLib.Zip {\r
- \r
+namespace ICSharpCode.SharpZipLib.Zip \r
+{\r
/// <summary>\r
/// This is a FilterOutputStream that writes the files into a zip\r
/// archive one after another. It has a special method to start a new\r
private byte[] zipComment = new byte[0];\r
private int defaultMethod = DEFLATED;\r
\r
- \r
/// <summary>\r
/// Our Zip version is hard coded to 1.0 resp. 2.0\r
/// </summary>\r
\r
\r
bool shouldWriteBack = false;\r
+ // -jr- Having a hard coded flag for seek capability requires this so users can determine\r
+ // if the entries will be patched or not.\r
+ public bool CanPatchEntries {\r
+ get { \r
+ return baseOutputStream.CanSeek; \r
+ }\r
+ }\r
+ \r
long seekPos = -1;\r
/// <summary>\r
/// Starts a new Zip entry. It automatically closes the previous\r
\r
CompressionMethod method = entry.CompressionMethod;\r
int flags = 0;\r
- \r
+ entry.IsCrypted = Password != null;\r
switch (method) {\r
case CompressionMethod.Stored:\r
if (entry.CompressedSize >= 0) {\r
entry.CompressedSize = entry.Size;\r
}\r
\r
+ if (entry.IsCrypted) {\r
+ entry.CompressedSize += 12;\r
+ }\r
+ \r
if (entry.Size < 0) {\r
throw new ZipException("Method STORED, but size not set");\r
} else if (entry.Crc < 0) {\r
CloseEntry();\r
}\r
\r
-// if (entry.DosTime < 0) {\r
-// entry.Time = System.Environment.TickCount;\r
-// }\r
- \r
- entry.flags = flags;\r
- entry.offset = offset;\r
+ // if (entry.DosTime < 0) {\r
+ // entry.Time = System.Environment.TickCount;\r
+ // }\r
+ if (entry.IsCrypted) {\r
+ flags |= 1;\r
+ }\r
+ entry.Flags = flags;\r
+ entry.Offset = offset;\r
entry.CompressionMethod = (CompressionMethod)method;\r
\r
curMethod = method;\r
if ((flags & 8) == 0) {\r
WriteLeShort(flags);\r
WriteLeShort((byte)method);\r
- WriteLeInt(entry.DosTime);\r
+ WriteLeInt((int)entry.DosTime);\r
WriteLeInt((int)entry.Crc);\r
WriteLeInt((int)entry.CompressedSize);\r
WriteLeInt((int)entry.Size);\r
WriteLeShort(flags);\r
}\r
WriteLeShort((byte)method);\r
- WriteLeInt(entry.DosTime);\r
- seekPos = baseOutputStream.Position;\r
+ WriteLeInt((int)entry.DosTime);\r
+ if (baseOutputStream.CanSeek) {\r
+ seekPos = baseOutputStream.Position;\r
+ }\r
WriteLeInt(0);\r
WriteLeInt(0);\r
WriteLeInt(0);\r
baseOutputStream.Write(name, 0, name.Length);\r
baseOutputStream.Write(extra, 0, extra.Length);\r
\r
+ if (Password != null) {\r
+ InitializePassword(Password);\r
+ byte[] cryptbuffer = new byte[12];\r
+ Random rnd = new Random();\r
+ for (int i = 0; i < cryptbuffer.Length; ++i) {\r
+ cryptbuffer[i] = (byte)rnd.Next();\r
+ }\r
+ EncryptBlock(cryptbuffer, 0, cryptbuffer.Length);\r
+ baseOutputStream.Write(cryptbuffer, 0, cryptbuffer.Length);\r
+ }\r
offset += ZipConstants.LOCHDR + name.Length + extra.Length;\r
\r
/* Activate the entry. */\r
if (curEntry.Size < 0) {\r
curEntry.Size = size;\r
} else if (curEntry.Size != size) {\r
- throw new ZipException("size was " + size +\r
- ", but I expected " + curEntry.Size);\r
+ throw new ZipException("size was " + size + ", but I expected " + curEntry.Size);\r
+ }\r
+ \r
+ if (curEntry.IsCrypted) {\r
+ csize += 12;\r
}\r
\r
if (curEntry.CompressedSize < 0) {\r
curEntry.CompressedSize = csize;\r
} else if (curEntry.CompressedSize != csize) {\r
- throw new ZipException("compressed size was " + csize + \r
- ", but I expected " + curEntry.CompressedSize);\r
+ throw new ZipException("compressed size was " + csize + ", but I expected " + curEntry.CompressedSize);\r
}\r
\r
if (curEntry.Crc < 0) {\r
curEntry.Crc = crc.Value;\r
} else if (curEntry.Crc != crc.Value) {\r
throw new ZipException("crc was " + crc.Value +\r
- ", but I expected " + \r
- curEntry.Crc);\r
+ ", but I expected " + \r
+ curEntry.Crc);\r
}\r
\r
offset += csize;\r
\r
/* Now write the data descriptor entry if needed. */\r
- if (curMethod == CompressionMethod.Deflated && (curEntry.flags & 8) != 0) {\r
+ if (curMethod == CompressionMethod.Deflated && (curEntry.Flags & 8) != 0) {\r
if (shouldWriteBack) {\r
+ curEntry.Flags &= ~8;\r
long curPos = baseOutputStream.Position;\r
baseOutputStream.Seek(seekPos, SeekOrigin.Begin);\r
WriteLeInt((int)curEntry.Crc);\r
entries.Add(curEntry);\r
curEntry = null;\r
}\r
- \r
- \r
+ \r
/// <summary>\r
/// Writes the given buffer to the current entry.\r
/// </summary>\r
base.Write(b, off, len);\r
break;\r
case CompressionMethod.Stored:\r
- baseOutputStream.Write(b, off, len);\r
+ if (Password != null) {\r
+ byte[] buf = new byte[len];\r
+ Array.Copy(b, off, buf, 0, len);\r
+ EncryptBlock(buf, 0, len);\r
+ baseOutputStream.Write(buf, off, len);\r
+ } else {\r
+ baseOutputStream.Write(b, off, len);\r
+ }\r
break;\r
}\r
- \r
crc.Update(b, off, len);\r
+ \r
size += len;\r
}\r
\r
- \r
/// <summary>\r
/// Finishes the stream. This will write the central directory at the\r
/// end of the zip file and flush the stream.\r
/// <exception cref="System.IO.IOException">\r
/// if an I/O error occured.\r
/// </exception>\r
- public override void Finish()\r
- {\r
- if (entries == null) {\r
- return;\r
- }\r
- if (curEntry != null) {\r
- CloseEntry();\r
- }\r
- \r
- int numEntries = 0;\r
- int sizeEntries = 0;\r
- \r
- foreach (ZipEntry entry in entries) {\r
- // TODO : check the appnote file for compilance with the central directory standard\r
- CompressionMethod method = entry.CompressionMethod;\r
- WriteLeInt(ZipConstants.CENSIG); \r
- WriteLeShort(method == CompressionMethod.Stored ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);\r
- WriteLeShort(method == CompressionMethod.Stored ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);\r
- WriteLeShort(entry.flags);\r
- WriteLeShort((short)method);\r
- WriteLeInt(entry.DosTime);\r
- WriteLeInt((int)entry.Crc);\r
- WriteLeInt((int)entry.CompressedSize);\r
- WriteLeInt((int)entry.Size);\r
- \r
- byte[] name = ZipConstants.ConvertToArray(entry.Name);\r
- \r
- if (name.Length > 0xffff) {\r
- throw new ZipException("Name too long.");\r
- }\r
- byte[] extra = entry.ExtraData;\r
- if (extra == null) {\r
- extra = new byte[0];\r
- }\r
- string strComment = entry.Comment;\r
- byte[] comment = strComment != null ? ZipConstants.ConvertToArray(strComment) : new byte[0];\r
- if (comment.Length > 0xffff) {\r
- throw new ZipException("Comment too long.");\r
- }\r
- \r
- WriteLeShort(name.Length);\r
- WriteLeShort(extra.Length);\r
- WriteLeShort(comment.Length);\r
- WriteLeShort(0); /* disk number */\r
- WriteLeShort(0); /* internal file attr */\r
- WriteLeInt(0); /* external file attr */\r
- WriteLeInt(entry.offset);\r
- \r
- baseOutputStream.Write(name, 0, name.Length);\r
- baseOutputStream.Write(extra, 0, extra.Length);\r
- baseOutputStream.Write(comment, 0, comment.Length);\r
- ++numEntries;\r
- sizeEntries += ZipConstants.CENHDR + name.Length + extra.Length + comment.Length;\r
- }\r
- \r
- WriteLeInt(ZipConstants.ENDSIG);\r
- WriteLeShort(0); /* disk number */\r
- WriteLeShort(0); /* disk with start of central dir */\r
- WriteLeShort(numEntries);\r
- WriteLeShort(numEntries);\r
- WriteLeInt(sizeEntries);\r
- WriteLeInt(offset);\r
- WriteLeShort(zipComment.Length);\r
- baseOutputStream.Write(zipComment, 0, zipComment.Length);\r
- baseOutputStream.Flush();\r
- entries = null;\r
- }\r
+ public override void Finish()\r
+ {\r
+ if (entries == null) {\r
+ return;\r
+ }\r
+ \r
+ if (curEntry != null) {\r
+ CloseEntry();\r
+ }\r
+ \r
+ int numEntries = 0;\r
+ int sizeEntries = 0;\r
+ \r
+ foreach (ZipEntry entry in entries) {\r
+ // TODO : check the appnote file for compilance with the central directory standard\r
+ CompressionMethod method = entry.CompressionMethod;\r
+ WriteLeInt(ZipConstants.CENSIG); \r
+ WriteLeShort(method == CompressionMethod.Stored ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);\r
+ WriteLeShort(method == CompressionMethod.Stored ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);\r
+ \r
+ WriteLeShort(entry.Flags);\r
+ WriteLeShort((short)method);\r
+ WriteLeInt((int)entry.DosTime);\r
+ WriteLeInt((int)entry.Crc);\r
+ WriteLeInt((int)entry.CompressedSize);\r
+ WriteLeInt((int)entry.Size);\r
+ \r
+ byte[] name = ZipConstants.ConvertToArray(entry.Name);\r
+ \r
+ if (name.Length > 0xffff) {\r
+ throw new ZipException("Name too long.");\r
+ }\r
+ \r
+ byte[] extra = entry.ExtraData;\r
+ if (extra == null) {\r
+ extra = new byte[0];\r
+ }\r
+ \r
+ string strComment = entry.Comment;\r
+ byte[] comment = strComment != null ? ZipConstants.ConvertToArray(strComment) : new byte[0];\r
+ if (comment.Length > 0xffff) {\r
+ throw new ZipException("Comment too long.");\r
+ }\r
+ \r
+ WriteLeShort(name.Length);\r
+ WriteLeShort(extra.Length);\r
+ WriteLeShort(comment.Length);\r
+ WriteLeShort(0); // disk number\r
+ WriteLeShort(0); // internal file attr\r
+ if (entry.IsDirectory) { // -jr- 17-12-2003 mark entry as directory (from nikolam.AT.perfectinfo.com)\r
+ WriteLeInt(16);\r
+ } else {\r
+ WriteLeInt(0); // external file attr\r
+ }\r
+ WriteLeInt(entry.Offset);\r
+ \r
+ baseOutputStream.Write(name, 0, name.Length);\r
+ baseOutputStream.Write(extra, 0, extra.Length);\r
+ baseOutputStream.Write(comment, 0, comment.Length);\r
+ ++numEntries;\r
+ sizeEntries += ZipConstants.CENHDR + name.Length + extra.Length + comment.Length;\r
+ }\r
+ \r
+ WriteLeInt(ZipConstants.ENDSIG);\r
+ WriteLeShort(0); // disk number \r
+ WriteLeShort(0); // disk with start of central dir\r
+ WriteLeShort(numEntries);\r
+ WriteLeShort(numEntries);\r
+ WriteLeInt(sizeEntries);\r
+ WriteLeInt(offset);\r
+ WriteLeShort(zipComment.Length);\r
+ baseOutputStream.Write(zipComment, 0, zipComment.Length);\r
+ baseOutputStream.Flush();\r
+ entries = null;\r
+ }\r
}\r
}\r
\r
using System;\r
\r
-namespace ICSharpCode.SharpZipLib {\r
+namespace ICSharpCode.SharpZipLib \r
+{\r
\r
/// <summary>\r
/// Is thrown during the creation or input of a zip file.\r
+I imported the 0.6 version of the library. The only changes from the origional were
+the case of some of the file names -- I changed them to match the names in cvs.
+
+Ben Maurer. May, 2004.
+
+--------------------
+
This directory contains a local copy of the Zip library from the NZipLib project.
I have added this as a temporary measure to simplify the building and development