// Show detailed information about CAB structures, for debug purposes static void DumpCAB(string name) { FileStream fs = new FileStream(name, FileMode.Open, FileAccess.Read); CFHeader cfh = new CFHeader(fs); Console.WriteLine("Cabinet Header"); Console.WriteLine(cfh); fs.Seek(cfh.uiFilesOffset, SeekOrigin.Begin); for (int i = 0; i < cfh.usNumFiles; i++) { Console.Write("@{0:X8}h ", fs.Position); CFFile cff = new CFFile(fs); Console.WriteLine(cff); } fs.Seek(cfh.Length, SeekOrigin.Begin); Console.WriteLine("Cabinet Folders"); for (int i = 0; i < cfh.usNumFolders; i++) { Console.Write("@{0:X8}h ", fs.Position); CFFolder cffld = new CFFolder(fs); Console.WriteLine(cffld); fs.Seek(cffld.uiDataOffset, SeekOrigin.Begin); Console.WriteLine("{0} CFDATA blocks", cffld.usBlocks); for (int j = 0; j < cffld.usBlocks; j++) { Console.Write("@{0:X8}h ", fs.Position); CFData cfd = new CFData(fs, bLoadData:true); Console.WriteLine(cfd); } } fs.Close(); }
// Show detailed information about CAB structures, for debug purposes static void DumpCAB(string name) { FileStream fs = new FileStream(name, FileMode.Open, FileAccess.Read); CFHeader cfh = new CFHeader(fs); Console.WriteLine("Cabinet Header"); Console.WriteLine(cfh); fs.Seek(cfh.uiFilesOffset, SeekOrigin.Begin); for (int i = 0; i < cfh.usNumFiles; i++) { Console.Write("@{0:X8}h ", fs.Position); CFFile cff = new CFFile(fs); Console.WriteLine(cff); } fs.Seek(cfh.Length, SeekOrigin.Begin); Console.WriteLine("Cabinet Folders"); for (int i = 0; i < cfh.usNumFolders; i++) { Console.Write("@{0:X8}h ", fs.Position); CFFolder cffld = new CFFolder(fs); Console.WriteLine(cffld); fs.Seek(cffld.uiDataOffset, SeekOrigin.Begin); Console.WriteLine("{0} CFDATA blocks", cffld.usBlocks); for (int j = 0; j < cffld.usBlocks; j++) { Console.Write("@{0:X8}h ", fs.Position); CFData cfd = new CFData(fs, bLoadData: true); Console.WriteLine(cfd); } } fs.Close(); }
// Expands and copies a folder's segment (starting from "offset" and long "length" bytes) to a file public int Copy(FileStream input, FileStream output, uint offset, uint length) { byte[] tmp; CFData cfd; bool bContinuedStream = false; uint uiStartChunk = offset / 32768; // If it is the last expanded block, cached... if (uiStartChunk == uiLastExpandedBlock) { bContinuedStream = true; goto Perform; } // If we already started the inflater, we have to skip // only the blocks between last & next... if (compressor != null && compressor.bInited) { uiStartChunk -= uiLastExpandedBlock; uiStartChunk--; } else { input.Seek(uiDataOffset, SeekOrigin.Begin); } // We must synchronize the inflater by expanding all previous chunks... while (uiStartChunk-- > 0) { cfd = new CFData(input, bLoadData: true); if (cfd.Check() == 1) { throw new ApplicationException("Corrupted data block found!"); } tmp = DecompressChunk(cfd.abData, cfd.usCompressedSize, false); uiLastExpandedBlock++; } Perform: int iStartOffset = (int)offset % 32768; // Start offset inside 1st chunk int ucb = (int)length; // uncompressed bytes to get expanded int cb = 0; // uncompressed bytes picked from current chunk // How many bytes we picked from last block? The remainder is for next call! while (ucb > 0) { if (!bContinuedStream) { cfd = new CFData(input, bLoadData: true); if (cfd.Check() == 1) { throw new ApplicationException("Corrupted data block found!"); } cb = (cfd.usOriginalSize - iStartOffset > ucb) ? ucb : cfd.usOriginalSize - iStartOffset; // The chunk is the last if cb == ucb tmp = DecompressChunk(cfd.abData, cfd.usCompressedSize, (ucb == cb)); LastExpandedBlock = tmp; uiLastExpandedBlock++; } else { tmp = LastExpandedBlock; cb = (tmp.Length - iStartOffset > ucb) ? ucb : tmp.Length - iStartOffset; bContinuedStream = false; } output.Write(tmp, iStartOffset, (ucb == cb) ? ucb : tmp.Length - iStartOffset); ucb -= cb; iStartOffset = 0; } return(1); }
public int WriteFolder(FileStream output) { uiDataOffset = (uint)output.Position; byte[] main_buf = new byte[32768]; byte[] tmp; // Cycles through files, filling the tmp buffer upto exactly 32KiB 'til the last chunk for (int i = 0, ucb = 0; i < cfFiles.Count; i++) { FileStream f = new FileStream(cfFiles[i].FileName, FileMode.Open, FileAccess.Read); Console.WriteLine(" -- adding: {0}", cfFiles[i].FileName); int req = 32768 - ucb; while (true) { // Restore the pointer to the main buffer tmp = main_buf; int cb = f.Read(tmp, ucb, req); // If it was the last chunk of the last file... //bool isLast = (cb == 0 && i == cfFiles.Count - 1); // ATTEMPT! bool isLast = (cb < 32768 && i == cfFiles.Count - 1); // ...AND there are no bytes pending, quits! //if (isLast && ucb == 0) break; if (isLast && cb == 0) { break; } ucb += cb; // If we reached the end of an intermediate file... if (ucb < 32768 && i < cfFiles.Count - 1) { break; } int ccb; if (usCompression != 0 && compressor != null) { // An uncompressed 32KiB block MUST be represented by some output // We tell the compressor if it is the last chunk tmp = CompressChunk(tmp, ucb, isLast); // "MS"-ZIP or LZX ccb = tmp.Length; } else { ccb = ucb; } // Makes and saves the CFDATA CFData cfd = new CFData(); cfd.SetContents(tmp, ccb); cfd.usOriginalSize = (ushort)ucb; cfd.usCompressedSize = (ushort)ccb; cfd.ToStream(output); usBlocks += 1; ucb = 0; req = 32768; } f.Close(); } long pos = output.Position; output.Position = Position; ToStream(output); output.Position = pos; return(0); }
public int WriteFolder(FileStream output) { uiDataOffset = (uint)output.Position; byte[] main_buf = new byte[32768]; byte[] tmp; // Cycles through files, filling the tmp buffer upto exactly 32KiB 'til the last chunk for (int i=0, ucb=0; i < cfFiles.Count; i++) { FileStream f = new FileStream(cfFiles[i].FileName, FileMode.Open, FileAccess.Read); Console.WriteLine(" -- adding: {0}", cfFiles[i].FileName); int req = 32768 - ucb; while (true) { // Restore the pointer to the main buffer tmp = main_buf; int cb = f.Read(tmp, ucb, req); // If it was the last chunk of the last file... //bool isLast = (cb == 0 && i == cfFiles.Count - 1); // ATTEMPT! bool isLast = (cb < 32768 && i == cfFiles.Count - 1); // ...AND there are no bytes pending, quits! //if (isLast && ucb == 0) break; if (isLast && cb == 0) break; ucb += cb; // If we reached the end of an intermediate file... if (ucb < 32768 && i < cfFiles.Count - 1) break; int ccb; if (usCompression != 0 && compressor != null) { // An uncompressed 32KiB block MUST be represented by some output // We tell the compressor if it is the last chunk tmp = CompressChunk(tmp, ucb, isLast); // "MS"-ZIP or LZX ccb = tmp.Length; } else ccb = ucb; // Makes and saves the CFDATA CFData cfd = new CFData(); cfd.SetContents(tmp, ccb); cfd.usOriginalSize = (ushort)ucb; cfd.usCompressedSize = (ushort)ccb; cfd.ToStream(output); usBlocks += 1; ucb = 0; req = 32768; } f.Close(); } long pos = output.Position; output.Position = Position; ToStream(output); output.Position = pos; return 0; }
// Expands and copies a folder's segment (starting from "offset" and long "length" bytes) to a file public int Copy(FileStream input, FileStream output, uint offset, uint length) { byte[] tmp; CFData cfd; bool bContinuedStream = false; uint uiStartChunk = offset / 32768; // If it is the last expanded block, cached... if (uiStartChunk == uiLastExpandedBlock) { bContinuedStream = true; goto Perform; } // If we already started the inflater, we have to skip // only the blocks between last & next... if (compressor != null && compressor.bInited) { uiStartChunk -= uiLastExpandedBlock; uiStartChunk--; } else { input.Seek(uiDataOffset, SeekOrigin.Begin); } // We must synchronize the inflater by expanding all previous chunks... while (uiStartChunk-- > 0) { cfd = new CFData(input, bLoadData:true); if (cfd.Check() == 1) throw new ApplicationException("Corrupted data block found!"); tmp = DecompressChunk(cfd.abData, cfd.usCompressedSize, false); uiLastExpandedBlock++; } Perform: int iStartOffset = (int)offset % 32768; // Start offset inside 1st chunk int ucb = (int)length; // uncompressed bytes to get expanded int cb = 0; // uncompressed bytes picked from current chunk // How many bytes we picked from last block? The remainder is for next call! while (ucb > 0) { if (!bContinuedStream) { cfd = new CFData(input, bLoadData: true); if (cfd.Check() == 1) throw new ApplicationException("Corrupted data block found!"); cb = (cfd.usOriginalSize - iStartOffset > ucb) ? ucb : cfd.usOriginalSize - iStartOffset; // The chunk is the last if cb == ucb tmp = DecompressChunk(cfd.abData, cfd.usCompressedSize, (ucb == cb)); LastExpandedBlock = tmp; uiLastExpandedBlock++; } else { tmp = LastExpandedBlock; cb = (tmp.Length - iStartOffset > ucb) ? ucb : tmp.Length - iStartOffset; bContinuedStream = false; } output.Write(tmp, iStartOffset, (ucb == cb) ? ucb : tmp.Length - iStartOffset); ucb -= cb; iStartOffset = 0; } return 1; }