00001
00002
00003
00004
00005
00006 #include "stdafx.h"
00007 #include "fsZipArchiveRebuilder.h"
00008 #include <fsString.h>
00009
00010 #ifdef _DEBUG
00011 #undef THIS_FILE
00012 static char THIS_FILE[]=__FILE__;
00013 #define new DEBUG_NEW
00014 #endif
00015
00016 using namespace fsArchive;
00017
00018 fsZipArchiveRebuilder::fsZipArchiveRebuilder()
00019 {
00020
00021 }
00022
00023 fsZipArchiveRebuilder::~fsZipArchiveRebuilder()
00024 {
00025 Free ();
00026 }
00027
00028 DWORD fsZipArchiveRebuilder::RetreiveArchiveContent()
00029 {
00030 UINT32 uSig = 0;
00031 fsArchiveFilePosition position;
00032 DWORD dwPos = 0;
00033 BOOL bSkipSigRead = FALSE;
00034
00035 do
00036 {
00037 position.dwSrcBegin = dwPos;
00038 position.dwDstBegin = dwPos;
00039
00040 if (bSkipSigRead == FALSE)
00041 {
00042 if (m_in->Read (&uSig, sizeof (uSig)) != sizeof (uSig))
00043 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;
00044
00045 dwPos += sizeof (uSig);
00046 }
00047 else
00048 {
00049 position.dwSrcBegin -= sizeof (uSig);
00050 position.dwDstBegin -= sizeof (uSig);
00051
00052 bSkipSigRead = FALSE;
00053 }
00054
00055 if (uSig != ZIP_LOCALFILEHEADER_SIG)
00056 break;
00057
00058 fsZipLocalFileHeader hdr;
00059
00060 if (m_in->Read (&hdr, sizeof (hdr)) != sizeof (hdr))
00061 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00062
00063 dwPos += sizeof (hdr);
00064
00065 fsString strFileName;
00066 strFileName.alloc (hdr.wFileNameLen);
00067
00068 if (m_in->Read (strFileName, hdr.wFileNameLen) != hdr.wFileNameLen)
00069 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00070
00071 dwPos += hdr.wFileNameLen;
00072
00073 BYTE *pbExtra = NULL;
00074
00075 if (hdr.wExtraLen)
00076 {
00077 pbExtra = new BYTE [hdr.wExtraLen];
00078
00079 if (m_in->Read (pbExtra, hdr.wExtraLen) != hdr.wExtraLen)
00080 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00081
00082 dwPos += hdr.wExtraLen;
00083 }
00084
00085 fsZipLocalFile file;
00086
00087 file.hdr = hdr;
00088 file.strFileName = strFileName;
00089 file.pbExtraInfo = pbExtra;
00090 file.sigAfter = 0;
00091
00092 if (hdr.uSizeComp == 0)
00093 {
00094
00095 }
00096 else
00097 {
00098 if (-1 == m_in->Seek (hdr.uSizeComp, ST_CURRENT))
00099 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00100
00101 dwPos += hdr.uSizeComp;
00102 }
00103
00104 if (m_in->Read (&uSig, sizeof (uSig)) == sizeof (uSig) &&
00105 (uSig == ZIP_SPLIT_SIG || uSig == ZIP_TEMPSPANNINGMARKER_SIG))
00106 {
00107
00108 file.sigAfter = uSig;
00109 }
00110 else
00111 bSkipSigRead = TRUE;
00112
00113 dwPos += sizeof (uSig);
00114
00115
00116 if (hdr.wGenFlags & 0x8)
00117 {
00118 fsZipDataDescriptor hdr;
00119
00120 if (bSkipSigRead == FALSE)
00121 {
00122 if (m_in->Read (&hdr, sizeof (hdr)) != sizeof (hdr))
00123 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00124
00125 dwPos += sizeof (hdr);
00126 }
00127 else
00128 {
00129 if (m_in->Read (LPBYTE (&hdr) + 4, sizeof (hdr) - 4) != sizeof (hdr) - 4)
00130 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00131
00132 dwPos += sizeof (hdr) - 4;
00133
00134 hdr.uCRC = uSig;
00135 bSkipSigRead = FALSE;
00136 }
00137
00138 file.descriptor = hdr;
00139 }
00140
00141 if (bSkipSigRead)
00142 {
00143 position.dwSrcEnd = dwPos - sizeof (UINT32);
00144 position.dwDstEnd = dwPos - sizeof (UINT32);
00145 }
00146 else
00147 {
00148 position.dwSrcEnd = dwPos;
00149 position.dwDstEnd = dwPos;
00150 }
00151
00152 file.position = position;
00153
00154 m_vLocalFiles.add (file);
00155 }
00156 while (TRUE);
00157
00158 do
00159 {
00160 if (uSig != ZIP_FILEHEADER_SIG)
00161 break;
00162
00163 fsZipFileHeader hdr;
00164
00165 if (m_in->Read (&hdr, sizeof (hdr)) != sizeof (hdr))
00166 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00167
00168 fsString strFileName;
00169 strFileName.alloc (hdr.wFileNameLen);
00170
00171 if (m_in->Read (strFileName, hdr.wFileNameLen) != hdr.wFileNameLen)
00172 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00173
00174 BYTE *pbExtra = NULL;
00175
00176 if (hdr.wExtraLen)
00177 {
00178 pbExtra = new BYTE [hdr.wExtraLen];
00179
00180 if (m_in->Read (pbExtra, hdr.wExtraLen) != hdr.wExtraLen)
00181 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00182 }
00183
00184 fsString strComment;
00185 strComment.alloc (hdr.wFileCommentLen);
00186
00187 if (m_in->Read (strComment, hdr.wFileCommentLen) != hdr.wFileCommentLen)
00188 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00189
00190 fsZipFile file;
00191 file.hdr = hdr;
00192 file.strComment = strComment;
00193 file.pbExtraInfo = pbExtra;
00194 file.strFileName = strFileName;
00195 m_vFiles.add (file);
00196
00197
00198 if (m_in->Read (&uSig, sizeof (uSig)) != sizeof (uSig))
00199 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00200 }
00201 while (TRUE);
00202
00203 if (uSig != ZIP_ENDOFCENTRALDIR_SIG)
00204 return ARR_BADARCHIVE;
00205
00206 fsZipEndOfCentralDirHdr hdr;
00207
00208 if (m_in->Read (&hdr, sizeof (hdr)) != sizeof (hdr))
00209 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00210
00211 m_hdrEndOfCDir = hdr;
00212
00213 m_strZipComment.alloc (hdr.wZipCommentLen);
00214 if (m_in->Read (m_strZipComment, hdr.wZipCommentLen) != hdr.wZipCommentLen)
00215 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00216
00217 return NOERROR;
00218 }
00219
00220 BOOL fsZipArchiveRebuilder::RebuildArchive(fs::list <fsString> vFileNames)
00221 {
00222 for (int i = 0; i < m_vLocalFiles.size (); i++)
00223 {
00224 fsZipLocalFile* file = &m_vLocalFiles [i];
00225
00226 int iFile = vFileNames.find (file->strFileName);
00227
00228 if (iFile == -1)
00229 RemoveFile (i--);
00230 }
00231
00232 CorrectCDir ();
00233
00234 return TRUE;
00235 }
00236
00237 int fsZipArchiveRebuilder::GetFileCount()
00238 {
00239 return m_vLocalFiles.size ();
00240 }
00241
00242 fsString fsZipArchiveRebuilder::GetFileName(int iFile)
00243 {
00244 return m_vLocalFiles [iFile].strFileName;
00245 }
00246
00247 void fsZipArchiveRebuilder::RemoveFile(int iIndex)
00248 {
00249 LPCSTR pszFile = m_vLocalFiles [iIndex].strFileName;
00250
00251 int imvFilesIndex = FindFile (pszFile, iIndex);
00252 if (imvFilesIndex != -1)
00253 m_vFiles.del (imvFilesIndex);
00254
00255 m_vLocalFiles.del (iIndex);
00256 }
00257
00258 void fsZipArchiveRebuilder::CorrectCDir()
00259 {
00260 DWORD dwPos = 0;
00261
00262 for (int i = 0; i < m_vLocalFiles.size (); i++)
00263 {
00264 fsZipLocalFile* file = &m_vLocalFiles [i];
00265
00266 int j = FindFile (file->strFileName, i);
00267 if (j != -1)
00268 m_vFiles [j].hdr.uLocHdrRelOffset = dwPos + m_dwSFXSize;
00269
00270 file->position.dwDstBegin = dwPos;
00271
00272 dwPos += sizeof (UINT32) + sizeof (fsZipLocalFileHeader) +
00273 file->hdr.wFileNameLen + file->hdr.wExtraLen;
00274
00275 dwPos += file->hdr.uSizeComp;
00276
00277 if (file->sigAfter)
00278 dwPos += sizeof (UINT32);
00279
00280 if (file->hdr.wGenFlags & 0x8)
00281 dwPos += sizeof (fsZipDataDescriptor);
00282
00283 file->position.dwDstEnd = dwPos;
00284 }
00285
00286 m_hdrEndOfCDir.wcCDirEntries = (WORD) GetFileCount ();
00287 m_hdrEndOfCDir.wcFilesTotal = (WORD) GetFileCount ();
00288 m_hdrEndOfCDir.uStartCDirOffsetWithRespectToStartingDiskNumber = dwPos + m_dwSFXSize;
00289
00290 m_hdrEndOfCDir.uCDirSize = 0;
00291 for (i = 0; i < m_vFiles.size (); i++)
00292 {
00293 fsZipFile* file = &m_vFiles [i];
00294
00295 m_hdrEndOfCDir.uCDirSize += sizeof (UINT32);
00296 m_hdrEndOfCDir.uCDirSize += sizeof (fsZipFileHeader);
00297 m_hdrEndOfCDir.uCDirSize += file->hdr.wFileNameLen;
00298 m_hdrEndOfCDir.uCDirSize += file->hdr.wExtraLen;
00299 m_hdrEndOfCDir.uCDirSize += file->hdr.wFileCommentLen;
00300 }
00301
00302 dwPos += m_hdrEndOfCDir.uCDirSize;
00303 dwPos += sizeof (UINT32) + sizeof (m_hdrEndOfCDir);
00304
00305 m_uResArchiveSize = dwPos;
00306 }
00307
00308 void fsZipArchiveRebuilder::Free()
00309 {
00310 for (int i = 0; i < m_vLocalFiles.size (); i++)
00311 {
00312 if (m_vLocalFiles [i].pbExtraInfo)
00313 delete [] m_vLocalFiles [i].pbExtraInfo;
00314 }
00315
00316 m_vLocalFiles.clear ();
00317
00318 for (i = 0; i < m_vFiles.size (); i++)
00319 {
00320 if (m_vFiles [i].pbExtraInfo)
00321 delete [] m_vFiles [i].pbExtraInfo;
00322 }
00323
00324 m_vFiles.clear ();
00325 }
00326
00327 const fsArchiveFilePosition* fsZipArchiveRebuilder::GetFilePosition(int iFile)
00328 {
00329 return &m_vLocalFiles [iFile].position;
00330 }
00331
00332 int fsZipArchiveRebuilder::FindFile(LPCSTR pszFile, int iProbIndex)
00333 {
00334 int imvFilesIndex = -1;
00335
00336 if (iProbIndex != -1 && m_vFiles.size () > iProbIndex &&
00337 m_vFiles [iProbIndex].strFileName == pszFile)
00338 imvFilesIndex = iProbIndex;
00339 else
00340 {
00341 for (int j = 0; j < m_vFiles.size (); j++)
00342 {
00343 if (m_vFiles [j].strFileName == pszFile)
00344 {
00345 imvFilesIndex = j;
00346 break;
00347 }
00348 }
00349 }
00350
00351 return imvFilesIndex;
00352 }
00353
00354 DWORD fsZipArchiveRebuilder::SaveArchiveHeaders_imp()
00355 {
00356 DWORD dwRes;
00357
00358 dwRes = SaveLocalFilesHeaders ();
00359 if (dwRes != NOERROR)
00360 return dwRes;
00361
00362 dwRes = SaveFilesHeaders ();
00363 if (dwRes != NOERROR)
00364 return dwRes;
00365
00366 dwRes = SaveEndOfCDirRecord ();
00367 if (dwRes != NOERROR)
00368 return dwRes;
00369
00370 return NOERROR;
00371 }
00372
00373 DWORD fsZipArchiveRebuilder::SaveLocalFilesHeaders()
00374 {
00375 UINT32 uSig = ZIP_LOCALFILEHEADER_SIG;
00376
00377 for (int i = 0; i < m_vLocalFiles.size (); i++)
00378 {
00379 fsZipLocalFile* file = &m_vLocalFiles [i];
00380
00381 if (m_out->Write (&uSig, sizeof (uSig)) != sizeof (uSig))
00382 return ARR_STREAMERROR;
00383
00384 if (m_out->Write (&file->hdr, sizeof (file->hdr)) != sizeof (file->hdr))
00385 return ARR_STREAMERROR;
00386
00387 if (m_out->Write (file->strFileName, file->hdr.wFileNameLen) != file->hdr.wFileNameLen)
00388 return ARR_STREAMERROR;
00389
00390 if (file->hdr.wExtraLen)
00391 {
00392 if (m_out->Write (file->pbExtraInfo, file->hdr.wExtraLen) != file->hdr.wExtraLen)
00393 return ARR_STREAMERROR;
00394 }
00395
00396 if (file->hdr.uSizeComp && -1 == m_out->Seek (file->hdr.uSizeComp, ST_CURRENT))
00397 return ARR_STREAMERROR;
00398
00399 if (file->sigAfter)
00400 {
00401 if (m_out->Write (&file->sigAfter, sizeof (UINT32)) != sizeof (UINT32))
00402 return ARR_STREAMERROR;
00403 }
00404
00405 if (file->hdr.wGenFlags & 0x8)
00406 {
00407 if (m_out->Write (&file->descriptor, sizeof (file->descriptor)) != sizeof (file->descriptor))
00408 return ARR_STREAMERROR;
00409 }
00410 }
00411
00412 return NOERROR;
00413 }
00414
00415 DWORD fsZipArchiveRebuilder::SaveFilesHeaders()
00416 {
00417 UINT32 uSig = ZIP_FILEHEADER_SIG;
00418
00419 for (int i = 0; i < m_vFiles.size (); i++)
00420 {
00421 fsZipFile* file = &m_vFiles [i];
00422
00423 if (m_out->Write (&uSig, sizeof (uSig)) != sizeof (uSig))
00424 return ARR_STREAMERROR;
00425
00426 if (m_out->Write (&file->hdr, sizeof (file->hdr)) != sizeof (file->hdr))
00427 return ARR_STREAMERROR;
00428
00429 if (m_out->Write (file->strFileName, file->hdr.wFileNameLen) != file->hdr.wFileNameLen)
00430 return ARR_STREAMERROR;
00431
00432 if (file->hdr.wExtraLen)
00433 if (m_out->Write (file->pbExtraInfo, file->hdr.wExtraLen) != file->hdr.wExtraLen)
00434 return ARR_STREAMERROR;
00435
00436 if (file->hdr.wFileCommentLen)
00437 if (m_out->Write (file->strComment, file->hdr.wFileCommentLen) != file->hdr.wFileCommentLen)
00438 return ARR_STREAMERROR;
00439 }
00440
00441 return NOERROR;
00442 }
00443
00444 DWORD fsZipArchiveRebuilder::SaveEndOfCDirRecord()
00445 {
00446 UINT32 uSig = ZIP_ENDOFCENTRALDIR_SIG;
00447
00448 if (m_out->Write (&uSig, sizeof (uSig)) != sizeof (uSig))
00449 return ARR_STREAMERROR;
00450
00451 if (m_out->Write (&m_hdrEndOfCDir, sizeof (m_hdrEndOfCDir)) != sizeof (m_hdrEndOfCDir))
00452 return ARR_STREAMERROR;
00453
00454 if (m_hdrEndOfCDir.wZipCommentLen)
00455 if (m_out->Write (m_strZipComment, m_hdrEndOfCDir.wZipCommentLen) != m_hdrEndOfCDir.wZipCommentLen)
00456 return ARR_STREAMERROR;
00457
00458 return NOERROR;
00459 }