00001
00002
00003
00004
00005
00006 #include "stdafx.h"
00007 #include "fsZipArchiveFastRebuilder.h"
00008 using namespace fsArchive;
00009
00010 #ifdef _DEBUG
00011 #undef THIS_FILE
00012 static char THIS_FILE[]=__FILE__;
00013 #define new DEBUG_NEW
00014 #endif
00015
00016 fsZipArchiveFastRebuilder::fsZipArchiveFastRebuilder()
00017 {
00018
00019 }
00020
00021 fsZipArchiveFastRebuilder::~fsZipArchiveFastRebuilder()
00022 {
00023 m_vLocalFiles.clear ();
00024 }
00025
00026 DWORD fsZipArchiveFastRebuilder::RetreiveArchiveContent()
00027 {
00028 LOG ("ZAFR: starting retreiving zip content" << nl);
00029
00030 if (m_dwFileSize == 0)
00031 {
00032 LOG ("ZAFR: err: file size is 0" << nl);
00033 return ARR_STREAMERROR;
00034 }
00035
00036 UINT32 uSig;
00037
00038 int iPosReq = m_dwFileSize - sizeof (fsZipEndOfCentralDirHdr) - 4;
00039
00040 LOG ("ZAFR: seek to eocd label" << nl);
00041
00042 if (FALSE == m_in->Seek (iPosReq, ST_BEGIN))
00043 {
00044 LOG ("ZAFR: err: failed" << nl);
00045 return ARR_STREAMERROR;
00046 }
00047
00048 LOG ("ZAFR: reading label" << nl);
00049
00050 if (m_in->Read (&uSig, sizeof (uSig)) != sizeof (uSig))
00051 {
00052 LOG ("ZAFR: err: failed to read" << nl);
00053 return ARR_STREAMERROR;
00054 }
00055
00056 fsZipEndOfCentralDirHdr ecd;
00057
00058 if (uSig != ZIP_ENDOFCENTRALDIR_SIG)
00059 {
00060
00061 LOG ("ZAFR: label not found. Do searching for label" << nl);
00062
00063 if (m_dwFileSize < 65536)
00064 {
00065 LOG ("ZAFR: err: file size is less than 65536" << nl);
00066 m_in->Seek (0, ST_BEGIN);
00067
00068 return fsZipArchiveRebuilder::RetreiveArchiveContent ();
00069 }
00070
00071 iPosReq = m_dwFileSize - (65536+sizeof (ecd)+4);
00072
00073 LOG ("ZAFR: seeking to region start" << nl);
00074
00075 if (FALSE == m_in->Seek (iPosReq, ST_BEGIN))
00076 {
00077 LOG ("ZAFR: err: failed to seek" << nl);
00078 return ARR_STREAMERROR;
00079 }
00080
00081 BYTE arbBuf [65536+sizeof (ecd)+4];
00082
00083 LOG ("ZAFR: reading region" << nl);
00084
00085 if (sizeof (arbBuf) != m_in->Read (arbBuf, sizeof (arbBuf)))
00086 {
00087 LOG ("ZAFR: failed to read" << nl);
00088 return ARR_STREAMERROR;
00089 }
00090
00091 LOG ("ZAFR: performing searching" << nl);
00092
00093 LPBYTE pS = arbBuf, pE = pS + sizeof (arbBuf) - 4 - sizeof (ecd);
00094
00095 while (pS < pE)
00096 {
00097 if (*(LPUINT (pS)) == ZIP_ENDOFCENTRALDIR_SIG)
00098 break;
00099
00100 pS++;
00101 }
00102
00103 if (pS == pE)
00104 {
00105 LOG ("ZAFR: err: label was not found" << nl);
00106 m_in->Seek (0, ST_BEGIN);
00107 return fsZipArchiveRebuilder::RetreiveArchiveContent ();
00108 }
00109
00110 LOG ("ZAFR: label was found" << nl);
00111
00112 pS += 4;
00113 CopyMemory (&ecd, pS, sizeof (ecd));
00114 pS += sizeof (ecd);
00115
00116 m_strZipComment.alloc (ecd.wZipCommentLen);
00117 CopyMemory (m_strZipComment, pS, ecd.wZipCommentLen);
00118 }
00119 else
00120 {
00121 LOG ("ZAFR: reading eocdr" << nl);
00122
00123 if (m_in->Read (&ecd, sizeof (ecd)) != sizeof (ecd))
00124 {
00125 LOG ("ZAFR: err: failed to read" << nl);
00126 return ARR_STREAMERROR;
00127 }
00128
00129 LOG ("ZAFR: reading ZIP comment" << nl);
00130
00131 m_strZipComment.alloc (ecd.wZipCommentLen);
00132 if (m_in->Read (m_strZipComment, ecd.wZipCommentLen) != ecd.wZipCommentLen)
00133 {
00134 LOG ("ZAFR: err: failed to read" << nl);
00135 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00136 }
00137 }
00138
00139 LOG ("ZAFR: files total: " << (int)ecd.wcFilesTotal << nl);
00140 LOG ("ZAFR: cdir size: " << (int)ecd.uCDirSize << nl);
00141
00142 m_hdrEndOfCDir = ecd;
00143
00144 LOG ("ZAFR: ZIP size is: " << m_dwFileSize << nl);
00145 LOG ("ZAFR: CDir start is: " << (int)ecd.uStartCDirOffsetWithRespectToStartingDiskNumber << nl);
00146
00147 LOG ("ZAFR: seek to cdir start" << nl);
00148
00149 if (FALSE == m_in->Seek (ecd.uStartCDirOffsetWithRespectToStartingDiskNumber, ST_BEGIN))
00150 {
00151 LOG ("ZAFR: err: failed to seek" << nl);
00152 return ARR_STREAMERROR;
00153 }
00154
00155 LOG ("ZAFR: do main loop" << nl);
00156
00157 for (int i = 0; i < ecd.wcCDirEntries; i++)
00158 {
00159 if (m_in->Read (&uSig, sizeof (uSig)) != sizeof (uSig))
00160 {
00161 LOG ("ZAFR: loop: err: failed to read label" << nl);
00162 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00163 }
00164
00165 if (uSig != ZIP_FILEHEADER_SIG)
00166 {
00167 LOG ("ZAFR: loop: err: unknown label" << nl);
00168 return ARR_BADARCHIVE;
00169 }
00170
00171 fsZipFileHeader hdr;
00172
00173 if (m_in->Read (&hdr, sizeof (hdr)) != sizeof (hdr))
00174 {
00175 LOG ("ZAFR: loop: err: failed to read header" << nl);
00176 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00177 }
00178
00179 fsString strFileName;
00180 strFileName.alloc (hdr.wFileNameLen);
00181
00182 if (m_in->Read (strFileName, hdr.wFileNameLen) != hdr.wFileNameLen)
00183 {
00184 LOG ("ZAFR: loop: err: failed to read file name" << nl);
00185 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00186 }
00187
00188 LOG ("ZAFR: loop: File found: " << strFileName << nl);
00189
00190 BYTE *pbExtra = NULL;
00191
00192 if (hdr.wExtraLen)
00193 {
00194 pbExtra = new BYTE [hdr.wExtraLen];
00195
00196 if (m_in->Read (pbExtra, hdr.wExtraLen) != hdr.wExtraLen)
00197 {
00198 LOG ("ZAFR: loop: err: failed to read extra info" << nl);
00199 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;;
00200 }
00201 }
00202
00203 fsString strComment;
00204 strComment.alloc (hdr.wFileCommentLen);
00205
00206 if (m_in->Read (strComment, hdr.wFileCommentLen) != hdr.wFileCommentLen)
00207 {
00208 LOG ("ZAFR: loop: err: failed to read comment" << nl);
00209 return m_in->GetLastError () != ASE_NOMOREDATA ? ARR_STREAMERROR : ARR_BADARCHIVE;
00210 }
00211
00212 fsZipFile file;
00213 file.hdr = hdr;
00214 file.strComment = strComment;
00215 file.pbExtraInfo = pbExtra;
00216 file.strFileName = strFileName;
00217 m_vFiles.add (file);
00218
00219 fsZipLocalFile locfile;
00220 locfile.position.dwSrcBegin = locfile.position.dwDstBegin = hdr.uLocHdrRelOffset;
00221 m_vLocalFiles.add (locfile);
00222
00223 if (m_vLocalFiles.size () > 1)
00224 {
00225 fsZipLocalFile* prev = &m_vLocalFiles [m_vLocalFiles.size ()-2];
00226 prev->position.dwDstEnd = prev->position.dwSrcEnd = locfile.position.dwDstBegin;
00227 }
00228
00229 }
00230
00231 fsZipLocalFile* lf = &m_vLocalFiles [m_vLocalFiles.size ()-1];
00232 lf->position.dwSrcEnd = lf->position.dwDstEnd = ecd.uStartCDirOffsetWithRespectToStartingDiskNumber;
00233
00234 LOG ("ZAFR: ZIP content was retreived with no errors." << nl);
00235
00236 return NOERROR;
00237 }
00238
00239 int fsZipArchiveFastRebuilder::GetFileCount()
00240 {
00241 return m_vFiles.size ();
00242 }
00243
00244 fsString fsZipArchiveFastRebuilder::GetFileName(int iIndex)
00245 {
00246 return m_vFiles [iIndex].strFileName;
00247 }
00248
00249 void fsZipArchiveFastRebuilder::RemoveFile(int iIndex)
00250 {
00251 m_vLocalFiles.del (iIndex);
00252 m_vFiles.del (iIndex);
00253 }
00254
00255 BOOL fsZipArchiveFastRebuilder::RebuildArchive(fs::list <fsString> vFileNames)
00256 {
00257 for (int i = 0; i < m_vFiles.size (); i++)
00258 {
00259 fsZipFile* file = &m_vFiles [i];
00260
00261 int iFile = vFileNames.find (file->strFileName);
00262
00263 if (iFile == -1)
00264 RemoveFile (i--);
00265 }
00266
00267 CorrectCDir ();
00268
00269 return TRUE;
00270 }
00271
00272 void fsZipArchiveFastRebuilder::CorrectCDir()
00273 {
00274 DWORD dwPos = 0;
00275 m_hdrEndOfCDir.uCDirSize = 0;
00276
00277 for (int i = 0; i < m_vFiles.size (); i++)
00278 {
00279 fsZipFile* file = &m_vFiles [i];
00280 fsZipLocalFile* lf = &m_vLocalFiles [i];
00281
00282 lf->position.dwDstBegin = dwPos;
00283 file->hdr.uLocHdrRelOffset = dwPos;
00284
00285 DWORD dwSize = lf->position.dwSrcEnd - lf->position.dwSrcBegin;
00286 dwPos += dwSize;
00287 lf->position.dwDstEnd = dwPos;
00288
00289 m_hdrEndOfCDir.uCDirSize += sizeof (UINT32);
00290 m_hdrEndOfCDir.uCDirSize += sizeof (fsZipFileHeader);
00291 m_hdrEndOfCDir.uCDirSize += file->hdr.wFileNameLen;
00292 m_hdrEndOfCDir.uCDirSize += file->hdr.wExtraLen;
00293 m_hdrEndOfCDir.uCDirSize += file->hdr.wFileCommentLen;
00294 }
00295
00296 m_hdrEndOfCDir.wcCDirEntries = (WORD) GetFileCount ();
00297 m_hdrEndOfCDir.wcFilesTotal = (WORD) GetFileCount ();
00298 m_hdrEndOfCDir.uStartCDirOffsetWithRespectToStartingDiskNumber = dwPos + m_dwSFXSize;
00299
00300 dwPos += m_hdrEndOfCDir.uCDirSize;
00301 dwPos += sizeof (UINT32) + sizeof (m_hdrEndOfCDir);
00302
00303 m_uResArchiveSize = dwPos;
00304 }
00305
00306 DWORD fsZipArchiveFastRebuilder::SaveArchiveHeaders_imp()
00307 {
00308 DWORD dwRes;
00309
00310 if (FALSE == m_out->Seek (m_hdrEndOfCDir.uStartCDirOffsetWithRespectToStartingDiskNumber, ST_BEGIN))
00311 return ARR_STREAMERROR;
00312
00313 dwRes = SaveFilesHeaders ();
00314 if (dwRes != NOERROR)
00315 return dwRes;
00316
00317 dwRes = SaveEndOfCDirRecord ();
00318 if (dwRes != NOERROR)
00319 return dwRes;
00320
00321 return NOERROR;
00322 }