Пример #1
0
        // 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();
        }
Пример #2
0
        // 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();
        }
Пример #3
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);
        }
Пример #4
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);
        }
Пример #5
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;
        }
Пример #6
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;
        }