//////////////////////////////////////////////////////////////////// // Save directory path in the ZIP directory //////////////////////////////////////////////////////////////////// public Boolean SaveDirectoryPath ( String FullFileName, String ArchiveFileName ) { try { // write zip file header for directory path WriteFileHeader(FullFileName, ArchiveFileName); // save file header ZipDir.Insert(~ZipDir.BinarySearch(FileHeaderInfo), FileHeaderInfo); // successful exit return(false); } // catch exceptions and save the exception error message and stack catch (Exception Ex) { // remove any information written to the file WriteStream.SetLength(WriteStartPosition); // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
//////////////////////////////////////////////////////////////////// // Delete central directory entry //////////////////////////////////////////////////////////////////// public Boolean Delete ( Int32 ZipDirIndex ) { try { // delete the entry ZipDir.RemoveAt(ZipDirIndex); } // catch exceptions and save the exception error message and stack catch (Exception Ex) { // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } // set delete mode flag for save archive DeleteMode = true; // successful exit return(false); }
//////////////////////////////////////////////////////////////////// // Decompress one file //////////////////////////////////////////////////////////////////// public Boolean Compress ( String FullFileName, String ArchiveFileName ) { try { // write zip file header WriteFileHeader(FullFileName, ArchiveFileName); // open source file for reading ReadStream = new FileStream(ReadFileName, FileMode.Open, FileAccess.Read, FileShare.Read); // convert stream to binary reader ReadFile = new BinaryReader(ReadStream, Encoding.UTF8); // uncompressed file length ReadRemain = (UInt32)ReadStream.Length; // reset CRC32 checksum ReadCRC32 = 0; // compress the file Compress(); // close read file ReadFile.Close(); ReadFile = null; // update zip file header with input file crc and compressed file length UpdateZipFileHeader(); // successful exit return(false); } // catch exceptions and save the exception error message and stack catch (Exception Ex) { // close the read file if it is open if (ReadFile != null) { ReadFile.Close(); ReadFile = null; } // remove any information written to the file WriteStream.SetLength(WriteStartPosition); // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
//////////////////////////////////////////////////////////////////// // Save ZIP Archive //////////////////////////////////////////////////////////////////// public Boolean SaveArchive() { try { // zip directory is empty if (ZipDir.Count == 0) { // close and delete the file WriteFile.Close(); WriteFile = null; File.Delete(WriteFileName); } else { // one or more files were deleted if (DeleteMode) { DeleteFiles(); } // write zip file directory ZipFileDirectory(); // close file WriteFile.Close(); WriteFile = null; // clear directory ZipDir.Clear(); } // successful exit return(false); } // catch exceptions and save the exception error message and stack catch (Exception Ex) { // close the write file if it is open CloseZipFile(); // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
//////////////////////////////////////////////////////////////////// // Create ZIP Archive //////////////////////////////////////////////////////////////////// public Boolean CreateArchive ( String WriteFileName ) { try { // save name this.WriteFileName = WriteFileName; // create destination file WriteStream = new FileStream(WriteFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None); // convert stream to binary writer WriteFile = new BinaryWriter(WriteStream, Encoding.UTF8); // convert stream to binary reader WriteFileReader = new BinaryReader(WriteStream, Encoding.UTF8); // create empty zip file directory ZipDir = new List <FileHeader>(); // reset zip directory position ZipDirPosition = 0; // reset delete mode DeleteMode = false; // successful exit return(false); } // catch exceptions and save the exception error message and stack catch (Exception Ex) { // close the write file if it is open CloseZipFile(); // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
///////////////////////////////////////////////////////////////////// // Open ZIP file and read file directory ///////////////////////////////////////////////////////////////////// public Boolean OpenZipFile ( String ReadFileName ) { // trap errors try { // save name this.ReadFileName = ReadFileName; // open source file for reading ReadStream = new FileStream(ReadFileName, FileMode.Open, FileAccess.Read, FileShare.Read); // convert stream to binary reader ReadFile = new BinaryReader(ReadStream, Encoding.UTF8); // file is too long if (ReadStream.Length > (Int64)0xffffffff) { throw new ApplicationException("No support for files over 4GB"); } // read zip directory ReadZipFileDirectory(); // successful exit return(false); } // make sure read file is closed catch (Exception Ex) { // close the read file if it is open CloseZipFile(); // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
//////////////////////////////////////////////////////////////////// // Decompress one file //////////////////////////////////////////////////////////////////// public Boolean Decompress ( String ReadFileName, String WriteFileName ) { try { // save name this.ReadFileName = ReadFileName; // open source file for reading ReadStream = new FileStream(ReadFileName, FileMode.Open, FileAccess.Read, FileShare.Read); // convert stream to binary reader ReadFile = new BinaryReader(ReadStream, Encoding.UTF8); // file is too long if (ReadStream.Length > (Int64)0xffffffff) { throw new ApplicationException("No support for files over 4GB"); } // compressed part of the file // we subtract 2 bytes for header and 4 bytes for adler32 checksum ReadRemain = (UInt32)ReadStream.Length - 6; ReadTotal = ReadRemain; // get ZLib header Int32 Header = (ReadFile.ReadByte() << 8) | ReadFile.ReadByte(); // test header: chksum, compression method must be deflated, no support for external dictionary if (Header % 31 != 0 || (Header & 0xf00) != 0x800 && (Header & 0xf00) != 0 || (Header & 0x20) != 0) { throw new ApplicationException("ZLIB file header is in error"); } // save name this.WriteFileName = WriteFileName; // create destination file WriteStream = new FileStream(WriteFileName, FileMode.Create, FileAccess.Write, FileShare.None); // convert stream to binary writer WriteFile = new BinaryWriter(WriteStream, Encoding.UTF8); // reset adler32 checksum WriteAdler32 = 1; // decompress the file if ((Header & 0xf00) == 0x800) { Decompress(); } else { NoCompression(); } // ZLib checksum is Adler32 if ((((UInt32)ReadFile.ReadByte() << 24) | ((UInt32)ReadFile.ReadByte() << 16) | ((UInt32)ReadFile.ReadByte() << 8) | ((UInt32)ReadFile.ReadByte())) != WriteAdler32) { throw new ApplicationException("ZLIB file Adler32 test failed"); } // close read file ReadFile.Close(); ReadFile = null; // save file length WriteTotal = (UInt32)WriteStream.Length; // close write file WriteFile.Close(); WriteFile = null; // successful exit return(false); } // make sure read and write files are closed catch (Exception Ex) { // close the read file if it is open if (ReadFile != null) { ReadFile.Close(); ReadFile = null; } // close the write file if it is open if (WriteFile != null) { WriteFile.Close(); WriteFile = null; } // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
//////////////////////////////////////////////////////////////////// // Compress one file //////////////////////////////////////////////////////////////////// public Boolean Compress ( String ReadFileName, String WriteFileName ) { try { // save name this.ReadFileName = ReadFileName; // open source file for reading ReadStream = new FileStream(ReadFileName, FileMode.Open, FileAccess.Read, FileShare.Read); // convert stream to binary reader ReadFile = new BinaryReader(ReadStream, Encoding.UTF8); // file is too long if (ReadStream.Length > (Int64)0xffffffff) { throw new ApplicationException("No support for files over 4GB"); } // uncompressed file length ReadRemain = (UInt32)ReadStream.Length; // save name this.WriteFileName = WriteFileName; // create destination file WriteStream = new FileStream(WriteFileName, FileMode.Create, FileAccess.Write, FileShare.None); // convert stream to binary writer WriteFile = new BinaryWriter(WriteStream, Encoding.UTF8); // compress the file (function defind in DeflateMethod the base class) Compress(); // close read file ReadFile.Close(); ReadFile = null; // close write file WriteFile.Close(); WriteFile = null; // successful exit return(false); } // make sure read and write files are closed catch (Exception Ex) { // close the read file if it is open if (ReadFile != null) { ReadFile.Close(); ReadFile = null; } // close the write file if it is open if (WriteFile != null) { WriteFile.Close(); WriteFile = null; } // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
//////////////////////////////////////////////////////////////////// // Decompress ZIP file //////////////////////////////////////////////////////////////////// public Boolean DecompressZipFile ( FileHeader FH, String RootPathName, // save the decompressed file in this directory String NewFileName, // if this file name is given it overwrite the name in the FH structure Boolean CreatePath, Boolean OverWrite ) { try { // save file header FileHeaderInfo = FH; // read file header for this file and compare it to the directory information ReadFileHeader(FileHeaderInfo.FilePos); // compressed length ReadRemain = FileHeaderInfo.CompSize; ReadTotal = ReadRemain; // build write file name // Root name (optional) plus either original name or a new name WriteFileName = (String.IsNullOrEmpty(RootPathName) ? String.Empty : (RootPathName.EndsWith("\\") ? RootPathName : RootPathName + "\\")) + (String.IsNullOrEmpty(NewFileName) ? FH.FileName : NewFileName); // test if write file name has a path component Int32 Ptr = WriteFileName.LastIndexOf('\\'); if (Ptr >= 0) { // make sure directory exists if (!Directory.Exists(WriteFileName.Substring(0, Ptr))) { // make a new folder if (CreatePath) { Directory.CreateDirectory(WriteFileName.Substring(0, Ptr)); } // error else { throw new ApplicationException("Extract file failed. Invalid directory path"); } } } // create destination file WriteStream = new FileStream(WriteFileName, OverWrite ? FileMode.Create : FileMode.CreateNew, FileAccess.Write, FileShare.None); // convert stream to binary writer WriteFile = new BinaryWriter(WriteStream, Encoding.UTF8); // reset crc32 checksum WriteCRC32 = 0; // switch based on compression method switch (FileHeaderInfo.CompMethod) { // no compression case 0: NoCompression(); break; // deflate compress method case 8: // decompress file Decompress(); break; // not supported default: throw new ApplicationException("Unsupported compression method"); } // Zip file checksum is CRC32 if (FileHeaderInfo.FileCRC32 != WriteCRC32) { throw new ApplicationException("ZIP file CRC test failed"); } // save file length WriteTotal = (UInt32)WriteStream.Length; // close write file WriteFile.Close(); WriteFile = null; // if file times are available set the file time if (FileTimeAvailable) { File.SetCreationTime(WriteFileName, FileCreateTime); File.SetLastWriteTime(WriteFileName, FileModifyTime); File.SetLastAccessTime(WriteFileName, FileAccessTime); } else { // convert dos file date and time to DateTime format DateTime FileDosTime = new DateTime(1980 + ((FileHeaderInfo.FileDate >> 9) & 0x7f), (FileHeaderInfo.FileDate >> 5) & 0xf, FileHeaderInfo.FileDate & 0x1f, (FileHeaderInfo.FileTime >> 11) & 0x1f, (FileHeaderInfo.FileTime >> 5) & 0x3f, 2 * (FileHeaderInfo.FileTime & 0x1f)); File.SetCreationTime(WriteFileName, FileDosTime); File.SetLastWriteTime(WriteFileName, FileDosTime); File.SetLastAccessTime(WriteFileName, FileDosTime); } // set file attribute attributes if (FileHeaderInfo.FileAttr != 0) { File.SetAttributes(WriteFileName, FileHeaderInfo.FileAttr); } // successful exit return(false); } // make sure write file is closed catch (Exception Ex) { // close the write file if it is open if (WriteFile != null) { WriteFile.Close(); WriteFile = null; } // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
//////////////////////////////////////////////////////////////////// // Compare Files //////////////////////////////////////////////////////////////////// private Boolean CompareFiles() { FileStream Stream1, Stream2; BinaryReader File1 = null, File2 = null; Byte[] Buffer1, Buffer2; // trap errors try { // open file1 for reading Stream1 = new FileStream(InputFileName, FileMode.Open, FileAccess.Read, FileShare.Read); // convert stream to binary reader File1 = new BinaryReader(Stream1, Encoding.UTF8); // open file2 for reading Stream2 = new FileStream(DecompFileName, FileMode.Open, FileAccess.Read, FileShare.Read); // convert stream to binary reader File2 = new BinaryReader(Stream2, Encoding.UTF8); // length must be the same if (Stream1.Length != Stream2.Length) { throw new ApplicationException("Compare files failed. Files lengths not the same"); } // allocate buffer Buffer1 = new Byte[32 * 1024]; Buffer2 = new Byte[32 * 1024]; // compare Int64 Len = Stream1.Length; while (Len > 0) { Int32 Count = Len < (Int64)Buffer1.Length ? (Int32)Len : Buffer1.Length; Int32 Act1 = File1.Read(Buffer1, 0, Count); if (Act1 != Count) { throw new ApplicationException("Compare files failed. Reading file1 failed"); } Int32 Act2 = File2.Read(Buffer2, 0, Count); if (Act2 != Count) { throw new ApplicationException("Compare files failed. Reading file2 failed"); } Int32 Index; for (Index = 0; Index < Count && Buffer1[Index] == Buffer2[Index]; Index++) { ; } if (Index != Count) { throw new ApplicationException("Compare files failed. The two files are not the same"); } Len -= Count; } File1.Close(); File2.Close(); // successful exit return(false); } catch (Exception Ex) { // make sure read file is closed File1.Close(); File2.Close(); // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }
//////////////////////////////////////////////////////////////////// // On add button //////////////////////////////////////////////////////////////////// private void OnAddButton ( object sender, EventArgs e ) { // get selected list ListView.SelectedListViewItemCollection SelectedList = FileList.SelectedItems; // the list is empty if (SelectedList.Count == 0) { return; } // trap duplicate file errors try { // zip file root directory RootDir = (String)DirectoryTree.SelectedNode.Tag; RootDirPtr = RootDir.Length + 1; // create empty file list AddDir = new List <FileHeader>(); // get all selected directories foreach (ListViewItem Item in SelectedList) { if (Item.Tag.GetType() == typeof(DirectoryInfo)) { ProcessDirectory((DirectoryInfo)Item.Tag); } } // get all selected files in the zip file root directory foreach (ListViewItem Item in SelectedList) { if (Item.Tag.GetType() == typeof(FileInfo)) { // shortcut for file information FileInfo FI = (FileInfo)Item.Tag; // create zip directory file header record with name date time and attributes FileHeader FH = new FileHeader(FI.FullName.Substring(RootDirPtr), FI.LastWriteTime, FI.Attributes, 0, FI.Length); // find item poition in the list Int32 Index = AddDir.BinarySearch(FH); if (Index >= 0) { throw new ApplicationException("Duplicate file name"); } // add to the list AddDir.Insert(~Index, FH); } } // save compression level CompLevel = (Int32)CompLevelUpDown.Value; // close screen DialogResult = DialogResult.OK; return; } // error catch (Exception Ex) { // error exit String[] ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); MessageBox.Show(this, "Add files and folders error\n" + ExceptionStack[0] + "\n" + ExceptionStack[1], "Add Files Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } }
//////////////////////////////////////////////////////////////////// // Decompress one file //////////////////////////////////////////////////////////////////// public Boolean Compress ( String ReadFileName, String WriteFileName ) { try { // save read file name this.ReadFileName = ReadFileName; // open source file for reading ReadStream = new FileStream(ReadFileName, FileMode.Open, FileAccess.Read, FileShare.Read); // convert stream to binary reader ReadFile = new BinaryReader(ReadStream, Encoding.UTF8); // file is too long if (ReadStream.Length > (Int64)0xffffffff) { throw new ApplicationException("No support for files over 4GB"); } // uncompressed file length ReadRemain = (UInt32)ReadStream.Length; // reset adler32 checksum ReadAdler32 = 1; // save name this.WriteFileName = WriteFileName; // create destination file WriteStream = new FileStream(WriteFileName, FileMode.Create, FileAccess.Write, FileShare.None); // convert stream to binary writer WriteFile = new BinaryWriter(WriteStream, Encoding.UTF8); // Header is made out of 16 bits [iiiicccclldxxxxx] // iiii is compression information. It is WindowBit - 8 in this case 7. iiii = 0111 // cccc is compression method. Deflate (8 dec) or Store (0 dec) // The first byte is 0x78 for deflate and 0x70 for store // ll is compression level 0 to 3 (CompLevelTable translates between user level of 0-9 to header level of 0-3) // d is preset dictionary. The preset dictionary is not supported by this program. d is always 0 // xxx is 5 bit check sum Int32 Header = (0x78 << 8) | (CompLevelTable[CompressionLevel] << 6); Header += 31 - (Header % 31); // write two bytes in most significant byte first WriteFile.Write((Byte)(Header >> 8)); WriteFile.Write((Byte)Header); // compress the file Compress(); // compress function was stored if (CompFunction == CompFunc.Stored) { // set file position to header WriteStream.Position = 0; // change compression method from Deflate(8) to Stored(0) Header = (0x70 << 8) | (CompLevelTable[CompressionLevel] << 6); Header += 31 - (Header % 31); // write two bytes in most significant byte first WriteFile.Write((Byte)(Header >> 8)); WriteFile.Write((Byte)Header); // restore file position WriteStream.Position = WriteStream.Length; } // ZLib checksum is Adler32 write it big endian order, high byte first WriteFile.Write((Byte)(ReadAdler32 >> 24)); WriteFile.Write((Byte)(ReadAdler32 >> 16)); WriteFile.Write((Byte)(ReadAdler32 >> 8)); WriteFile.Write((Byte)ReadAdler32); // close read file ReadFile.Close(); ReadFile = null; // close write file WriteFile.Close(); WriteFile = null; // successful exit return(false); } // make sure read and write files are closed catch (Exception Ex) { // close the read file if it is open if (ReadFile != null) { ReadFile.Close(); ReadFile = null; } // close the write file if it is open if (WriteFile != null) { WriteFile.Close(); WriteFile = null; } // error exit ExceptionStack = ExceptionReport.GetMessageAndStack(this, Ex); return(true); } }