centralDir.cpp
Engine/source/core/util/zip/centralDir.cpp
Namespaces:
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
