📄 ziparchive.cpp
字号:
{
TRACE(_T("%s(%i) : Cannot flush an existing disk spanning archive.\n"),__FILE__,__LINE__);
return;
}
WriteCentralDirectory();
m_storage.FlushFile();
if (m_storage.IsSpanMode() > 0) // try to finalize disk-spanning archive without closing it
m_storage.FinalizeSpan();
}
void CZipArchive::GetCentralDirInfo(CZipCentralDir::Info& info)const
{
if (IsClosed())
{
TRACE(_T("%s(%i) : ZipArchive not yet opened.\n"),__FILE__,__LINE__);
return;
}
m_centralDir.GetInfo(info);
if (GetSpanMode() > 0)
info.m_uDiskEntriesNo = m_storage.GetCurrentDisk();
}
bool CZipArchive::CWildcard::IsPatternValid(LPCTSTR lpszPattern, int* iErrorType)
{
try
{
/* loop through pattern to EOS */
while (*lpszPattern)
{
/* determine pattern type */
switch (*lpszPattern)
{
/* check literal escape, it cannot be at end of pattern */
case _T('\\'):
if (!*++lpszPattern)
throw patternEsc;
lpszPattern++;
break;
/* the [..] construct must be well formed */
case _T('['):
lpszPattern++;
/* if the next character is ']' then bad pattern */
if (*lpszPattern == _T(']'))
throw patternEmpty;
/* if end of pattern here then bad pattern */
if (!*lpszPattern)
throw patternClose;
/* loop to end of [..] construct */
while (*lpszPattern != _T(']'))
{
/* check for literal escape */
if (*lpszPattern == _T('\\'))
{
lpszPattern++;
/* if end of pattern here then bad pattern */
if (!*lpszPattern++)
throw patternEsc;
}
else lpszPattern++;
/* if end of pattern here then bad pattern */
if (!*lpszPattern)
throw patternClose;
/* if this a range */
if (*lpszPattern == _T('-'))
{
/* we must have an end of range */
if (!*++lpszPattern || *lpszPattern == ']')
throw patternRange;
else
{
/* check for literal escape */
if (*lpszPattern == _T('\\'))
lpszPattern++;
/* if end of pattern here
then bad pattern */
if (!*lpszPattern++)
throw patternEsc;
}
}
}
break;
/* all other characters are valid pattern elements */
case '*':
case '?':
default:
lpszPattern++; /* "normal" character */
break;
}
}
throw patternValid;
}
catch (int i)
{
if (iErrorType)
*iErrorType = i;
return i == patternValid;
}
}
bool CZipArchive::CWildcard::IsPattern(LPCTSTR lpszPattern)
{
while (*lpszPattern)
{
switch (*lpszPattern++)
{
case _T('?'):
case _T('*'):
case _T('['):
case _T('\\'):
return true;
}
}
return false;
}
bool CZipArchive::CWildcard::IsMatch(LPCTSTR lpszText, int *iRetCode)
{
CZipString sz;
if (!m_bCaseSensitive)
{
sz = lpszText;
sz.MakeLower();
lpszText = (LPCTSTR)sz;
}
int i = Match((LPCTSTR)m_szPattern, lpszText);
if (iRetCode)
*iRetCode = i;
return i == matchValid;
}
int CZipArchive::CWildcard::MatchAfterStar(LPCTSTR p, LPCTSTR t)
{
int iMatch = matchNone;
TCHAR nextp;
/* pass over existing ? and * in pattern */
while ( *p == _T('?') || *p == _T('*') )
{
/* take one char for each ? and + */
if (*p == _T('?'))
{
/* if end of text then no match */
if (!*t++)
return matchAbort;
}
/* move to next char in pattern */
p++;
}
/* if end of pattern we have matched regardless of text left */
if (!*p)
return matchValid;
/* get the next character to match which must be a literal or '[' */
nextp = *p;
if (nextp == _T('\\'))
{
nextp = p[1];
/* if end of text then we have a bad pattern */
if (!nextp)
return matchPattern;
}
/* Continue until we run out of text or definite result seen */
do
{
/* a precondition for matching is that the next character
in the pattern match the next character in the text or that
the next pattern char is the beginning of a range. Increment
text pointer as we go here */
if (nextp == *t || nextp == _T('['))
iMatch = Match(p, t);
/* if the end of text is reached then no iMatch */
if (!*t++)
iMatch = matchAbort;
} while ( iMatch != matchValid &&
iMatch != matchAbort &&
iMatch != matchPattern);
/* return result */
return iMatch;
}
int CZipArchive::CWildcard::Match(LPCTSTR lpszPattern, LPCTSTR lpszText)
{
TCHAR range_start, range_end; /* start and end in range */
bool bInvert; /* is this [..] or [!..] */
bool bMemberMatch; /* have I matched the [..] construct? */
bool bLoop; /* should I terminate? */
for ( ; *lpszPattern; lpszPattern++, lpszText++)
{
/* if this is the end of the text
then this is the end of the match */
if (!*lpszText)
{
if ( *lpszPattern == _T('*') && *++lpszPattern == _T('\0') )
return matchValid;
else
return matchAbort;
}
/* determine and react to pattern type */
switch (*lpszPattern)
{
case _T('?'): /* single any character match */
break;
case _T('*'): /* multiple any character match */
return MatchAfterStar (lpszPattern, lpszText);
/* [..] construct, single member/exclusion character match */
case _T('['):
{
/* move to beginning of range */
lpszPattern++;
/* check if this is a member match or exclusion match */
bInvert = false;
if (*lpszPattern == _T('!') || *lpszPattern == _T('^'))
{
bInvert = true;
lpszPattern++;
}
/* if closing bracket here or at range start then we have a
malformed pattern */
if (*lpszPattern == _T(']'))
return matchPattern;
bMemberMatch = false;
bLoop = true;
while (bLoop)
{
/* if end of construct then bLoop is done */
if (*lpszPattern == _T(']'))
{
bLoop = false;
continue;
}
/* matching a '!', '^', '-', '\' or a ']' */
if (*lpszPattern == _T('\\'))
range_start = range_end = *++lpszPattern;
else
range_start = range_end = *lpszPattern;
/* if end of pattern then bad pattern (Missing ']') */
if (!*lpszPattern)
return matchPattern;
/* check for range bar */
if (*++lpszPattern == _T('-'))
{
/* get the range end */
range_end = *++lpszPattern;
/* if end of pattern or construct
then bad pattern */
if (range_end == _T('\0') || range_end == _T(']'))
return matchPattern;
/* special character range end */
if (range_end == _T('\\'))
{
range_end = *++lpszPattern;
/* if end of text then
we have a bad pattern */
if (!range_end)
return matchPattern;
}
/* move just beyond this range */
lpszPattern++;
}
/* if the text character is in range then match found.
make sure the range letters have the proper
relationship to one another before comparison */
if (range_start < range_end)
{
if (*lpszText >= range_start && *lpszText <= range_end)
{
bMemberMatch = true;
bLoop = false;
}
}
else
{
if (*lpszText >= range_end && *lpszText <= range_start)
{
bMemberMatch = true;
bLoop = false;
}
}
}
/* if there was a match in an exclusion set then no match */
/* if there was no match in a member set then no match */
if ((bInvert && bMemberMatch) || !(bInvert || bMemberMatch))
return matchRange;
/* if this is not an exclusion then skip the rest of
the [...] construct that already matched. */
if (bMemberMatch)
{
while (*lpszPattern != _T(']'))
{
/* bad pattern (Missing ']') */
if (!*lpszPattern)
return matchPattern;
/* skip exact match */
if (*lpszPattern == _T('\\'))
{
lpszPattern++;
/* if end of text then
we have a bad pattern */
if (!*lpszPattern)
return matchPattern;
}
/* move to next pattern char */
lpszPattern++;
}
}
break;
}
case _T('\\'): /* next character is quoted and must match exactly */
/* move pattern pointer to quoted char and fall through */
lpszPattern++;
/* if end of text then we have a bad pattern */
if (!*lpszPattern)
return matchPattern;
/* must match this character exactly */
default:
if (*lpszPattern != *lpszText)
return matchPattern;
}
}
/* if end of text not reached then the pattern fails */
if (*lpszText)
return matchEnd;
else
return matchValid;
}
void CZipArchive::FindMatches(LPCTSTR lpszPattern, CZipWordArray &ar, bool bFullPath) const
{
if (IsClosed())
{
TRACE(_T("%s(%i) : ZipArchive is closed.\n"),__FILE__,__LINE__);
return;
}
// ar.RemoveAll(); don't do this
int iCount = GetCount();
CWildcard wc(lpszPattern, m_bCaseSensitive);
for (int i = 0; i < iCount; i++)
{
const CZipFileHeader* pHeader = m_centralDir[i];
CZipString sz = m_centralDir.GetProperHeaderFileName(pHeader);
if (!bFullPath)
{
CZipPathComponent::RemoveSeparators(sz);
CZipPathComponent zpc(sz);
sz = zpc.GetFileName();
}
if (wc.IsMatch(sz))
ar.Add(i);
}
}
int CZipArchive::WillBeDuplicated(LPCTSTR lpszFilePath, bool bFullPath, bool bFileNameOnly , int iWhat)
{
CZipString szFile;
// we predict with bExactly set to false, because FindFile converts all filanames anyway
if (bFileNameOnly)
{
CZipPathComponent zpc(lpszFilePath);
szFile = PredictFileNameInZip(zpc.GetFileName(), false, iWhat);
}
else
szFile = PredictFileNameInZip(lpszFilePath, bFullPath, iWhat);
return FindFile(szFile, ffDefault, bFileNameOnly);
}
// it'll get up to the next file or to the end of file (bad if zip corrupted or not-ordered by offsett or redundant bytes added)
bool CZipArchive::GetFromArchive(CZipArchive& zip, WORD uIndex, int iReplaceIndex, bool bKeepSystComp, CZipActionCallback* pCallback)
{
if (IsClosed() || zip.IsClosed())
{
TRACE(_T("%s(%i) : ZipArchive is closed.\n"),__FILE__,__LINE__);
return false;
}
if (m_iFileOpened || zip.m_iFileOpened)
{
TRACE(_T("%s(%i) : You cannot get files from another archive if there is a file opened.\n"),__FILE__,__LINE__);
return false;
}
if (zip.m_storage.IsSpanMode())
{
TRACE(_T("%s(%i) : You cannot get files from the disk spannig archive.\n"),__FILE__,__LINE__);
return false;
}
if (m_storage.IsSpanMode() == -1)
{
TRACE(_T("%s(%i) : You cannot add files to the existing disk spannig archive.\n"),__FILE__,__LINE__);
return false;
}
ASSERT(m_info.m_pBuffer.GetSize() > 0);
bool bIsSpan = m_storage.IsSpanMode() == 1;
CZipFileHeader fh;
if (!zip.GetFileInfo(fh, uIndex))
return false;
CZipAbstractFile* pFile = zip.m_storage.m_pFile;
DWORD uEndOffset;
if (uIndex < zip.GetCount() - 1)
{
CZipFileHeader fhTemp;
if (!zip.GetFileInfo(fhTemp, uIndex+1))
return false;
uEndOffset = fhTemp.m_uOffset;
}
else
{
CZipCentralDir::Info info;
zip.m_centralDir.GetInfo(info);
if (info.m_bOnDisk)
uEndOffset = info.m_uOffset;
else
uEndOffset = pFile->GetLength();
}
uEndOffset += zip.m_centralDir.GetBytesBefore();
DWORD uStartOffset = zip.m_centralDir.GetBytesBefore() + fh.m_uOffset + fh.GetSize(true);
DWORD uTotalToMove = uEndOffset - uStartOffset, uTotalMoved = 0;
DWORD uPredictedSize = fh.m_uComprSize +
(fh.IsDataDescr() ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -