centralDir.cpp

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

More...

Namespaces:

namespace

Namespace for the zip code.

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/stream/stream.h"
 25#include "core/strings/stringFunctions.h"
 26
 27#include "core/util/zip/centralDir.h"
 28#include "core/util/zip/compressor.h"
 29
 30#include "core/util/safeDelete.h"
 31
 32namespace Zip
 33{
 34
 35//-----------------------------------------------------------------------------
 36// CentralDir Class
 37//-----------------------------------------------------------------------------
 38
 39CentralDir::CentralDir()
 40{
 41   mHeaderSig = mCentralDirSignature;
 42
 43   mDiskNumStart = 0;
 44
 45   mInternalFileAttr = 0;
 46   mExternalFileAttr = 0;
 47
 48   mLocalHeadOffset = 0;
 49   
 50   mVersionMadeBy = 0;
 51
 52   mFileComment = NULL;
 53
 54   mInternalFlags = 0;
 55}
 56
 57CentralDir::CentralDir(FileHeader &fh) : FileHeader(fh)
 58{
 59   mHeaderSig = mCentralDirSignature;
 60
 61   mDiskNumStart = 0;
 62
 63   mInternalFileAttr = 0;
 64   mExternalFileAttr = 0;
 65
 66   mLocalHeadOffset = 0;
 67
 68   mVersionMadeBy = 0;
 69
 70   mFileComment = NULL;
 71}
 72
 73CentralDir::~CentralDir()
 74{
 75   SAFE_DELETE_ARRAY(mFileComment);
 76}
 77
 78//-----------------------------------------------------------------------------
 79
 80bool CentralDir::read(Stream *stream)
 81{
 82   stream->read(&mHeaderSig);
 83   if(mHeaderSig != mCentralDirSignature)
 84      return false;
 85
 86   stream->read(&mVersionMadeBy);
 87   stream->read(&mExtractVer);
 88   stream->read(&mFlags);
 89   stream->read(&mCompressMethod);
 90   stream->read(&mModTime);
 91   stream->read(&mModDate);
 92   stream->read(&mCRC32);
 93   stream->read(&mCompressedSize);
 94   stream->read(&mUncompressedSize);
 95
 96   U16 fnLen, efLen, fcLen;
 97   stream->read(&fnLen);
 98   stream->read(&efLen);
 99   stream->read(&fcLen);
100
101   stream->read(&mDiskNumStart);
102
103   stream->read(&mInternalFileAttr);
104   stream->read(&mExternalFileAttr);
105
106   stream->read(&mLocalHeadOffset);
107
108   char *fn = new char[fnLen + 1];
109   stream->read(fnLen, fn);
110   fn[fnLen] = 0;
111   mFilename = String(fn);
112   SAFE_DELETE_ARRAY(fn);
113   
114
115   // [tom, 10/28/2006] We currently only need the extra fields when we want to
116   // open the file, so we won't bother reading them here. This avoids keeping
117   // them in memory twice.
118
119   //readExtraFields(stream, efLen);
120   stream->setPosition(stream->getPosition() + efLen);
121
122   fn = new char[fcLen + 1];
123   stream->read(fcLen, fn);
124   fn[fcLen] = 0;
125
126   SAFE_DELETE_ARRAY(mFileComment);
127   mFileComment = fn;
128
129   // Sanity checks to make life easier elsewhere
130   if(mCompressMethod != Stored && mUncompressedSize == 0 && mCompressedSize == 0)
131      mCompressMethod = Stored;
132
133   return true;
134}
135
136bool CentralDir::write(Stream *stream)
137{
138   mHeaderSig = mCentralDirSignature;
139   stream->write(mHeaderSig);
140
141   stream->write(mVersionMadeBy);
142   stream->write(mExtractVer);
143   stream->write(mFlags);
144   stream->write(mCompressMethod);
145   stream->write(mModTime);
146   stream->write(mModDate);
147   stream->write(mCRC32);
148   stream->write(mCompressedSize);
149   stream->write(mUncompressedSize);
150
151   U16 fnLen = mFilename.length(),
152       efLen = 0,
153       fcLen = mFileComment ? (U16)dStrlen(mFileComment) : 0;
154   stream->write(fnLen);
155   stream->write(efLen);
156   stream->write(fcLen);
157
158   stream->write(mDiskNumStart);
159
160   stream->write(mInternalFileAttr);
161   stream->write(mExternalFileAttr);
162
163   stream->write(mLocalHeadOffset);
164
165   if(fnLen)
166      stream->write(fnLen, mFilename);
167
168   // FIXME [tom, 10/29/2006] Write extra fields here
169
170   if(fcLen)
171      stream->write(fcLen, mFileComment);
172
173   return true;
174}
175
176//-----------------------------------------------------------------------------
177
178void CentralDir::setFileComment(const char *comment)
179{
180   SAFE_DELETE_ARRAY(mFileComment);
181   mFileComment = new char [dStrlen(comment)+1];
182   dStrcpy(mFileComment, comment);
183}
184
185//-----------------------------------------------------------------------------
186// EndOfCentralDir Class
187//-----------------------------------------------------------------------------
188
189EndOfCentralDir::EndOfCentralDir()
190{
191   mHeaderSig = mEOCDSignature;
192
193   mDiskNum = 0;
194   mStartCDDiskNum = 0;
195   mNumEntriesInThisCD = 0;
196   mTotalEntriesInCD = 0;
197   mCDSize = 0;
198   mCDOffset = 0;
199   mCommentSize = 0;
200   mZipComment = NULL;
201}
202
203EndOfCentralDir::~EndOfCentralDir()
204{
205   SAFE_DELETE_ARRAY(mZipComment);
206}
207
208//-----------------------------------------------------------------------------
209
210bool EndOfCentralDir::read(Stream *stream)
211{
212   stream->read(&mHeaderSig);
213   if(mHeaderSig != mEOCDSignature)
214      return false;
215
216   stream->read(&mDiskNum);
217   stream->read(&mStartCDDiskNum);
218   stream->read(&mNumEntriesInThisCD);
219   stream->read(&mTotalEntriesInCD);
220   stream->read(&mCDSize);
221   stream->read(&mCDOffset);
222
223   stream->read(&mCommentSize);
224   
225   char *comment = new char[mCommentSize + 1];
226   stream->read(mCommentSize, comment);
227   comment[mCommentSize] = 0;
228
229   SAFE_DELETE_ARRAY(mZipComment);
230   mZipComment = comment;
231
232   return true;
233}
234
235bool EndOfCentralDir::write(Stream *stream)
236{
237   stream->write(mHeaderSig);
238
239   stream->write(mDiskNum);
240   stream->write(mStartCDDiskNum);
241   stream->write(mNumEntriesInThisCD);
242   stream->write(mTotalEntriesInCD);
243   stream->write(mCDSize);
244   stream->write(mCDOffset);
245
246   stream->write(mCommentSize);
247   if(mZipComment && mCommentSize)
248      stream->write(mCommentSize, mZipComment);
249
250   return true;
251}
252
253//-----------------------------------------------------------------------------
254
255// [tom, 10/19/2006] I know, i know ... this'll get rewritten.
256// [tom, 1/23/2007] Maybe.
257
258bool EndOfCentralDir::findInStream(Stream *stream)
259{
260   U32 initialPos = stream->getPosition();
261   U32 size = stream->getStreamSize();
262   U32 pos;
263   if(size == 0)
264      return false;
265
266   if(! stream->setPosition(size - mRecordSize))
267      goto hell;
268
269   U32 sig;
270   stream->read(&sig);
271
272   if(sig == mEOCDSignature)
273   {
274      stream->setPosition(size - mRecordSize);
275      return true;
276   }
277
278   // OK, so we couldn't find the EOCD where we expected it. The zip file
279   // either has comments or isn't a zip file. We need to search the last
280   // 64Kb of the file for the EOCD.
281
282   pos = size > mEOCDSearchSize ? size - mEOCDSearchSize : 0;
283   if(! stream->setPosition(pos))
284      goto hell;
285
286   while(pos < (size - 4))
287   {
288      stream->read(&sig);
289
290      if(sig == mEOCDSignature)
291      {
292         stream->setPosition(pos);
293         return true;
294      }
295
296      pos++;
297      if(! stream->setPosition(pos))
298         goto hell;
299   }
300
301hell:
302   stream->setPosition(initialPos);
303   return false;
304}
305
306//-----------------------------------------------------------------------------
307
308void EndOfCentralDir::setZipComment(U16 commentSize, const char *zipComment)
309{
310   SAFE_DELETE_ARRAY(mZipComment);
311   mZipComment = new char [commentSize];
312   dMemcpy((void *)mZipComment, zipComment, commentSize);
313   mCommentSize = commentSize;
314}
315
316void EndOfCentralDir::setZipComment(const char *zipComment)
317{
318   setZipComment(dStrlen(zipComment), zipComment);
319}
320
321} // end namespace Zip
322