home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / system / source / zip.cpp < prev   
Encoding:
C/C++ Source or Header  |  2009-09-14  |  14.5 KB  |  604 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. void VDZipStream::Write(const void *buffer, sint32 bytes) {
  175.     throw MyError("Zip streams are read-only.");
  176. }
  177.  
  178. bool VDZipStream::Inflate() {
  179.     if (mBlockType == kNoBlock)
  180.         if (mbNoMoreBlocks || !ParseBlockHeader())
  181.             return false;
  182.  
  183.     if (mBlockType == kStoredBlock) {
  184.         while(mBufferLevel < 65536) {
  185.             if (mStoredBytesLeft <= 0) {
  186.                 mBlockType = kNoBlock;
  187.                 break;
  188.             }
  189.             uint32 tc = std::min<uint32>(65536 - mWritePt, std::min<uint32>(65536 - mBufferLevel, mStoredBytesLeft));
  190.  
  191.             mBits.readbytes(mBuffer + mWritePt, tc);
  192.  
  193.             mWritePt = (mWritePt + tc) & 65535;
  194.             mStoredBytesLeft -= tc;
  195.             mBufferLevel += tc;
  196.         }
  197.     } else {
  198.         static const unsigned len_tbl[32]={
  199.             3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,
  200.             131,163,195,227,258
  201.         };
  202.  
  203.         static const unsigned char len_bits_tbl[32]={
  204.             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
  205.         };
  206.  
  207.         static const unsigned char dist_bits_tbl[]={
  208.             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
  209.         };
  210.  
  211.         static const unsigned dist_tbl[]={
  212.             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,
  213.             6145,8193,12289,16385,24577
  214.         };
  215.  
  216.         while(mBufferLevel < 65024) {
  217.             unsigned code, bits;
  218.  
  219.             code    = mCodeDecode[mBits.peek() & 0x7fff];
  220.             bits    = mCodeLengths[code];
  221.  
  222.             if (!mBits.consume(bits))
  223.                 return false;
  224.  
  225.             if (code == 256) {
  226.                 mBlockType = kNoBlock;
  227.                 break;
  228.             } else if (code >= 257) {
  229.                 unsigned    dist, len;
  230.  
  231.                 code -= 257;
  232.  
  233.                 len = len_tbl[code] + mBits.getbits(len_bits_tbl[code]);
  234.  
  235.                 if (len < 3)
  236.                     return false;    // can happen with a bad static block
  237.  
  238.                 code = mDistDecode[mBits.peek() & 0x7fff];
  239.                 bits = mCodeLengths[code + 288];
  240.  
  241.                 if (!mBits.consume(bits))
  242.                     return false;
  243.  
  244.                 dist = dist_tbl[code] + mBits.getbits(dist_bits_tbl[code]);
  245.  
  246.                 unsigned copysrc = (mWritePt - dist) & 65535;
  247.  
  248.                 mBufferLevel += len;
  249.  
  250.                 // NOTE: This can be a self-replicating copy.  It must be ascending and it must
  251.                 //         be by bytes.
  252. //                printf("%08lx: distance %04x count %d\n", mWritePt, dist, len);
  253.                 do {
  254.                     mBuffer[mWritePt++] = mBuffer[copysrc++];
  255.                     mWritePt &= 65535;
  256.                     copysrc &= 65535;
  257.                 } while(--len);
  258.             } else {
  259. //                printf("%08lx: literal %02x\n", mWritePt, code);
  260.                 mBuffer[mWritePt++] = code;
  261.                 mWritePt &= 65535;
  262.                 ++mBufferLevel;
  263.             }
  264.         }
  265.     }
  266.  
  267.     return true;
  268. }
  269.  
  270. namespace {
  271.     static unsigned revword8(unsigned x) {
  272.         x = (unsigned char )((x << 4) + (x >> 4));
  273.         x = ((x << 2) & 0xcc) + ((x >> 2) & 0x33);
  274.         return ((x << 1) & 0xaa) + ((x >> 1) & 0x55);
  275.     }
  276.  
  277.     static unsigned revword15(unsigned x) {
  278.         x = ((x << 8) & 0xff00) + ((x >> 8) & 0x00ff);
  279.         x = ((x << 4) & 0xf0f0) + ((x >> 4) & 0x0f0f);
  280.         x = ((x << 2) & 0xcccc) + ((x >> 2) & 0x3333);
  281.         return (x & 0x5555) + ((x >> 2) & 0x2aaa);
  282.     }
  283.  
  284.     static bool InflateExpandTable256(unsigned char *dst, unsigned char *lens, unsigned codes) {
  285.         unsigned    k;
  286.         unsigned    ki;
  287.         unsigned    base=0;
  288.  
  289.         for(unsigned i=1; i<16; ++i) {
  290.             ki = 1<<i;
  291.  
  292.             for(unsigned j=0; j<codes; ++j) {
  293.                 if (lens[j] == i) {
  294.                     for(k=base; k<0x100; k+=ki)
  295.                         dst[k] = j;
  296.  
  297.                     base = revword8((revword8(base)+(0x100 >> i)) & 0xff);
  298.                 }
  299.             }
  300.         }
  301.  
  302.         return !base;
  303.     }
  304.  
  305.     static bool InflateExpandTable32K(unsigned short *dst, unsigned char *lens, unsigned codes) {
  306.         unsigned    k;
  307.         unsigned    ki;
  308.         unsigned    base=0;
  309.  
  310.         for(int i=1; i<16; ++i) {
  311.             ki = 1<<i;
  312.  
  313.             for(unsigned j=0; j<codes; ++j) {
  314.                 if (lens[j] == i) {
  315.                     for(k=base; k<0x8000; k+=ki)
  316.                         dst[k] = j;
  317.  
  318.                     base = revword15(revword15(base)+(0x8000 >> i));
  319.                 }
  320.             }
  321.         }
  322.  
  323.         return !base;
  324.     }
  325. }
  326.  
  327. bool VDZipStream::ParseBlockHeader() {
  328.     unsigned char ltbl_lengths[20];
  329.     unsigned char ltbl_decode[256];
  330.  
  331.     if (mBits.getbit())
  332.         mbNoMoreBlocks = true;
  333.  
  334.     unsigned type = mBits.getbits(2);
  335.  
  336.     switch(type) {
  337.     case 0:        // stored
  338.         {
  339.             mBits.align();
  340.             if (mBits.avail() < 32)
  341.                 return false;
  342.  
  343.             mStoredBytesLeft = mBits.getbits(16);
  344.  
  345.             uint32 invCount = mBits.getbits(16);
  346.  
  347.             if ((uint16)~invCount != mStoredBytesLeft)
  348.                 return false;
  349.  
  350.             if (mBits.bytesleft() < mStoredBytesLeft)
  351.                 return false;
  352.  
  353.             mBlockType = kStoredBlock;
  354.         }
  355.         break;
  356.     case 1:        // static trees
  357.         {
  358.             int i;
  359.  
  360.             for(i=0; i<144; ++i) mCodeLengths[i] = 8;
  361.             for(   ; i<256; ++i) mCodeLengths[i] = 9;
  362.             for(   ; i<280; ++i) mCodeLengths[i] = 7;
  363.             for(   ; i<288; ++i) mCodeLengths[i] = 8;
  364.             for(i=0; i< 32; ++i) mCodeLengths[i+288] = 5;
  365.  
  366.             if (!InflateExpandTable32K(mCodeDecode, mCodeLengths, 288)) {
  367.                 VDASSERT(false);        // code table bad
  368.                 return false;
  369.             }
  370.             if (!InflateExpandTable32K(mDistDecode, mCodeLengths+288, 32)) {
  371.                 VDASSERT(false);        // distance table bad
  372.                 return false;
  373.             }
  374.  
  375.             mBlockType = kDeflatedBlock;
  376.         }
  377.         break;
  378.     case 2:        // dynamic trees
  379.         {
  380.             if (mBits.avail() < 16)
  381.                 return false;
  382.  
  383.             const unsigned    code_count    = mBits.getbits(5) + 257;
  384.             const unsigned    dist_count    = mBits.getbits(5) + 1;
  385.             const unsigned    total_count    = code_count + dist_count;
  386.             const unsigned    ltbl_count    = mBits.getbits(4) + 4;
  387.  
  388.             // decompress length table tree
  389.  
  390.             if (mBits.bitsleft() < 3*ltbl_count)
  391.                 return false;
  392.  
  393.             memset(ltbl_lengths, 0, sizeof ltbl_lengths);
  394.  
  395.             static const unsigned char hclen_tbl[]={
  396.                 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
  397.             };
  398.  
  399.             for(unsigned i=0; i<ltbl_count; ++i) {
  400.                 ltbl_lengths[hclen_tbl[i]] = mBits.getbits(3);
  401.             }
  402.  
  403.             if (!InflateExpandTable256(ltbl_decode, ltbl_lengths, 20)) {
  404.                 VDASSERT(false);    // tree table bad
  405.                 return false;
  406.             }
  407.  
  408.             // decompress length table
  409.  
  410.             unsigned j=0;
  411.             unsigned last = 0;
  412.             while(j < total_count) {
  413.                 unsigned k = ltbl_decode[0xff & mBits.peek()];
  414.                 unsigned run = 1;
  415.  
  416.                 if (!mBits.consume(ltbl_lengths[k]))
  417.                     return false;
  418.  
  419.                 switch(k) {
  420.                 case 16:    // last run of 3-6
  421.                     if (mBits.avail() < 2)
  422.                         return false;
  423.                     run = mBits.getbits(2) + 3;
  424.                     break;
  425.                 case 17:    // zero run of 3-10
  426.                     if (mBits.avail() < 3)
  427.                         return false;
  428.                     run = mBits.getbits(3) + 3;
  429.                     last = 0;
  430.                     break;
  431.                 case 18:    // zero run of 11-138
  432.                     if (mBits.avail() < 7)
  433.                         return false;
  434.                     run = mBits.getbits(7) + 11;
  435.                     last = 0;
  436.                     break;
  437.                 default:
  438.                     last = k;
  439.                 }
  440.  
  441.                 if (run+j > total_count) {
  442.                     VDASSERT(false);    // tree table bad
  443.                     return false;
  444.                 }
  445.  
  446.                 do {
  447.                     mCodeLengths[j++] = last;
  448.                 } while(--run);
  449.             }
  450.  
  451.             memmove(mCodeLengths + 288, mCodeLengths + code_count, dist_count);
  452.  
  453.             if (!InflateExpandTable32K(mCodeDecode, mCodeLengths, code_count)) {
  454.                 VDASSERT(false);    // code table bad
  455.                 return false;
  456.             }
  457.             if (!InflateExpandTable32K(mDistDecode, mCodeLengths+288, dist_count)) {
  458.                 VDASSERT(false);    // data table bad
  459.                 return false;
  460.             }
  461.             mBlockType = kDeflatedBlock;
  462.         }
  463.         break;
  464.     default:
  465.         return false;
  466.     }
  467.  
  468.     return true;
  469. }
  470.  
  471. ///////////////////////////////////////////////////////////////////////////
  472.  
  473. #pragma pack(push, 2)
  474.  
  475. namespace {
  476.     enum {
  477.         kZipMethodStore        = 0,
  478.         kZipMethodDeflate    = 8
  479.     };
  480.  
  481.     struct ZipFileHeader {
  482.         enum { kSignature = 0x04034b50 };
  483.         uint32        signature;
  484.         uint16        version_required;
  485.         uint16        flags;
  486.         uint16        method;
  487.         uint16        mod_time;
  488.         uint16        mod_date;
  489.         uint32        crc32;
  490.         uint32        compressed_size;
  491.         uint32        uncompressed_size;
  492.         uint16        filename_len;
  493.         uint16        extrafield_len;
  494.     };
  495.  
  496.     struct ZipFileEntry {
  497.         enum { kSignature = 0x02014b50 };
  498.         uint32        signature;
  499.         uint16        version_create;
  500.         uint16        version_required;
  501.         uint16        flags;
  502.         uint16        method;
  503.         uint16        mod_time;
  504.         uint16        mod_date;
  505.         uint32        crc32;
  506.         uint32        compressed_size;
  507.         uint32        uncompressed_size;
  508.         uint16        filename_len;
  509.         uint16        extrafield_len;
  510.         uint16        comment_len;
  511.         uint16        diskno;
  512.         uint16        internal_attrib;
  513.         uint32        external_attrib;
  514.         uint32        reloff_localhdr;
  515.     };
  516.  
  517.     struct ZipCentralDir {
  518.         enum { kSignature = 0x06054b50 };
  519.  
  520.         uint32        signature;
  521.         uint16        diskno;
  522.         uint16        diskno_dir;
  523.         uint16        dirents;
  524.         uint16        dirents_total;
  525.         uint32        dirsize;
  526.         uint32        diroffset;
  527.         uint16        comment_len;
  528.     };
  529. }
  530.  
  531. #pragma pack(pop)
  532.  
  533. VDZipArchive::VDZipArchive() {
  534. }
  535.  
  536. VDZipArchive::~VDZipArchive() {
  537. }
  538.  
  539. void VDZipArchive::Init(IVDRandomAccessStream *pSrc) {
  540.     mpStream = pSrc;
  541.  
  542.     // This seek is wrong for files with zip comments, but we aren't creating
  543.     // a general purpose Unzip utility anyway.
  544.     mpStream->Seek(mpStream->Length() - sizeof(ZipCentralDir));
  545.  
  546.     ZipCentralDir cdirhdr;
  547.  
  548.     mpStream->Read(&cdirhdr, sizeof cdirhdr);
  549.     if (cdirhdr.signature != ZipCentralDir::kSignature)
  550.         throw MyError("Zip file has missing or bad central directory");
  551.  
  552.     mDirectory.resize(cdirhdr.dirents_total);
  553.  
  554.     mpStream->Seek(cdirhdr.diroffset);
  555.  
  556.     for(int i=0; i<cdirhdr.dirents_total; ++i) {
  557.         FileInfoInternal& fii = mDirectory[i];
  558.         ZipFileEntry ent;
  559.  
  560.         mpStream->Read(&ent, sizeof ent);
  561.         if (ent.signature != ZipFileEntry::kSignature)
  562.             throw MyError("Zip directory is bad");
  563.  
  564.         if (ent.method != kZipMethodStore && ent.method != kZipMethodDeflate)
  565.             throw MyError("Unsupported compression method in zip archive");
  566.  
  567.         fii.mDataStart            = ent.reloff_localhdr;
  568.         fii.mCompressedSize        = ent.compressed_size;
  569.         fii.mUncompressedSize    = ent.uncompressed_size;
  570.         fii.mCRC32                = ent.crc32;
  571.         fii.mbPacked            = ent.method == kZipMethodDeflate;
  572.         fii.mFileName.resize(ent.filename_len);
  573.  
  574.         mpStream->Read(&*fii.mFileName.begin(), ent.filename_len);
  575.         
  576.         mpStream->Seek(mpStream->Pos() + ent.extrafield_len + ent.comment_len);
  577.     }
  578. }
  579.  
  580. sint32 VDZipArchive::GetFileCount() {
  581.     return mDirectory.size();
  582. }
  583.  
  584. const VDZipArchive::FileInfo& VDZipArchive::GetFileInfo(sint32 idx) {
  585.     VDASSERT((size_t)idx < mDirectory.size());
  586.     return mDirectory[idx];
  587. }
  588.  
  589. IVDStream *VDZipArchive::OpenRawStream(sint32 idx) {
  590.     const FileInfoInternal& fi = mDirectory[idx];
  591.  
  592.     mpStream->Seek(fi.mDataStart);
  593.  
  594.     ZipFileHeader hdr;
  595.     mpStream->Read(&hdr, sizeof hdr);
  596.  
  597.     if (hdr.signature != ZipFileHeader::kSignature)
  598.         throw MyError("Bad header for file in zip archive");
  599.  
  600.     mpStream->Seek(fi.mDataStart + sizeof(hdr) + hdr.filename_len + hdr.extrafield_len);
  601.  
  602.     return mpStream;
  603. }
  604.