home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / system / source / zip.cpp < prev   
Encoding:
C/C++ Source or Header  |  2006-12-02  |  14.4 KB  |  600 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <vd2/system/zip.h>
  28. #include <vd2/system/error.h>
  29.  
  30. bool VDDeflateBitReader::refill() {
  31.     sint32 tc = mBytesLeft>kBufferSize?kBufferSize:(sint32)mBytesLeft;
  32.  
  33.     if (!tc)
  34.         return false;
  35.  
  36.     mpSrc->Read(mBuffer+kBufferSize-tc, tc);    // might throw
  37.  
  38.     mBufferPt = -tc;
  39.  
  40.     mBytesLeftLimited = mBytesLeft > kBigAvailThreshold ? kBigAvailThreshold : (unsigned)mBytesLeft;
  41.     mBytesLeft -= tc;
  42.  
  43.     return true;
  44. }
  45.  
  46. void VDDeflateBitReader::readbytes(void *dst, unsigned len) {
  47.     // LAME: OPTIMIZE LATER
  48.     uint8 *dst2 = (uint8 *)dst;
  49.     while(len-->0)
  50.         *dst2++ = getbits(8);
  51. }
  52.  
  53. ///////////////////////////////////////////////////////////////////////////
  54.  
  55. void VDCRCChecker::Init(uint32 crc) {
  56.     mValue = 0xFFFFFFFF;
  57.  
  58.     for(int i=0; i<256; ++i) {
  59.         unsigned v = i;
  60.         for(int j=0; j<8; ++j)
  61.             v = (v>>1) ^ (crc & -(sint32)(v&1));
  62.  
  63.         mTable[i] = v;
  64.     }
  65. }
  66.  
  67. void VDCRCChecker::Process(const void *src0, sint32 count) {
  68.     const uint8 *src = (const uint8 *)src0;
  69.  
  70.     uint32 v = mValue;
  71.  
  72.     // This code is from the PNG spec.
  73.     if (count > 0)
  74.         do {
  75.             v = mTable[(uint8)v ^ *src++] ^ (v >> 8);
  76.         } while(--count);
  77.  
  78.     mValue = v;
  79. }
  80.  
  81. uint32 VDCRCChecker::CRC(uint32 crc, const void *src, sint32 len) {
  82.     Init(crc);
  83.     Process(src, len);
  84.     return CRC();
  85. }
  86.  
  87. ///////////////////////////////////////////////////////////////////////////
  88.  
  89. VDZipStream::VDZipStream()
  90.     : mPos(0)
  91.     , mbCRCEnabled(false)
  92. {
  93. }
  94.  
  95. VDZipStream::VDZipStream(IVDStream *pSrc, uint64 limit, bool bStored) {
  96.     Init(pSrc, limit, bStored);
  97. }
  98.  
  99. VDZipStream::~VDZipStream() {
  100. }
  101.  
  102.  
  103. void VDZipStream::Init(IVDStream *pSrc, uint64 limit, bool bStored) {
  104.     mBits.init(pSrc, limit);
  105.     mBlockType = kNoBlock;
  106.     mReadPt = mWritePt = mBufferLevel = 0;
  107.     mStoredBytesLeft = 0;
  108.     mbNoMoreBlocks = false;
  109.  
  110.     if (bStored) {
  111.         mStoredBytesLeft = (uint32)limit;
  112.         mbNoMoreBlocks = true;
  113.         mBlockType = kStoredBlock;
  114.     }
  115. }
  116.  
  117. const wchar_t *VDZipStream::GetNameForError() {
  118.     return mBits.stream()->GetNameForError();
  119. }
  120.  
  121. sint64 VDZipStream::Pos() {
  122.     return mPos;
  123. }
  124.  
  125. void VDZipStream::Read(void *buffer, sint32 bytes) {
  126.     if (bytes != ReadData(buffer, bytes))
  127.         throw MyError("Read error on compressed data");
  128. }
  129.  
  130. sint32 VDZipStream::ReadData(void *dst0, sint32 bytes) {
  131.     sint32 actual = 0;
  132.  
  133.     uint8 *dst = (uint8 *)dst0;
  134.  
  135.     while(bytes > 0) {
  136.         if (mBufferLevel > 0) {
  137.             unsigned tc = std::min<unsigned>(mBufferLevel, bytes);
  138.             unsigned bp = 65536 - mReadPt;
  139.  
  140.             if (bp < tc) {
  141.                 memcpy(dst, mBuffer+mReadPt, bp);
  142.                 memcpy(dst+bp, mBuffer, tc-bp);
  143.                 mReadPt = tc-bp;
  144.             } else {
  145.                 memcpy(dst, mBuffer+mReadPt, tc);
  146.                 mReadPt += tc;
  147.             }
  148.             mBufferLevel -= tc;
  149.             dst += tc;
  150.             bytes -= tc;
  151.             actual += tc;
  152.         } else {
  153.             uint32 origWritePt = mWritePt;
  154.             uint32 origBufferLevel = mBufferLevel;
  155.  
  156.             if (!Inflate())
  157.                 break;
  158.  
  159.             if (mbCRCEnabled && mBufferLevel != origBufferLevel) {
  160.                 if (mWritePt <= origWritePt) {
  161.                     mCRCChecker.Process(mBuffer+origWritePt, 65536 - origWritePt);
  162.                     mCRCChecker.Process(mBuffer, mWritePt);
  163.                 } else {
  164.                     mCRCChecker.Process(mBuffer+origWritePt, mWritePt - origWritePt);
  165.                 }
  166.             }
  167.         }
  168.     }
  169.  
  170.     mPos += actual;
  171.     return actual;
  172. }
  173.  
  174. bool VDZipStream::Inflate() {
  175.     if (mBlockType == kNoBlock)
  176.         if (mbNoMoreBlocks || !ParseBlockHeader())
  177.             return false;
  178.  
  179.     if (mBlockType == kStoredBlock) {
  180.         while(mBufferLevel < 65536) {
  181.             if (mStoredBytesLeft <= 0) {
  182.                 mBlockType = kNoBlock;
  183.                 break;
  184.             }
  185.             uint32 tc = std::min<uint32>(65536 - mWritePt, std::min<uint32>(65536 - mBufferLevel, mStoredBytesLeft));
  186.  
  187.             mBits.readbytes(mBuffer + mWritePt, tc);
  188.  
  189.             mWritePt = (mWritePt + tc) & 65535;
  190.             mStoredBytesLeft -= tc;
  191.             mBufferLevel += tc;
  192.         }
  193.     } else {
  194.         static const unsigned len_tbl[32]={
  195.             3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,
  196.             131,163,195,227,258
  197.         };
  198.  
  199.         static const unsigned char len_bits_tbl[32]={
  200.             0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
  201.         };
  202.  
  203.         static const unsigned char dist_bits_tbl[]={
  204.             0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
  205.         };
  206.  
  207.         static const unsigned dist_tbl[]={
  208.             1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,
  209.             6145,8193,12289,16385,24577
  210.         };
  211.  
  212.         while(mBufferLevel < 65024) {
  213.             unsigned code, bits;
  214.  
  215.             code    = mCodeDecode[mBits.peek() & 0x7fff];
  216.             bits    = mCodeLengths[code];
  217.  
  218.             if (!mBits.consume(bits))
  219.                 return false;
  220.  
  221.             if (code == 256) {
  222.                 mBlockType = kNoBlock;
  223.                 break;
  224.             } else if (code >= 257) {
  225.                 unsigned    dist, len;
  226.  
  227.                 code -= 257;
  228.  
  229.                 len = len_tbl[code] + mBits.getbits(len_bits_tbl[code]);
  230.  
  231.                 if (len < 3)
  232.                     return false;    // can happen with a bad static block
  233.  
  234.                 code = mDistDecode[mBits.peek() & 0x7fff];
  235.                 bits = mCodeLengths[code + 288];
  236.  
  237.                 if (!mBits.consume(bits))
  238.                     return false;
  239.  
  240.                 dist = dist_tbl[code] + mBits.getbits(dist_bits_tbl[code]);
  241.  
  242.                 unsigned copysrc = (mWritePt - dist) & 65535;
  243.  
  244.                 mBufferLevel += len;
  245.  
  246.                 // NOTE: This can be a self-replicating copy.  It must be ascending and it must
  247.                 //         be by bytes.
  248. //                printf("%08lx: distance %04x count %d\n", mWritePt, dist, len);
  249.                 do {
  250.                     mBuffer[mWritePt++] = mBuffer[copysrc++];
  251.                     mWritePt &= 65535;
  252.                     copysrc &= 65535;
  253.                 } while(--len);
  254.             } else {
  255. //                printf("%08lx: literal %02x\n", mWritePt, code);
  256.                 mBuffer[mWritePt++] = code;
  257.                 mWritePt &= 65535;
  258.                 ++mBufferLevel;
  259.             }
  260.         }
  261.     }
  262.  
  263.     return true;
  264. }
  265.  
  266. namespace {
  267.     static unsigned revword8(unsigned x) {
  268.         x = (unsigned char )((x << 4) + (x >> 4));
  269.         x = ((x << 2) & 0xcc) + ((x >> 2) & 0x33);
  270.         return ((x << 1) & 0xaa) + ((x >> 1) & 0x55);
  271.     }
  272.  
  273.     static unsigned revword15(unsigned x) {
  274.         x = ((x << 8) & 0xff00) + ((x >> 8) & 0x00ff);
  275.         x = ((x << 4) & 0xf0f0) + ((x >> 4) & 0x0f0f);
  276.         x = ((x << 2) & 0xcccc) + ((x >> 2) & 0x3333);
  277.         return (x & 0x5555) + ((x >> 2) & 0x2aaa);
  278.     }
  279.  
  280.     static bool InflateExpandTable256(unsigned char *dst, unsigned char *lens, unsigned codes) {
  281.         unsigned    k;
  282.         unsigned    ki;
  283.         unsigned    base=0;
  284.  
  285.         for(unsigned i=1; i<16; ++i) {
  286.             ki = 1<<i;
  287.  
  288.             for(unsigned j=0; j<codes; ++j) {
  289.                 if (lens[j] == i) {
  290.                     for(k=base; k<0x100; k+=ki)
  291.                         dst[k] = j;
  292.  
  293.                     base = revword8((revword8(base)+(0x100 >> i)) & 0xff);
  294.                 }
  295.             }
  296.         }
  297.  
  298.         return !base;
  299.     }
  300.  
  301.     static bool InflateExpandTable32K(unsigned short *dst, unsigned char *lens, unsigned codes) {
  302.         unsigned    k;
  303.         unsigned    ki;
  304.         unsigned    base=0;
  305.  
  306.         for(int i=1; i<16; ++i) {
  307.             ki = 1<<i;
  308.  
  309.             for(unsigned j=0; j<codes; ++j) {
  310.                 if (lens[j] == i) {
  311.                     for(k=base; k<0x8000; k+=ki)
  312.                         dst[k] = j;
  313.  
  314.                     base = revword15(revword15(base)+(0x8000 >> i));
  315.                 }
  316.             }
  317.         }
  318.  
  319.         return !base;
  320.     }
  321. }
  322.  
  323. bool VDZipStream::ParseBlockHeader() {
  324.     unsigned char ltbl_lengths[20];
  325.     unsigned char ltbl_decode[256];
  326.  
  327.     if (mBits.getbit())
  328.         mbNoMoreBlocks = true;
  329.  
  330.     unsigned type = mBits.getbits(2);
  331.  
  332.     switch(type) {
  333.     case 0:        // stored
  334.         {
  335.             mBits.align();
  336.             if (mBits.avail() < 32)
  337.                 return false;
  338.  
  339.             mStoredBytesLeft = mBits.getbits(16);
  340.  
  341.             uint32 invCount = mBits.getbits(16);
  342.  
  343.             if ((uint16)~invCount != mStoredBytesLeft)
  344.                 return false;
  345.  
  346.             if (mBits.bytesleft() < mStoredBytesLeft)
  347.                 return false;
  348.  
  349.             mBlockType = kStoredBlock;
  350.         }
  351.         break;
  352.     case 1:        // static trees
  353.         {
  354.             int i;
  355.  
  356.             for(i=0; i<144; ++i) mCodeLengths[i] = 8;
  357.             for(   ; i<256; ++i) mCodeLengths[i] = 9;
  358.             for(   ; i<280; ++i) mCodeLengths[i] = 7;
  359.             for(   ; i<288; ++i) mCodeLengths[i] = 8;
  360.             for(i=0; i< 32; ++i) mCodeLengths[i+288] = 5;
  361.  
  362.             if (!InflateExpandTable32K(mCodeDecode, mCodeLengths, 288)) {
  363.                 VDASSERT(false);        // code table bad
  364.                 return false;
  365.             }
  366.             if (!InflateExpandTable32K(mDistDecode, mCodeLengths+288, 32)) {
  367.                 VDASSERT(false);        // distance table bad
  368.                 return false;
  369.             }
  370.  
  371.             mBlockType = kDeflatedBlock;
  372.         }
  373.         break;
  374.     case 2:        // dynamic trees
  375.         {
  376.             if (mBits.avail() < 16)
  377.                 return false;
  378.  
  379.             const unsigned    code_count    = mBits.getbits(5) + 257;
  380.             const unsigned    dist_count    = mBits.getbits(5) + 1;
  381.             const unsigned    total_count    = code_count + dist_count;
  382.             const unsigned    ltbl_count    = mBits.getbits(4) + 4;
  383.  
  384.             // decompress length table tree
  385.  
  386.             if (mBits.bitsleft() < 3*ltbl_count)
  387.                 return false;
  388.  
  389.             memset(ltbl_lengths, 0, sizeof ltbl_lengths);
  390.  
  391.             static const unsigned char hclen_tbl[]={
  392.                 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
  393.             };
  394.  
  395.             for(unsigned i=0; i<ltbl_count; ++i) {
  396.                 ltbl_lengths[hclen_tbl[i]] = mBits.getbits(3);
  397.             }
  398.  
  399.             if (!InflateExpandTable256(ltbl_decode, ltbl_lengths, 20)) {
  400.                 VDASSERT(false);    // tree table bad
  401.                 return false;
  402.             }
  403.  
  404.             // decompress length table
  405.  
  406.             unsigned j=0;
  407.             unsigned last = 0;
  408.             while(j < total_count) {
  409.                 unsigned k = ltbl_decode[0xff & mBits.peek()];
  410.                 unsigned run = 1;
  411.  
  412.                 if (!mBits.consume(ltbl_lengths[k]))
  413.                     return false;
  414.  
  415.                 switch(k) {
  416.                 case 16:    // last run of 3-6
  417.                     if (mBits.avail() < 2)
  418.                         return false;
  419.                     run = mBits.getbits(2) + 3;
  420.                     break;
  421.                 case 17:    // zero run of 3-10
  422.                     if (mBits.avail() < 3)
  423.                         return false;
  424.                     run = mBits.getbits(3) + 3;
  425.                     last = 0;
  426.                     break;
  427.                 case 18:    // zero run of 11-138
  428.                     if (mBits.avail() < 7)
  429.                         return false;
  430.                     run = mBits.getbits(7) + 11;
  431.                     last = 0;
  432.                     break;
  433.                 default:
  434.                     last = k;
  435.                 }
  436.  
  437.                 if (run+j > total_count) {
  438.                     VDASSERT(false);    // tree table bad
  439.                     return false;
  440.                 }
  441.  
  442.                 do {
  443.                     mCodeLengths[j++] = last;
  444.                 } while(--run);
  445.             }
  446.  
  447.             memmove(mCodeLengths + 288, mCodeLengths + code_count, dist_count);
  448.  
  449.             if (!InflateExpandTable32K(mCodeDecode, mCodeLengths, code_count)) {
  450.                 VDASSERT(false);    // code table bad
  451.                 return false;
  452.             }
  453.             if (!InflateExpandTable32K(mDistDecode, mCodeLengths+288, dist_count)) {
  454.                 VDASSERT(false);    // data table bad
  455.                 return false;
  456.             }
  457.             mBlockType = kDeflatedBlock;
  458.         }
  459.         break;
  460.     default:
  461.         return false;
  462.     }
  463.  
  464.     return true;
  465. }
  466.  
  467. ///////////////////////////////////////////////////////////////////////////
  468.  
  469. #pragma pack(push, 2)
  470.  
  471. namespace {
  472.     enum {
  473.         kZipMethodStore        = 0,
  474.         kZipMethodDeflate    = 8
  475.     };
  476.  
  477.     struct ZipFileHeader {
  478.         enum { kSignature = 0x04034b50 };
  479.         uint32        signature;
  480.         uint16        version_required;
  481.         uint16        flags;
  482.         uint16        method;
  483.         uint16        mod_time;
  484.         uint16        mod_date;
  485.         uint32        crc32;
  486.         uint32        compressed_size;
  487.         uint32        uncompressed_size;
  488.         uint16        filename_len;
  489.         uint16        extrafield_len;
  490.     };
  491.  
  492.     struct ZipFileEntry {
  493.         enum { kSignature = 0x02014b50 };
  494.         uint32        signature;
  495.         uint16        version_create;
  496.         uint16        version_required;
  497.         uint16        flags;
  498.         uint16        method;
  499.         uint16        mod_time;
  500.         uint16        mod_date;
  501.         uint32        crc32;
  502.         uint32        compressed_size;
  503.         uint32        uncompressed_size;
  504.         uint16        filename_len;
  505.         uint16        extrafield_len;
  506.         uint16        comment_len;
  507.         uint16        diskno;
  508.         uint16        internal_attrib;
  509.         uint32        external_attrib;
  510.         uint32        reloff_localhdr;
  511.     };
  512.  
  513.     struct ZipCentralDir {
  514.         enum { kSignature = 0x06054b50 };
  515.  
  516.         uint32        signature;
  517.         uint16        diskno;
  518.         uint16        diskno_dir;
  519.         uint16        dirents;
  520.         uint16        dirents_total;
  521.         uint32        dirsize;
  522.         uint32        diroffset;
  523.         uint16        comment_len;
  524.     };
  525. }
  526.  
  527. #pragma pack(pop)
  528.  
  529. VDZipArchive::VDZipArchive() {
  530. }
  531.  
  532. VDZipArchive::~VDZipArchive() {
  533. }
  534.  
  535. void VDZipArchive::Init(IVDRandomAccessStream *pSrc) {
  536.     mpStream = pSrc;
  537.  
  538.     // This seek is wrong for files with zip comments, but we aren't creating
  539.     // a general purpose Unzip utility anyway.
  540.     mpStream->Seek(mpStream->Length() - sizeof(ZipCentralDir));
  541.  
  542.     ZipCentralDir cdirhdr;
  543.  
  544.     mpStream->Read(&cdirhdr, sizeof cdirhdr);
  545.     if (cdirhdr.signature != ZipCentralDir::kSignature)
  546.         throw MyError("Zip file has missing or bad central directory");
  547.  
  548.     mDirectory.resize(cdirhdr.dirents_total);
  549.  
  550.     mpStream->Seek(cdirhdr.diroffset);
  551.  
  552.     for(int i=0; i<cdirhdr.dirents_total; ++i) {
  553.         FileInfoInternal& fii = mDirectory[i];
  554.         ZipFileEntry ent;
  555.  
  556.         mpStream->Read(&ent, sizeof ent);
  557.         if (ent.signature != ZipFileEntry::kSignature)
  558.             throw MyError("Zip directory is bad");
  559.  
  560.         if (ent.method != kZipMethodStore && ent.method != kZipMethodDeflate)
  561.             throw MyError("Unsupported compression method in zip archive");
  562.  
  563.         fii.mDataStart            = ent.reloff_localhdr;
  564.         fii.mCompressedSize        = ent.compressed_size;
  565.         fii.mUncompressedSize    = ent.uncompressed_size;
  566.         fii.mCRC32                = ent.crc32;
  567.         fii.mbPacked            = ent.method == kZipMethodDeflate;
  568.         fii.mFileName.resize(ent.filename_len);
  569.  
  570.         mpStream->Read(&*fii.mFileName.begin(), ent.filename_len);
  571.         
  572.         mpStream->Seek(mpStream->Pos() + ent.extrafield_len + ent.comment_len);
  573.     }
  574. }
  575.  
  576. sint32 VDZipArchive::GetFileCount() {
  577.     return mDirectory.size();
  578. }
  579.  
  580. const VDZipArchive::FileInfo& VDZipArchive::GetFileInfo(sint32 idx) {
  581.     VDASSERT((size_t)idx < mDirectory.size());
  582.     return mDirectory[idx];
  583. }
  584.  
  585. IVDStream *VDZipArchive::OpenRawStream(sint32 idx) {
  586.     const FileInfoInternal& fi = mDirectory[idx];
  587.  
  588.     mpStream->Seek(fi.mDataStart);
  589.  
  590.     ZipFileHeader hdr;
  591.     mpStream->Read(&hdr, sizeof hdr);
  592.  
  593.     if (hdr.signature != ZipFileHeader::kSignature)
  594.         throw MyError("Bad header for file in zip archive");
  595.  
  596.     mpStream->Seek(fi.mDataStart + sizeof(hdr) + hdr.filename_len + hdr.extrafield_len);
  597.  
  598.     return mpStream;
  599. }
  600.