Torque3D Documentation / _generateds / zipCryptStream.cpp

zipCryptStream.cpp

Engine/source/core/util/zip/zipCryptStream.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "core/util/zip/zipCryptStream.h"
 25#include "core/util/zip/crctab.h"
 26
 27#include "console/console.h"
 28
 29//-----------------------------------------------------------------------------
 30// Constructor/Destructor
 31//-----------------------------------------------------------------------------
 32
 33ZipCryptRStream::ZipCryptRStream() : mStream(NULL), mFileEndPos(0), mPassword(NULL)
 34{
 35}
 36
 37ZipCryptRStream::~ZipCryptRStream()
 38{
 39}
 40
 41//-----------------------------------------------------------------------------
 42// Private Methods
 43//-----------------------------------------------------------------------------
 44
 45U32 ZipCryptRStream::fillBuffer(const U32 in_attemptSize, void *pBuffer)
 46{
 47   AssertFatal(mStream != NULL, "No stream to fill from?");
 48   AssertFatal(mStream->getStatus() != Stream::Closed,
 49      "Fill from a closed stream?");
 50
 51   U32 currPos    = mStream->getPosition();
 52
 53   U32 actualReadSize;
 54   if (in_attemptSize + currPos > mFileEndPos) {
 55      actualReadSize = mFileEndPos - currPos;
 56   } else {
 57      actualReadSize = in_attemptSize;
 58   }
 59
 60   if (mStream->read(actualReadSize, pBuffer) == true) {
 61      return actualReadSize;
 62   } else {
 63      AssertWarn(false, "Read failed while trying to fill buffer");
 64      return 0;
 65   }
 66}
 67
 68//-----------------------------------------------------------------------------
 69// Public Methods
 70//-----------------------------------------------------------------------------
 71
 72void ZipCryptRStream::setPassword(const char *password)
 73{
 74   mKeys[0] = 305419896;
 75   mKeys[1] = 591751049;
 76   mKeys[2] = 878082192;
 77   
 78   mPassword = password;
 79   const char *pPtr = password;
 80   while(*pPtr)
 81   {
 82      updateKeys(*pPtr);
 83      pPtr++;
 84   }
 85}
 86
 87bool ZipCryptRStream::attachStream(Stream* io_pSlaveStream)
 88{
 89   mStream = io_pSlaveStream;
 90   mStreamStartPos = mStream->getPosition();
 91
 92   // [tom, 12/20/2005] Encrypted zip files have an extra 12 bytes
 93   // of entropy before the file data.
 94
 95   U8 buffer[12];
 96   if(mStream->read(sizeof(buffer), &buffer))
 97   {
 98      // Initialize keys
 99      for(S32 i = 0;i < sizeof(buffer);i++)
100      {
101         updateKeys(buffer[i] ^= decryptByte());
102      }
103      
104      // if(buffer[11] !)
105      mFileStartPos = mStream->getPosition();
106
107      setStatus(Ok);
108      return true;
109   }
110   return false;
111}
112
113void ZipCryptRStream::detachStream()
114{
115   mStream = NULL;
116
117   // Clear keys, just in case
118   dMemset(&mKeys, 0, sizeof(mKeys));
119
120   setStatus(Closed);
121}
122
123U32 ZipCryptRStream::getPosition() const
124{
125   return mStream->getPosition();
126}
127
128bool ZipCryptRStream::setPosition(const U32 in_newPosition)
129{
130   if(in_newPosition > mFileEndPos)
131      return false;
132
133   U32 curPos = getPosition();
134   U32 readSize = in_newPosition - mFileStartPos;
135   bool ret = true;
136
137   if(in_newPosition < curPos)
138   {
139      // Reposition to start of stream
140      Stream *stream = getStream();
141      U32 startPos = mStreamStartPos;
142      const char *password = mPassword;
143      detachStream();
144      setPassword(password);
145      stream->setPosition(startPos);
146      ret = attachStream(stream);
147
148      if(in_newPosition == mFileStartPos)
149         return ret;
150   }
151
152   // Read until we reach the new position
153   U8 *buffer = new U8 [1024];
154   while(readSize >= 1024)
155   {
156      readSize -= 1024;
157      ret = _read(1024, buffer);
158      if(! ret)
159         break;
160   }
161
162   if(readSize > 0 && ret)
163   {
164      ret = _read(readSize, buffer);
165   }
166   delete [] buffer;
167
168   return ret;
169}
170
171//-----------------------------------------------------------------------------
172// Protected Methods
173//-----------------------------------------------------------------------------
174
175void ZipCryptRStream::updateKeys(const U8 c)
176{
177   mKeys[0] = ZC_CRC32(mKeys[0], c);
178   mKeys[1] += mKeys[0] & 0x000000ff;
179   mKeys[1] = mKeys[1] * 134775813 + 1;
180   U32 k = mKeys[1] >> 24;
181   mKeys[2] = ZC_CRC32(mKeys[2], k);
182}
183
184U8 ZipCryptRStream::decryptByte()
185{
186   U16 temp;
187   temp = (mKeys[2] & 0xffff) | 2;
188   return (temp * (temp ^ 1)) >> 8;
189}
190
191bool ZipCryptRStream::_read(const U32 in_numBytes, void* out_pBuffer)
192{
193   U32 numRead = fillBuffer(in_numBytes, out_pBuffer);
194   if(numRead > 0)
195   {
196      // Decrypt
197      U8 *pBytes = (U8 *)out_pBuffer;
198      for(S32 i = 0;i < numRead;i++)
199      {
200         updateKeys(pBytes[i] ^= decryptByte());
201      }
202      return true;
203   }
204   return false;
205}
206