diff options
Diffstat (limited to 'CPP')
68 files changed, 938 insertions, 289 deletions
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index b0c6b98c..d8c27175 100644 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -1097,7 +1097,10 @@ HRESULT CInArchive::ReadAndDecodePackedStreams( if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) ThrowIncorrect(); } - HeadersSize += folders.PackPositions[folders.NumPackStreams]; + + if (folders.PackPositions) + HeadersSize += folders.PackPositions[folders.NumPackStreams]; + return S_OK; } diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 4e74fa33..68e57f09 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -38,7 +38,7 @@ struct CFilterMode { if (Id == k_IA64) Delta = 16; - else if (Id == k_ARM || Id == k_PPC || Id == k_PPC) + else if (Id == k_ARM || Id == k_PPC || Id == k_SPARC) Delta = 4; else if (Id == k_ARMT) Delta = 2; @@ -779,7 +779,7 @@ struct CSolidGroup CRecordVector<CFolderRepack> folderRefs; }; -static const char *g_ExeExts[] = +static const char * const g_ExeExts[] = { "dll" , "exe" diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 5f145739..18f58b3d 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -168,7 +168,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidVolumeIndex: { - if (m_Database.Volumes.Size() == 1) + if (!m_Database.Volumes.IsEmpty()) { const CDatabaseEx &db = m_Database.Volumes[0]; const CInArcInfo &ai = db.ArcInfo; diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp index 1c3c7c45..4543b067 100644 --- a/CPP/7zip/Archive/ElfHandler.cpp +++ b/CPP/7zip/Archive/ElfHandler.cpp @@ -156,7 +156,7 @@ bool CHeader::Parse(const Byte *p) #define PT_PHDR 6 -static const char *g_SegnmentTypes[] = +static const char * const g_SegnmentTypes[] = { "Unused", "Loadable segment", @@ -554,13 +554,31 @@ static const CUInt32PCharPair g_OS[] = { 255, "Standalone" } }; +#define k_Machine_ARM 40 + +/* +#define EF_ARM_ABIMASK 0xFF000000 +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_GCCMASK 0x00400FFF +#define EF_ARM_ABI_FLOAT_SOFT 0x00000200 +#define EF_ARM_ABI_FLOAT_HARD 0x00000400 +*/ + +static const CUInt32PCharPair g_ARM_Flags[] = +{ + { 9, "SF" }, + { 10, "HF" }, + { 23, "BE8" } +}; + + #define ET_NONE 0 #define ET_REL 1 #define ET_EXEC 2 #define ET_DYN 3 #define ET_CORE 4 -static const char *g_Types[] = +static const char * const g_Types[] = { "None", "Relocatable file", @@ -569,6 +587,9 @@ static const char *g_Types[] = "Core file" }; + + + class CHandler: public IInArchive, public IArchiveAllowTail, @@ -659,7 +680,29 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) case kpidBit64: if (_header.Mode64) prop = _header.Mode64; break; case kpidBigEndian: if (_header.Be) prop = _header.Be; break; case kpidShortComment: - case kpidCpu: PAIR_TO_PROP(g_Machines, _header.Machine, prop); break; + + case kpidCpu: + { + AString s = TypePairToString(g_Machines, ARRAY_SIZE(g_Machines), _header.Machine); + UInt32 flags = _header.Flags; + if (flags != 0) + { + char sz[16]; + s.Add_Space(); + if (_header.Machine == k_Machine_ARM) + { + s += FlagsToString(g_ARM_Flags, ARRAY_SIZE(g_ARM_Flags), flags & (((UInt32)1 << 24) - 1)); + s += " ABI:"; + ConvertUInt32ToString(flags >> 24, sz); + } + else + ConvertUInt32ToHex(flags, sz); + s += sz; + } + prop = s; + break; + } + case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break; case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break; case kpidExtension: diff --git a/CPP/7zip/Archive/FlvHandler.cpp b/CPP/7zip/Archive/FlvHandler.cpp index 72ccd993..1f52f60b 100644 --- a/CPP/7zip/Archive/FlvHandler.cpp +++ b/CPP/7zip/Archive/FlvHandler.cpp @@ -93,7 +93,7 @@ static const Byte kProps[] = IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO_Table -static const char *g_AudioTypes[16] = +static const char * const g_AudioTypes[16] = { "pcm" , "adpcm" @@ -113,7 +113,7 @@ static const char *g_AudioTypes[16] = , "audio15" }; -static const char *g_VideoTypes[16] = +static const char * const g_VideoTypes[16] = { "video0" , "jpeg" @@ -133,7 +133,7 @@ static const char *g_VideoTypes[16] = , "video15" }; -static const char *g_Rates[4] = +static const char * const g_Rates[4] = { "5.5 kHz" , "11 kHz" diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp index 53e941c7..52c7aab9 100644 --- a/CPP/7zip/Archive/GptHandler.cpp +++ b/CPP/7zip/Archive/GptHandler.cpp @@ -244,9 +244,31 @@ HRESULT CHandler::Open2(IInStream *stream) _items.Add(item); } - UInt64 end = (backupLba + 1) * kSectorSize; - if (_totalSize < end) - _totalSize = end; + { + const UInt64 end = (backupLba + 1) * kSectorSize; + if (_totalSize < end) + _totalSize = end; + } + + { + UInt64 fileEnd; + RINOK(stream->Seek(0, STREAM_SEEK_END, &fileEnd)); + + if (_totalSize < fileEnd) + { + const UInt64 rem = fileEnd - _totalSize; + const UInt64 kRemMax = 1 << 22; + if (rem <= kRemMax) + { + RINOK(stream->Seek(_totalSize, STREAM_SEEK_SET, NULL)); + bool areThereNonZeros = false; + UInt64 numZeros = 0; + if (ReadZeroTail(stream, areThereNonZeros, numZeros, kRemMax) == S_OK) + if (!areThereNonZeros) + _totalSize += numZeros; + } + } + } return S_OK; } diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index abf8bef6..185df7f0 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp @@ -507,7 +507,7 @@ HRESULT CHeaderRec::Parse(const Byte *p) // LeafRecords = Get32(p + 6); FirstLeafNode = Get32(p + 0xA); // LastLeafNode = Get32(p + 0xE); - UInt32 nodeSize = Get16(p + 0x12); + const UInt32 nodeSize = Get16(p + 0x12); unsigned i; for (i = 9; ((UInt32)1 << i) != nodeSize; i++) @@ -583,9 +583,9 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec for (unsigned i = 0; i < desc.NumRecords; i++) { - UInt32 nodeSize = (UInt32)1 << hr.NodeSizeLog; - UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); + const UInt32 nodeSize = (UInt32)1 << hr.NodeSizeLog; + const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); + const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); if (offs > nodeSize || offsNext > nodeSize) return S_FALSE; UInt32 recSize = offsNext - offs; @@ -727,12 +727,12 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe for (unsigned i = 0; i < desc.NumRecords; i++) { - UInt32 nodeSize = (1 << hr.NodeSizeLog); - UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); + const UInt32 nodeSize = (1 << hr.NodeSizeLog); + const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); + const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); UInt32 recSize = offsNext - offs; if (offs >= nodeSize - || offsNext >= nodeSize + || offsNext > nodeSize || offsNext < offs) return S_FALSE; @@ -898,7 +898,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents return S_FALSE; usedBuf[node] = 1; - size_t nodeOffset = (size_t)node << hr.NodeSizeLog; + const size_t nodeOffset = (size_t)node << hr.NodeSizeLog; CNodeDescriptor desc; desc.Parse(p + nodeOffset); if (!desc.CheckNumRecords(hr.NodeSizeLog)) @@ -908,12 +908,12 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents for (unsigned i = 0; i < desc.NumRecords; i++) { - UInt32 nodeSize = (1 << hr.NodeSizeLog); - UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); - UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); + const UInt32 nodeSize = (1 << hr.NodeSizeLog); + const UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2); + const UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2); UInt32 recSize = offsNext - offs; if (offs >= nodeSize - || offs >= nodeSize + || offsNext > nodeSize || offsNext < offs || recSize < 6) return S_FALSE; diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index 14aec498..5a19516c 100644 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -30,7 +30,14 @@ static const Byte kProps[] = kpidIsDir, kpidSize, kpidPackSize, - kpidMTime + kpidMTime, + // kpidCTime, + // kpidATime, + kpidPosixAttrib, + // kpidUser, + // kpidGroup, + // kpidLinks, + kpidSymLink }; static const Byte kArcProps[] = @@ -213,17 +220,87 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = s; } break; + + case kpidSymLink: + if (_archive.IsSusp) + { + UString s; + UInt32 mode; + if (item.GetPx(_archive.SuspSkipSize, k_Px_Mode, mode)) + { + if (((mode >> 12) & 0xF) == 10) + { + AString s8; + if (item.GetSymLink(_archive.SuspSkipSize, s8)) + { + s = MultiByteToUnicodeString(s8, CP_OEMCP); + prop = s; + } + } + } + } + break; + + + case kpidPosixAttrib: + /* + case kpidLinks: + case kpidUser: + case kpidGroup: + */ + { + if (_archive.IsSusp) + { + UInt32 t = 0; + switch (propID) + { + case kpidPosixAttrib: t = k_Px_Mode; break; + /* + case kpidLinks: t = k_Px_Links; break; + case kpidUser: t = k_Px_User; break; + case kpidGroup: t = k_Px_Group; break; + */ + } + UInt32 v; + if (item.GetPx(_archive.SuspSkipSize, t, v)) + prop = v; + } + break; + } + case kpidIsDir: prop = item.IsDir(); break; case kpidSize: case kpidPackSize: if (!item.IsDir()) prop = (UInt64)ref.TotalSize; break; + case kpidMTime: + // case kpidCTime: + // case kpidATime: { FILETIME utc; - if (item.DateTime.GetFileTime(utc)) + if (/* propID == kpidMTime && */ item.DateTime.GetFileTime(utc)) prop = utc; + /* + else + { + UInt32 t = 0; + switch (propID) + { + case kpidMTime: t = k_Tf_MTime; break; + case kpidCTime: t = k_Tf_CTime; break; + case kpidATime: t = k_Tf_ATime; break; + } + CRecordingDateTime dt; + if (item.GetTf(_archive.SuspSkipSize, t, dt)) + { + FILETIME utc; + if (dt.GetFileTime(utc)) + prop = utc; + } + } + */ break; } } @@ -321,8 +398,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 offset = 0; for (UInt32 e = 0; e < ref.NumExtents; e++) { - lps->InSize = lps->OutSize = currentTotalSize + offset; const CDir &item2 = ref.Dir->_subItems[ref.Index + e]; + if (item2.Size == 0) + continue; + lps->InSize = lps->OutSize = currentTotalSize + offset; RINOK(_stream->Seek((UInt64)item2.ExtentLocation * kBlockSize, STREAM_SEEK_SET, NULL)); streamSpec->Init(item2.Size); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index 1ebc15e8..8530a25e 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -608,7 +608,7 @@ HRESULT CInArchive::Open2() for (UInt32 j = 0; j < ref.NumExtents; j++) { const CDir &item = ref.Dir->_subItems[ref.Index + j]; - if (!item.IsDir()) + if (!item.IsDir() && item.Size != 0) UpdatePhySize(item.ExtentLocation, item.Size); } } diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index ce154264..c4950e60 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -3,6 +3,8 @@ #ifndef __ARCHIVE_ISO_ITEM_H #define __ARCHIVE_ISO_ITEM_H +#include "../../../../C/CpuArch.h" + #include "../../../Common/MyString.h" #include "../../../Common/MyBuffer.h" @@ -38,6 +40,32 @@ struct CRecordingDateTime } }; +enum EPx +{ + k_Px_Mode, + k_Px_Links, + k_Px_User, + k_Px_Group, + k_Px_SerialNumber + + // k_Px_Num +}; + +/* +enum ETf +{ + k_Tf_CTime, + k_Tf_MTime, + k_Tf_ATime, + k_Tf_Attrib, + k_Tf_Backup, + k_Tf_Expiration, + k_Tf_Effective + + // k_Tf_Num +}; +*/ + struct CDirRecord { UInt32 ExtentLocation; @@ -69,7 +97,8 @@ struct CDirRecord return (b == 0 || b == 1); } - const Byte* FindSuspName(unsigned skipSize, unsigned &lenRes) const + + const Byte* FindSuspRecord(unsigned skipSize, Byte id0, Byte id1, unsigned &lenRes) const { lenRes = 0; if (SystemUse.Size() < skipSize) @@ -81,12 +110,12 @@ struct CDirRecord unsigned len = p[2]; if (len < 3 || len > rem) return 0; - if (p[0] == 'N' && p[1] == 'M' && p[3] == 1) + if (p[0] == id0 && p[1] == id1 && p[3] == 1) { - if (len < 5) + if (len < 4) return 0; // Check it - lenRes = len - 5; - return p + 5; + lenRes = len - 4; + return p + 4; } p += len; rem -= len; @@ -94,17 +123,23 @@ struct CDirRecord return 0; } + const Byte* GetNameCur(bool checkSusp, int skipSize, unsigned &nameLenRes) const { const Byte *res = NULL; unsigned len = 0; if (checkSusp) - res = FindSuspName(skipSize, len); - if (!res) + res = FindSuspRecord(skipSize, 'N', 'M', len); + if (!res || len < 1) { res = (const Byte *)FileId; len = (unsigned)FileId.Size(); } + else + { + res++; + len--; + } unsigned i; for (i = 0; i < len; i++) if (res[i] == 0) @@ -114,6 +149,141 @@ struct CDirRecord } + const bool GetSymLink(int skipSize, AString &link) const + { + link.Empty(); + const Byte *p = NULL; + unsigned len = 0; + p = FindSuspRecord(skipSize, 'S', 'L', len); + if (!p || len < 1) + return false; + + if (*p != 0) + return false; + + p++; + len--; + + while (len != 0) + { + if (len < 2) + return false; + unsigned flags = p[0]; + unsigned cl = p[1]; + p += 2; + len -= 2; + + if (cl > len) + return false; + + bool needSlash = false; + + if (flags & (1 << 1)) link += "./"; + else if (flags & (1 << 2)) link += "../"; + else if (flags & (1 << 3)) link += '/'; + else + needSlash = true; + + for (unsigned i = 0; i < cl; i++) + { + char c = p[i]; + if (c == 0) + { + break; + // return false; + } + link += c; + } + + p += cl; + len -= cl; + + if (len == 0) + break; + + if (needSlash) + link += '/'; + } + + return true; + } + + static const bool GetLe32Be32(const Byte *p, UInt32 &dest) + { + UInt32 v1 = GetUi32(p); + UInt32 v2 = GetBe32(p + 4); + if (v1 == v2) + { + dest = v1; + return true; + } + return false; + } + + + const bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const + { + const Byte *p = NULL; + unsigned len = 0; + p = FindSuspRecord(skipSize, 'P', 'X', len); + if (!p) + return false; + // px.Clear(); + if (len < ((unsigned)pxType + 1) * 8) + return false; + + return GetLe32Be32(p + pxType * 8, val); + } + + /* + const bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const + { + const Byte *p = NULL; + unsigned len = 0; + p = FindSuspRecord(skipSize, 'T', 'F', len); + if (!p) + return false; + if (len < 1) + return false; + Byte flags = *p++; + len--; + + unsigned step = 7; + if (flags & 0x80) + { + step = 17; + return false; + } + + if ((flags & (1 << pxType)) == 0) + return false; + + for (unsigned i = 0; i < pxType; i++) + { + if (len < step) + return false; + if (flags & (1 << i)) + { + p += step; + len -= step; + } + } + + if (len < step) + return false; + + t.Year = p[0]; + t.Month = p[1]; + t.Day = p[2]; + t.Hour = p[3]; + t.Minute = p[4]; + t.Second = p[5]; + t.GmtOffset = (signed char)p[6]; + + return true; + } + */ + bool CheckSusp(const Byte *p, unsigned &startPos) const { if (p[0] == 'S' && diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp index 9dae1e70..26260686 100644 --- a/CPP/7zip/Archive/MachoHandler.cpp +++ b/CPP/7zip/Archive/MachoHandler.cpp @@ -75,7 +75,7 @@ static const CUInt32PCharPair g_CpuPairs[] = #define SECT_ATTR_ZEROFILL 1 -static const char *g_SectTypes[] = +static const char * const g_SectTypes[] = { "REGULAR" , "ZEROFILL" @@ -108,7 +108,7 @@ enum EFileType kType_DSYM }; -static const char *g_FileTypes[] = +static const char * const g_FileTypes[] = { "0" , "OBJECT" @@ -124,7 +124,7 @@ static const char *g_FileTypes[] = }; -static const char *g_ArcFlags[] = +static const char * const g_ArcFlags[] = { "NOUNDEFS" , "INCRLINK" diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp index 0bbf6094..daf3df6e 100644 --- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp +++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp @@ -12,7 +12,6 @@ #include "../../Compress/BcjCoder.h" #include "../../Compress/BZip2Decoder.h" -#include "../../Compress/DeflateDecoder.h" #define Get32(p) GetUi32(p) @@ -27,12 +26,16 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) if (Method != _curMethod) Release(); _curMethod = Method; + if (!_codecInStream) { switch (Method) { // case NMethodType::kCopy: return E_NOTIMPL; - case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break; + case NMethodType::kDeflate: + _deflateDecoder = new NCompress::NDeflate::NDecoder::CCOMCoder(); + _codecInStream = _deflateDecoder; + break; case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break; case NMethodType::kLZMA: _lzmaDecoder = new NCompress::NLzma::CDecoder(); @@ -42,6 +45,9 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter) } } + if (Method == NMethodType::kDeflate) + _deflateDecoder->SetNsisMode(IsNsisDeflate); + if (FilterFlag) { Byte flag; @@ -199,9 +205,8 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp if (outBuf) { - if (!unpackSizeDefined) - return S_FALSE; - outBuf->Alloc(unpackSize); + if (unpackSizeDefined) + outBuf->Alloc(unpackSize); } UInt64 inSizeStart = 0; @@ -213,6 +218,8 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp unpackSize = 0xFFFFFFFF; UInt32 offset = 0; + HRESULT res = S_OK; + for (;;) { size_t rem = unpackSize - offset; @@ -225,11 +232,25 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp if (size == 0) { if (unpackSizeDefined) - return S_FALSE; + res = S_FALSE; break; } + if (outBuf) + { + size_t nextSize = offset + size; + if (outBuf->Size() < nextSize) + { + { + const size_t nextSize2 = outBuf->Size() * 2; + if (nextSize < nextSize2) + nextSize = nextSize2; + } + outBuf->ChangeSize_KeepData(nextSize, offset); + } memcpy((Byte *)*outBuf + (size_t)offset, Buffer, size); + } + StreamPos += size; offset += (UInt32)size; @@ -243,9 +264,17 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp UInt64 outSize = offset; RINOK(progress->SetRatioInfo(&inSize, &outSize)); if (realOutStream) - RINOK(WriteStream(realOutStream, Buffer, size)); + { + res = WriteStream(realOutStream, Buffer, size); + if (res != S_OK) + break; + } } - return S_OK; + + if (outBuf && offset != outBuf->Size()) + outBuf->ChangeSize_KeepData(offset, offset); + + return res; } }} diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h index 7b22181e..ec713d05 100644 --- a/CPP/7zip/Archive/Nsis/NsisDecode.h +++ b/CPP/7zip/Archive/Nsis/NsisDecode.h @@ -8,6 +8,7 @@ #include "../../Common/FilterCoder.h" #include "../../Common/StreamUtils.h" +#include "../../Compress/DeflateDecoder.h" #include "../../Compress/LzmaDecoder.h" namespace NArchive { @@ -37,6 +38,7 @@ class CDecoder CMyComPtr<ISequentialInStream> _codecInStream; CMyComPtr<ISequentialInStream> _decoderInStream; + NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoder; NCompress::NLzma::CDecoder *_lzmaDecoder; public: @@ -46,9 +48,16 @@ public: NMethodType::EEnum Method; bool FilterFlag; bool Solid; + bool IsNsisDeflate; CByteBuffer Buffer; // temp buf. + CDecoder(): + FilterFlag(false), + Solid(true), + IsNsisDeflate(true) + {} + void Release() { _filterInStream.Release(); diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index e04a97a8..a3bfcaec 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -175,7 +175,7 @@ static const CCommandInfo k_Commands[kNumCmds] = { 0 }, // "BringToFront" }, { 2 }, // "SetDetailsView" }, { 2 }, // "SetFileAttributes" }, - { 2 }, // CreateDirectory, SetOutPath + { 3 }, // CreateDirectory, SetOutPath { 3 }, // "IfFileExists" }, { 3 }, // SetRebootFlag, ... { 4 }, // "If" }, // IfAbort, IfSilent, IfErrors, IfRebootFlag @@ -1395,7 +1395,7 @@ void CInArchive::AddRegRoot(UInt32 val) Script += s; } -static const char *g_WinAttrib[] = +static const char * const g_WinAttrib[] = { "READONLY" , "HIDDEN" @@ -3362,6 +3362,11 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) #ifdef NSIS_SCRIPT s += isSetOutPath ? "SetOutPath" : "CreateDirectory"; AddParam(params[0]); + if (params[2] != 0) + { + SmallSpaceComment(); + s += "CreateRestrictedDirectory"; + } #endif break; @@ -3378,11 +3383,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) params[2] == 0 && params[3] == 0) { - if (IsVarStr(params[1], kVar_OUTDIR)) - { - spec_outdir_U = UPrefixes.Back(); // outdir_U; - spec_outdir_A = APrefixes.Back();// outdir_A; - } + spec_outdir_U = UPrefixes.Back(); // outdir_U; + spec_outdir_A = APrefixes.Back(); // outdir_A; } } @@ -5045,6 +5047,9 @@ HRESULT CInArchive::Parse() DetectNsisType(bhEntries, _data + bhEntries.Offset); + Decoder.IsNsisDeflate = (NsisType != k_NsisType_Nsis3); + + #ifdef NSIS_SCRIPT { @@ -5606,6 +5611,9 @@ HRESULT CInArchive::Open2(const Byte *sig, size_t size) Decoder.Method = Method; Decoder.FilterFlag = FilterFlag; Decoder.Solid = IsSolid; + + Decoder.IsNsisDeflate = true; // we need some smart check that NSIS is not NSIS3 here. + Decoder.InputStream = _stream; Decoder.Buffer.Alloc(kInputBufSize); Decoder.StreamPos = 0; diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index 93e9f88f..a6350944 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -2157,7 +2157,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data return S_OK; const CItem &item = Items[index]; const CMftRec &rec = Recs[item.RecIndex]; - if (rec.SiAttr.SecurityId >= 0) + if (rec.SiAttr.SecurityId > 0) { UInt64 offset; UInt32 size; @@ -2169,6 +2169,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data } } } + return S_OK; } diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 51087166..7175cef3 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -321,7 +321,7 @@ bool COptHeader::Parse(const Byte *p, UInt32 size) if (NumDirItems > (1 << 16)) return false; pos += 4; - if (pos + 8 * NumDirItems != size) + if (pos + 8 * NumDirItems > size) return false; for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++) DirItems[i].Parse(p + pos + i * 8); diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index 5ddfae3f..3bcb2862 100644 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -959,7 +959,7 @@ static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *src *srcLen = 0; const Byte *destStart = dest; const Byte *srcStart = src; - unsigned mode = 2; + unsigned mode = 0; { if (srcRem == 0) @@ -970,7 +970,7 @@ static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *src src++; srcRem--; b -= 17; - mode = (b < 4 ? 0 : 1); + mode = (b < 4 ? 1 : 4); if (b > srcRem || b > destRem) return S_FALSE; srcRem -= b; @@ -988,6 +988,7 @@ static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *src UInt32 b = *src++; srcRem--; UInt32 len, back; + if (b >= 64) { srcRem--; @@ -996,7 +997,7 @@ static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *src } else if (b < 16) { - if (mode == 2) + if (mode == 0) { if (b == 0) { @@ -1013,21 +1014,23 @@ static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *src } } } + b += 3; if (b > srcRem || b > destRem) return S_FALSE; srcRem -= b; destRem -= b; - mode = 1; + mode = 4; do *dest++ = *src++; while (--b); continue; } + srcRem--; back = (b >> 2) + (*src++ << 2); len = 2; - if (mode == 1) + if (mode == 4) { back += (1 << 11); len = 3; @@ -1038,6 +1041,7 @@ static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *src UInt32 bOld = b; b = (b < 32 ? 7 : 31); len = bOld & b; + if (len == 0) { for (len = b;; len += 255) @@ -1053,6 +1057,7 @@ static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *src } } } + len += 2; if (srcRem < 2) return S_FALSE; @@ -1062,38 +1067,39 @@ static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *src srcRem -= 2; if (bOld < 32) { + back += ((bOld & 8) << 11); if (back == 0) { *destLen = dest - destStart; *srcLen = src - srcStart; return S_OK; } - back += ((bOld & 8) << 11) + (1 << 14) - 1; + back += (1 << 14) - 1; } } + back++; if (len > destRem || (size_t)(dest - destStart) < back) return S_FALSE; destRem -= len; Byte *destTemp = dest - back; dest += len; + do { *(destTemp + back) = *destTemp; destTemp++; } while (--len); + b &= 3; + mode = b; if (b == 0) - { - mode = 2; continue; - } if (b > srcRem || b > destRem) return S_FALSE; srcRem -= b; destRem -= b; - mode = 0; *dest++ = *src++; if (b > 1) { diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp index 77d2ad7d..06ed2106 100644 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -646,7 +646,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } -static const char *g_TagDesc[92] = +static const char * const g_TagDesc[92] = { "End" , "ShowFrame" diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index 14cf3e59..baa43c79 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -72,6 +72,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) break; } + case kpidWarningFlags: + { + if (_warning) + prop = kpv_ErrorFlags_HeadersError; + break; + } + case kpidCodePage: { const char *name = NULL; @@ -98,7 +105,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item) { item.HeaderPos = _phySize; - RINOK(ReadItem(stream, filled, item, _error)); + EErrorType error; + HRESULT res = ReadItem(stream, filled, item, error); + if (error == k_ErrorType_Warning) + _warning = true; + else if (error != k_ErrorType_OK) + _error = error; + RINOK(res); if (filled) { /* @@ -233,6 +246,7 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) STDMETHODIMP CHandler::Close() { _isArc = false; + _warning = false; _error = k_ErrorType_OK; _phySizeDefined = false; diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h index 42d57d45..eb9c049e 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.h +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -37,6 +37,7 @@ private: UInt64 _headersSize; bool _phySizeDefined; EErrorType _error; + bool _warning; bool _isArc; // bool _isSparse; diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp index 429a8afe..0b67a285 100644 --- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -75,7 +75,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt { COM_TRY_BEGIN - if ((_stream && (_error != k_ErrorType_OK /* || _isSparse */)) || _seqStream) + if ((_stream && (_error != k_ErrorType_OK || _warning /* || _isSparse */)) || _seqStream) return E_NOTIMPL; CObjectVector<CUpdateItem> updateItems; UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage); diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 80200c3b..57e18ac0 100644 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -328,13 +328,63 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE return S_OK; } + +static HRESULT ReadDataToString(ISequentialInStream *stream, CItemEx &item, AString &s, EErrorType &error) +{ + const unsigned packSize = (unsigned)item.GetPackSizeAligned(); + size_t processedSize = packSize; + HRESULT res = ReadStream(stream, s.GetBuf(packSize), &processedSize); + item.HeaderSize += (unsigned)processedSize; + s.ReleaseBuf_CalcLen((unsigned)item.PackSize); + RINOK(res); + if (processedSize != packSize) + error = k_ErrorType_UnexpectedEnd; + return S_OK; +} + +static bool ParsePaxLongName(const AString &src, AString &dest) +{ + dest.Empty(); + for (unsigned pos = 0;;) + { + if (pos >= src.Len()) + return false; + const char *start = src.Ptr(pos); + const char *end; + const UInt32 lineLen = ConvertStringToUInt32(start, &end); + if (end == start) + return false; + if (*end != ' ') + return false; + if (lineLen > src.Len() - pos) + return false; + unsigned offset = (unsigned)(end - start) + 1; + if (lineLen < offset) + return false; + if (IsString1PrefixedByString2(src.Ptr(pos + offset), "path=")) + { + offset += 5; // "path=" + dest = src.Mid(pos + offset, lineLen - offset); + if (dest.IsEmpty()) + return false; + if (dest.Back() != '\n') + return false; + dest.DeleteBack(); + return true; + } + pos += lineLen; + } +} + HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErrorType &error) { item.HeaderSize = 0; + bool flagL = false; bool flagK = false; AString nameL; AString nameK; + AString pax; for (;;) { @@ -363,18 +413,11 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro return S_OK; if (item.PackSize > (1 << 14)) return S_OK; - unsigned packSize = (unsigned)item.GetPackSizeAligned(); - char *buf = name->GetBuf(packSize); - size_t processedSize = packSize; - HRESULT res = ReadStream(stream, buf, &processedSize); - item.HeaderSize += (unsigned)processedSize; - name->ReleaseBuf_CalcLen((unsigned)item.PackSize); - RINOK(res); - if (processedSize != packSize) - { - error = k_ErrorType_UnexpectedEnd; + + RINOK(ReadDataToString(stream, item, *name, error)); + if (error != k_ErrorType_OK) return S_OK; - } + continue; } @@ -385,6 +428,14 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro case 'X': { // pax Extended Header + if (item.Name.IsPrefixedBy("PaxHeader/")) + { + RINOK(ReadDataToString(stream, item, pax, error)); + if (error != k_ErrorType_OK) + return S_OK; + continue; + } + break; } case NFileHeader::NLinkFlag::kDumpDir: @@ -415,6 +466,16 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro } error = k_ErrorType_OK; + + if (!pax.IsEmpty()) + { + AString name; + if (ParsePaxLongName(pax, name)) + item.Name = name; + else + error = k_ErrorType_Warning; + } + return S_OK; } } diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h index a67b1dbd..1c508bcc 100644 --- a/CPP/7zip/Archive/Tar/TarIn.h +++ b/CPP/7zip/Archive/Tar/TarIn.h @@ -15,6 +15,7 @@ enum EErrorType k_ErrorType_OK, k_ErrorType_Corrupted, k_ErrorType_UnexpectedEnd, + k_ErrorType_Warning }; HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, EErrorType &error); diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp index 80692493..ff0737a0 100644 --- a/CPP/7zip/Archive/UefiHandler.cpp +++ b/CPP/7zip/Archive/UefiHandler.cpp @@ -225,7 +225,7 @@ enum FV_FILETYPE_FFS_PAD = 0xF0 }; -static const char *g_FileTypes[] = +static const char * const g_FileTypes[] = { "ALL" , "RAW" diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index 27d3298a..234780dd 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -298,7 +298,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) AString res; - bool numMethods = 0; + unsigned numMethods = 0; + for (unsigned i = 0; i < ARRAY_SIZE(k_Methods); i++) { if (methodMask & ((UInt32)1 << i)) diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp index 59196b18..96386809 100644 --- a/CPP/7zip/Archive/XarHandler.cpp +++ b/CPP/7zip/Archive/XarHandler.cpp @@ -255,13 +255,13 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren if (encodingItem.IsTag) { AString s = encodingItem.GetPropVal("style"); - if (s.Len() >= 0) + if (!s.IsEmpty()) { - AString appl = "application/"; + const AString appl = "application/"; if (s.IsPrefixedBy(appl)) { s.DeleteFrontal(appl.Len()); - AString xx = "x-"; + const AString xx = "x-"; if (s.IsPrefixedBy(xx)) { s.DeleteFrontal(xx.Len()); @@ -365,12 +365,12 @@ HRESULT CHandler::Open2(IInStream *stream) { const CFile &file = _files[i]; file.UpdateTotalPackSize(totalPackSize); - if (file.Name == "Payload") + if (file.Name == "Payload" || file.Name == "Content") { _mainSubfile = i; numMainFiles++; } - if (file.Name == "PackageInfo") + else if (file.Name == "PackageInfo") _is_pkg = true; } @@ -723,7 +723,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) static const Byte k_Signature[] = { 'x', 'a', 'r', '!', 0, 0x1C }; REGISTER_ARC_I( - "Xar", "xar pkg", 0, 0xE1, + "Xar", "xar pkg xip", 0, 0xE1, k_Signature, 0, 0, diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp index aa06c4f8..8a8de511 100644 --- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -276,7 +276,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt EXTERNAL_CODECS_VARS m_Items, updateItems, outStream, m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock, - &options, callback); + options, callback); COM_TRY_END2 } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index c71c40fd..6361dc5c 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -1454,7 +1454,10 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback) if (result == S_FALSE || !ZipStream) { if (MissingName.IsEmpty()) + { + MissingZip = true; MissingName = volName; + } return S_OK; } @@ -1988,6 +1991,12 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items) if (!IsMultiVol) { + if (EcdVolIndex == 0 && Vols.MissingZip && Vols.StartIsExe) + { + Vols.MissingName.Empty(); + Vols.MissingZip = false; + } + UseDisk_in_SingleVol = true; if (localsWereRead) diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h index 9b10905e..9b0afe28 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.h +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -139,6 +139,7 @@ public: bool StartIsZ; // is .zip or .zNN bool StartIsZip; // is .zip bool IsUpperCase; + bool MissingZip; Int32 StartVolIndex; // = (NN - 1), if StartStream is .zNN Int32 StartParsingVol; // if we need local parsing, we must use that stream @@ -173,6 +174,7 @@ public: BaseName.Empty(); MissingName.Empty(); + MissingZip = false; ecd_wasRead = false; Streams.Clear(); diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp index 8cb123e6..bc50c1d7 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -584,7 +584,7 @@ static HRESULT Update2( CInArchive *inArchive, const CObjectVector<CItemEx> &inputItems, CObjectVector<CUpdateItem> &updateItems, - const CCompressionMethodMode *options, + const CCompressionMethodMode &options, const CByteBuffer *comment, IArchiveUpdateCallback *updateCallback) { @@ -629,17 +629,15 @@ static HRESULT Update2( UInt64 totalComplexity = complexity; - CAddCommon compressor(*options); + CAddCommon compressor(options); complexity = 0; - CCompressionMethodMode options2; - if (options != 0) - options2 = *options; + CCompressionMethodMode options2 = options; #ifndef _7ZIP_ST - UInt32 numThreads = options->NumThreads; + UInt32 numThreads = options.NumThreads; const UInt32 kNumMaxThreads = 64; if (numThreads > kNumMaxThreads) numThreads = kNumMaxThreads; @@ -652,12 +650,12 @@ static HRESULT Update2( const size_t kMemPerThread = (1 << 25); const size_t kBlockSize = 1 << 16; - bool mtMode = ((options != 0) && (numThreads > 1)); + bool mtMode = (numThreads > 1); if (numFilesToCompress <= 1) mtMode = false; - Byte method = options->MethodSequence.Front(); + Byte method = options.MethodSequence.Front(); if (!mtMode) { @@ -670,7 +668,7 @@ static HRESULT Update2( } else { - if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined) + if (method == NFileHeader::NCompressionMethod::kStored && !options.PasswordIsDefined) numThreads = 1; if (method == NFileHeader::NCompressionMethod::kBZip2) { @@ -855,16 +853,16 @@ static HRESULT Update2( if (isDir) { - WriteDirHeader(archive, options, ui, item); + WriteDirHeader(archive, &options, ui, item); } else { if (lastRealStreamItemIndex < (int)itemIndex) { lastRealStreamItemIndex = itemIndex; - SetFileHeader(archive, *options, ui, item); + SetFileHeader(archive, options, ui, item); // file Size can be 64-bit !!! - archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode()); + archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options.IsRealAesMode()); } CMemBlocks2 &memRef = refs.Refs[itemIndex]; @@ -874,12 +872,12 @@ static HRESULT Update2( CMyComPtr<IOutStream> outStream; archive.CreateStreamForCompressing(&outStream); memRef.WriteToStream(memManager.GetBlockSize(), outStream); - SetFileHeader(archive, *options, ui, item); + SetFileHeader(archive, options, ui, item); // the BUG was fixed in 9.26: // SetItemInfoFromCompressingResult must be after SetFileHeader // to write correct Size. SetItemInfoFromCompressingResult(memRef.CompressingResult, - options->IsRealAesMode(), options->AesKeyMode, item); + options.IsRealAesMode(), options.AesKeyMode, item); archive.WriteLocalHeader_And_SeekToNextFile(item); // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); memRef.FreeOpt(&memManager); @@ -920,9 +918,9 @@ static HRESULT Update2( { RINOK(threadInfo.OutStreamSpec->WriteToRealStream()); threadInfo.OutStreamSpec->ReleaseOutStream(); - SetFileHeader(archive, *options, ui, item); + SetFileHeader(archive, options, ui, item); SetItemInfoFromCompressingResult(threadInfo.CompressingResult, - options->IsRealAesMode(), options->AesKeyMode, item); + options.IsRealAesMode(), options.AesKeyMode, item); archive.WriteLocalHeader_And_SeekToNextFile(item); } else @@ -1173,7 +1171,7 @@ HRESULT Update( CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, CInArchive *inArchive, bool removeSfx, - CCompressionMethodMode *compressionMethodMode, + const CCompressionMethodMode &compressionMethodMode, IArchiveUpdateCallback *updateCallback) { if (inArchive) diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h index 054db668..15cbf69d 100644 --- a/CPP/7zip/Archive/Zip/ZipUpdate.h +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -51,7 +51,7 @@ HRESULT Update( CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, CInArchive *inArchive, bool removeSfx, - CCompressionMethodMode *compressionMethodMode, + const CCompressionMethodMode &compressionMethodMode, IArchiveUpdateCallback *updateCallback); }} diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index 5ca288f4..178753e5 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -749,11 +749,10 @@ static int main2(int numArgs, const char *args[]) } } - if (!stdOutMode) - Print_Size("Output size: ", outStreamSpec->ProcessedSize); - if (outStreamSpec) { + if (!stdOutMode) + Print_Size("Output size: ", outStreamSpec->ProcessedSize); if (outStreamSpec->Close() != S_OK) throw "File closing error"; } diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp index 4f55d013..b21b9e84 100644 --- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp +++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp @@ -804,6 +804,15 @@ SOURCE=..\..\..\..\C\Delta.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\DllSecur.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp index d74f472d..d828922f 100644 --- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp +++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp @@ -24,6 +24,8 @@ #include "../../MyVersion.h" +#include "../../../../C/DllSecur.h" + using namespace NWindows; using namespace NFile; using namespace NDir; @@ -103,7 +105,7 @@ static const wchar_t *kUniversalWildcard = L"*"; static const int kCommandIndex = 0; static const char *kHelpString = - "\nUsage: 7zSFX [<command>] [<switches>...]\n" + "\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\n" "\n" "<Commands>\n" // " l: List contents of archive\n" @@ -222,13 +224,6 @@ void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError); } -void AddToCensorFromNonSwitchesStrings(NWildcard::CCensor &wildcardCensor, - const UStringVector & /* nonSwitchStrings */, NRecursedType::EEnum type, - bool /* thereAreSwitchIncludeWildcards */) -{ - AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, type); -} - #ifndef _WIN32 static void GetArguments(int numArgs, const char *args[], UStringVector &parts) @@ -248,6 +243,11 @@ int Main2( #endif ) { + #ifdef _WIN32 + // do we need load Security DLLs for console program? + LoadSecurityDlls(); + #endif + #if defined(_WIN32) && !defined(UNDER_CE) SetFileApisToOEM(); #endif @@ -283,9 +283,16 @@ int Main2( commandStrings.Delete(0); NCommandLineParser::CParser parser(kNumSwitches); + try { - parser.ParseStrings(kSwitchForms, commandStrings); + if (!parser.ParseStrings(kSwitchForms, commandStrings)) + { + g_StdOut << "Command line error:" << endl + << parser.ErrorMessage << endl + << parser.ErrorLine << endl; + return NExitCode::kUserError; + } } catch(...) { @@ -297,19 +304,23 @@ int Main2( PrintHelp(); return 0; } + const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; - int numNonSwitchStrings = nonSwitchStrings.Size(); + unsigned curCommandIndex = 0; CArchiveCommand command; - if (numNonSwitchStrings == 0) + if (nonSwitchStrings.IsEmpty()) command.CommandType = NCommandType::kFullExtract; else { - if (numNonSwitchStrings > 1) - PrintHelpAndExit(); - if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command)) - PrintHelpAndExit(); + const UString &cmd = nonSwitchStrings[curCommandIndex]; + if (!ParseArchiveCommand(cmd, command)) + { + g_StdOut << "ERROR: Unknown command:" << endl << cmd << endl; + return NExitCode::kUserError; + } + curCommandIndex = 1; } @@ -318,11 +329,17 @@ int Main2( NWildcard::CCensor wildcardCensor; - bool thereAreSwitchIncludeWildcards; - thereAreSwitchIncludeWildcards = false; - - AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType, - thereAreSwitchIncludeWildcards); + { + if (nonSwitchStrings.Size() == curCommandIndex) + AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, recursedType); + for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++) + { + const UString &s = nonSwitchStrings[curCommandIndex]; + if (s.IsEmpty()) + throw "Empty file path"; + AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType); + } + } bool yesToAll = parser[NKey::kYes].ThereIs; diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile index f1cd2f57..4c201c00 100644 --- a/CPP/7zip/Bundles/SFXCon/makefile +++ b/CPP/7zip/Bundles/SFXCon/makefile @@ -4,6 +4,7 @@ CFLAGS = $(CFLAGS) \ -DEXTRACT_ONLY \ -DNO_READ_FROM_CODER \ -D_SFX \ + -D_CONSOLE \ CURRENT_OBJS = \ $O\SfxCon.obj \ @@ -114,6 +115,7 @@ C_OBJS = \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ + $O\DllSecur.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ $O\Ppmd7.obj \ diff --git a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp index ba41fd1a..b1592993 100644 --- a/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp +++ b/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp @@ -55,8 +55,7 @@ struct CThreadExtracting Result = ArchiveLink.Open2(options, ExtractCallbackSpec); if (Result != S_OK) { - if (Result != S_OK) - ErrorMessage = kCantOpenArchive; + ErrorMessage = kCantOpenArchive; return; } diff --git a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp index f2783e02..787c1bde 100644 --- a/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp +++ b/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp @@ -706,6 +706,15 @@ SOURCE=..\..\..\..\C\Delta.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\DllSecur.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index 68e28eda..aef2e196 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp @@ -23,6 +23,8 @@ #include "ExtractEngine.h" +#include "../../../../C/DllSecur.h" + #include "resource.h" using namespace NWindows; @@ -135,6 +137,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, NT_CHECK + #ifdef _WIN32 + LoadSecurityDlls(); + #endif + // InitCommonControls(); UString archiveName, switches; diff --git a/CPP/7zip/Bundles/SFXSetup/makefile b/CPP/7zip/Bundles/SFXSetup/makefile index 5f6f6032..5849cf36 100644 --- a/CPP/7zip/Bundles/SFXSetup/makefile +++ b/CPP/7zip/Bundles/SFXSetup/makefile @@ -100,6 +100,7 @@ C_OBJS = \ $O\BraIA64.obj \ $O\CpuArch.obj \ $O\Delta.obj \ + $O\DllSecur.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ $O\Threads.obj \ diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp index 1f3d88d1..301a6c5c 100644 --- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp +++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp @@ -888,6 +888,15 @@ SOURCE=..\..\..\..\C\Delta.h # End Source File # Begin Source File +SOURCE=..\..\..\..\C\DllSecur.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Lzma2Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp index c301ecf8..db7acfef 100644 --- a/CPP/7zip/Bundles/SFXWin/SfxWin.cpp +++ b/CPP/7zip/Bundles/SFXWin/SfxWin.cpp @@ -28,6 +28,8 @@ #include "../../UI/GUI/ExtractGUI.h" #include "../../UI/GUI/ExtractRes.h" +#include "../../../../C/DllSecur.h" + using namespace NWindows; using namespace NFile; using namespace NDir; @@ -220,6 +222,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, try { + #ifdef _WIN32 + LoadSecurityDlls(); + #endif + return WinMain2(); } catch(const CNewException &) diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile index 0ffec922..dc48ae88 100644 --- a/CPP/7zip/Bundles/SFXWin/makefile +++ b/CPP/7zip/Bundles/SFXWin/makefile @@ -131,8 +131,9 @@ C_OBJS = \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ - $O\Delta.obj \ $O\CpuArch.obj \ + $O\Delta.obj \ + $O\DllSecur.obj \ $O\Lzma2Dec.obj \ $O\LzmaDec.obj \ $O\Ppmd7.obj \ diff --git a/CPP/7zip/Compress/DeflateDecoder.cpp b/CPP/7zip/Compress/DeflateDecoder.cpp index 5c097f13..60c9aea6 100644 --- a/CPP/7zip/Compress/DeflateDecoder.cpp +++ b/CPP/7zip/Compress/DeflateDecoder.cpp @@ -8,9 +8,9 @@ namespace NCompress { namespace NDeflate { namespace NDecoder { -CCoder::CCoder(bool deflate64Mode, bool deflateNSIS): +CCoder::CCoder(bool deflate64Mode): _deflate64Mode(deflate64Mode), - _deflateNSIS(deflateNSIS), + _deflateNSIS(false), _keepHistory(false), _needFinishInput(false), _needInitInStream(true), diff --git a/CPP/7zip/Compress/DeflateDecoder.h b/CPP/7zip/Compress/DeflateDecoder.h index 5b2dd32d..09f84eb4 100644 --- a/CPP/7zip/Compress/DeflateDecoder.h +++ b/CPP/7zip/Compress/DeflateDecoder.h @@ -79,9 +79,11 @@ public: bool ZlibMode; Byte ZlibFooter[4]; - CCoder(bool deflate64Mode, bool deflateNSIS = false); + CCoder(bool deflate64Mode); virtual ~CCoder() {}; + void SetNsisMode(bool nsisMode) { _deflateNSIS = nsisMode; } + void Set_KeepHistory(bool keepHistory) { _keepHistory = keepHistory; } void Set_NeedFinishInput(bool needFinishInput) { _needFinishInput = needFinishInput; } @@ -147,7 +149,6 @@ public: }; class CCOMCoder : public CCoder { public: CCOMCoder(): CCoder(false) {} }; -class CNsisCOMCoder : public CCoder { public: CNsisCOMCoder(): CCoder(false, true) {} }; class CCOMCoder64 : public CCoder { public: CCOMCoder64(): CCoder(true) {} }; }}} diff --git a/CPP/7zip/Compress/Rar5Decoder.cpp b/CPP/7zip/Compress/Rar5Decoder.cpp index dc8830f8..fdd65a11 100644 --- a/CPP/7zip/Compress/Rar5Decoder.cpp +++ b/CPP/7zip/Compress/Rar5Decoder.cpp @@ -862,22 +862,26 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream _numCorrectDistSymbols = newSizeLog * 2; } - if (!_window || _winSize != newSize) + // If dictionary was reduced, we use allocated dictionary block + // for compatibility with original unRAR decoder. + + if (_window && newSize < _winSizeAllocated) + _winSize = _winSizeAllocated; + else if (!_window || _winSize != newSize) { - if (!_isSolid && newSize > _winSizeAllocated) + if (!_isSolid) { ::MidFree(_window); _window = NULL; _winSizeAllocated = 0; } - Byte *win = _window; - if (!_window || newSize > _winSizeAllocated) + Byte *win; + { win = (Byte *)::MidAlloc(newSize); if (!win) return E_OUTOFMEMORY; - _winSizeAllocated = newSize; memset(win, 0, newSize); } @@ -892,16 +896,18 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream size_t newMask = newSize - 1; size_t oldMask = _winSize - 1; size_t winPos = _winPos; - for (size_t i = 1; i < oldSize; i++) // i < oldSize) ? + for (size_t i = 1; i <= oldSize; i++) win[(winPos - i) & newMask] = winOld[(winPos - i) & oldMask]; ::MidFree(_window); } _window = win; + _winSizeAllocated = newSize; _winSize = newSize; } _winMask = _winSize - 1; + _winPos &= _winMask; if (!_inputBuf) { diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 61a781af..832ec66d 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -387,7 +387,7 @@ static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs, val.Add_LF(); if (type == NRecursedType::kRecursed) val.AddAscii("-r"); - else if (type == NRecursedType::kRecursed) + else if (type == NRecursedType::kWildcardOnlyRecursed) val.AddAscii("-r0"); throw CArcCmdLineException("Unsupported rename command:", val); } diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index a6de8dc0..3da0aadb 100644 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -359,14 +359,11 @@ HRESULT Extract( op.stream = NULL; op.filePath = arcPath; - HRESULT result = arcLink.Open3(op, openCallback); + HRESULT result = arcLink.Open_Strict(op, openCallback); if (result == E_ABORT) return result; - if (result == S_OK && arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) - result = S_FALSE; - // arcLink.Set_ErrorsText(); RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result)); diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h index 10514ec4..d46d69e8 100644 --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -401,6 +401,14 @@ struct CArchiveLink HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI); + HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI) + { + HRESULT result = Open3(options, callbackUI); + if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + result = S_FALSE; + return result; + } + HRESULT ReOpen(COpenOptions &options); }; diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index 69fdb78e..0db4a87f 100644 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -251,8 +251,6 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize) { - if (newSize < 0) - return E_INVALIDARG; unsigned i = 0; while (i < Streams.Size()) { @@ -1108,14 +1106,11 @@ HRESULT UpdateArchive( RINOK(callback->StartOpenArchive(arcPath)); - HRESULT result = arcLink.Open3(op, openCallback); + HRESULT result = arcLink.Open_Strict(op, openCallback); if (result == E_ABORT) return result; - if (result == S_OK && arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) - result = S_FALSE; - HRESULT res2 = callback->OpenResult(codecs, arcLink, arcPath, result); /* if (result == S_FALSE) diff --git a/CPP/7zip/UI/Console/HashCon.cpp b/CPP/7zip/UI/Console/HashCon.cpp index a71e4b50..6a82daf2 100644 --- a/CPP/7zip/UI/Console/HashCon.cpp +++ b/CPP/7zip/UI/Console/HashCon.cpp @@ -283,7 +283,7 @@ HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBun return CheckBreak2(); } -static const char *k_DigestTitles[] = +static const char * const k_DigestTitles[] = { " : " , " for data: " diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index 362c1ff1..62e813b2 100644 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp @@ -1068,7 +1068,7 @@ HRESULT ListArchives(CCodecs *codecs, g_StdOut << endl << kListing << arcPath << endl << endl; } - HRESULT result = arcLink.Open3(options, &openCallback); + HRESULT result = arcLink.Open_Strict(options, &openCallback); if (result != S_OK) { @@ -1095,9 +1095,6 @@ HRESULT ListArchives(CCodecs *codecs, } { - if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) - numErrors++; - FOR_VECTOR (r, arcLink.Arcs) { const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo; diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 4e4ac221..62ad0aa9 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -489,7 +489,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_fileNames.Size() > 0) { const UString &fileName = _fileNames.Front(); - + #if defined(_WIN32) && !defined(UNDER_CE) if (NName::IsDevicePath(us2fs(fileName))) { @@ -577,7 +577,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (!needExtract) { - FOR_VECTOR (i, _fileNames) + for (unsigned i = 1; i < _fileNames.Size(); i++) { NFind::CFileInfo fi; if (!fi.Find(us2fs(_fileNames[i]))) @@ -594,57 +594,52 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (needExtract) { - // Extract - if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) { - CCommandMapItem commandMapItem; - FillCommand(kExtract, mainString, commandMapItem); + UString baseFolder = fs2us(folderPrefix); if (_dropMode) - commandMapItem.Folder = _dropPath; - else - commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.Folder += GetSubFolderNameForExtract(fs2us(fi0.Name)); - commandMapItem.Folder.Add_PathSepar(); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); - _commandMap.Add(commandMapItem); - } + baseFolder = _dropPath; + + UString specFolder = L'*'; + if (_fileNames.Size() == 1) + specFolder = GetSubFolderNameForExtract(fs2us(fi0.Name)); + specFolder.Add_PathSepar(); - // Extract Here - if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0) - { - CCommandMapItem commandMapItem; - FillCommand(kExtractHere, mainString, commandMapItem); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); - if (_dropMode) - commandMapItem.Folder = _dropPath; - else - commandMapItem.Folder = fs2us(folderPrefix); - _commandMap.Add(commandMapItem); - } + if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) + { + // Extract + CCommandMapItem commandMapItem; + FillCommand(kExtract, mainString, commandMapItem); + commandMapItem.Folder = baseFolder + specFolder; + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); + _commandMap.Add(commandMapItem); + } - // Extract To - if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0) - { - CCommandMapItem commandMapItem; - UString s; - FillCommand(kExtractTo, s, commandMapItem); - UString folder = L'*'; - if (_fileNames.Size() == 1) - folder = GetSubFolderNameForExtract(fs2us(fi0.Name)); - if (_dropMode) - commandMapItem.Folder = _dropPath; - else - commandMapItem.Folder = fs2us(folderPrefix); - commandMapItem.Folder += folder; - folder.Add_PathSepar(); - MyFormatNew_ReducedName(s, folder); - MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); - _commandMap.Add(commandMapItem); + if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0) + { + // Extract Here + CCommandMapItem commandMapItem; + FillCommand(kExtractHere, mainString, commandMapItem); + commandMapItem.Folder = baseFolder; + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); + _commandMap.Add(commandMapItem); + } + + if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0) + { + // Extract To + CCommandMapItem commandMapItem; + UString s; + FillCommand(kExtractTo, s, commandMapItem); + commandMapItem.Folder = baseFolder + specFolder; + MyFormatNew_ReducedName(s, specFolder); + MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); + _commandMap.Add(commandMapItem); + } } - - // Test + if ((contextMenuFlags & NContextMenuFlags::kTest) != 0) { + // Test CCommandMapItem commandMapItem; FillCommand(kTest, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString, bitmap); diff --git a/CPP/7zip/UI/Far/Far.cpp b/CPP/7zip/UI/Far/Far.cpp index 789cc223..7c0876dd 100644 --- a/CPP/7zip/UI/Far/Far.cpp +++ b/CPP/7zip/UI/Far/Far.cpp @@ -396,8 +396,7 @@ static HANDLE MyOpenFilePluginW(const wchar_t *name) agent, (const wchar_t *)archiveType ); - if (!plugin) - return INVALID_HANDLE_VALUE; + plugin->PasswordIsDefined = openArchiveCallbackSpec->PasswordIsDefined; plugin->Password = openArchiveCallbackSpec->Password; diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp index d34d67bb..cba9aa21 100644 --- a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp +++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp @@ -43,7 +43,7 @@ CEnumFormatEtc::CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats) m_Index = 0; m_NumFormats = 0; m_Formats = new FORMATETC[numFormats]; - if (m_Formats) + // if (m_Formats) { m_NumFormats = numFormats; for (ULONG i = 0; i < numFormats; i++) diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp index a80fd049..5e3ec8ef 100644 --- a/CPP/7zip/UI/FileManager/Panel.cpp +++ b/CPP/7zip/UI/FileManager/Panel.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include <Windowsx.h> +// #include <stdio.h> #include "../../../Common/IntToString.h" #include "../../../Common/StringConvert.h" @@ -619,10 +620,47 @@ bool CPanel::OnNotifyReBar(LPNMHDR header, LRESULT & /* result */) return false; } +/* +UInt32 g_OnNotify = 0; +UInt32 g_LVIF_TEXT = 0; +UInt32 g_Time = 0; + +void Print_OnNotify(const char *name) +{ + char s[256]; + DWORD tim = GetTickCount(); + sprintf(s, + "Time = %7u ms, Notify = %9u, TEXT = %9u, %s", + tim - g_Time, + g_OnNotify, + g_LVIF_TEXT, + name); + g_Time = tim; + OutputDebugStringA(s); + g_OnNotify = 0; + g_LVIF_TEXT = 0; +} +*/ + bool CPanel::OnNotify(UINT /* controlID */, LPNMHDR header, LRESULT &result) { + /* + g_OnNotify++; + + if (header->hwndFrom == _listView) + { + if (header->code == LVN_GETDISPINFOW) + { + LV_DISPINFOW *dispInfo = (LV_DISPINFOW *)header; + if ((dispInfo->item.mask & LVIF_TEXT)) + g_LVIF_TEXT++; + } + } + */ + if (!_processNotify) return false; + if (header->hwndFrom == _headerComboBox) return OnNotifyComboBox(header, result); else if (header->hwndFrom == _headerReBar) diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index 261388de..0110ee9d 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -361,6 +361,7 @@ public: // CMyComboBox _headerComboBox; CMyComboBoxEdit _comboBoxEdit; CMyListView _listView; + bool _thereAre_ListView_Items; NWindows::NControl::CStatusBar _statusBar; bool _lastFocusedIsList; // NWindows::NControl::CStatusBar _statusBar2; @@ -380,6 +381,18 @@ public: bool PanelCreated; + void DeleteListItems() + { + if (_thereAre_ListView_Items) + { + bool b = _enableItemChangeNotify; + _enableItemChangeNotify = false; + _listView.DeleteAllItems(); + _thereAre_ListView_Items = false; + _enableItemChangeNotify = b; + } + } + HWND GetParent(); UInt32 GetRealIndex(const LVITEMW &item) const @@ -502,6 +515,7 @@ public: _flatModeForDisk(false), _flatModeForArc(false), PanelCreated(false), + _thereAre_ListView_Items(false), // _showNtfsStrems_Mode(false), // _showNtfsStrems_ModeForDisk(false), diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index befd19f5..ff16f24e 100644 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -404,8 +404,11 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) } else { - if (res != DRAGDROP_S_CANCEL && res != S_OK) + // we ignore E_UNEXPECTED that is returned if we drag file to printer + if (res != DRAGDROP_S_CANCEL && res != S_OK + && res != E_UNEXPECTED) MessageBoxError(res); + res = dropSourceSpec->Result; } diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index aaf3f867..5a59d056 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -30,6 +30,8 @@ using namespace NFind; void CPanel::ReleaseFolder() { + DeleteListItems(); + _folder.Release(); _folderCompare.Release(); @@ -175,15 +177,36 @@ HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bo } else if (fileInfo.IsDir()) { + #ifdef _WIN32 + if (DoesNameContainWildcard(sysPath)) + { + FString dirPrefix, fileName; + NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); + if (DoesNameContainWildcard(dirPrefix)) + return E_INVALIDARG; + sysPath = fs2us(dirPrefix + fileInfo.Name); + } + #endif + NName::NormalizeDirPathPrefix(sysPath); _folder->BindToFolder(sysPath, &newFolder); } else { FString dirPrefix, fileName; + NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName); - HRESULT res; - // = OpenAsArc(fs2us(fileName), arcFormat, encrypted); + + HRESULT res = S_OK; + + #ifdef _WIN32 + if (DoesNameContainWildcard(dirPrefix)) + return E_INVALIDARG; + + if (DoesNameContainWildcard(fileName)) + res = S_FALSE; + else + #endif { CTempFileInfo tfi; tfi.RelPath = fs2us(fileName); @@ -258,9 +281,9 @@ HRESULT CPanel::BindToPathAndRefresh(const UString &path) CDisableTimerProcessing disableTimerProcessing(*this); CDisableNotify disableNotify(*this); bool archiveIsOpened, encrypted; - RINOK(BindToPath(path, UString(), archiveIsOpened, encrypted)); + HRESULT res = BindToPath(path, UString(), archiveIsOpened, encrypted); RefreshListCtrl(UString(), -1, true, UStringVector()); - return S_OK; + return res; } void CPanel::SetBookmark(unsigned index) diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 8f73cffd..55981d6d 100644 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp @@ -92,7 +92,7 @@ HRESULT CPanel::InitColumns() { SaveListViewInfo(); - _listView.DeleteAllItems(); + // DeleteListItems(); _selectedStatusVector.Clear(); { @@ -411,9 +411,21 @@ void CPanel::SetFocusedSelectedItem(int index, bool select) } } +// #define PRINT_STAT + +#ifdef PRINT_STAT + void Print_OnNotify(const char *name); +#else + #define Print_OnNotify(x) +#endif + + HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool selectFocused, const UStringVector &selectedNames) { + if (!_folder) + return S_OK; + _dontShowMode = false; LoadFullPathAndShow(); // OutputDebugStringA("=======\n"); @@ -431,11 +443,11 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool ZeroMemory(&item, sizeof(item)); // DWORD tickCount0 = GetTickCount(); - _enableItemChangeNotify = false; - _listView.DeleteAllItems(); + + // _enableItemChangeNotify = false; + DeleteListItems(); _enableItemChangeNotify = true; - int listViewItemCount = 0; _selectedStatusVector.Clear(); @@ -512,6 +524,12 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool } } + _thereAre_ListView_Items = true; + + // OutputDebugStringA("\n\n"); + + Print_OnNotify("===== Before Load"); + if (showDots) { UString itemName = L".."; @@ -642,7 +660,8 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool // item.pszText = const_cast<wchar_t *>((const wchar_t *)name); item.pszText = LPSTR_TEXTCALLBACKW; /* LPSTR_TEXTCALLBACKW works, but in some cases there are problems, - since we block notify handler. */ + since we block notify handler. + LPSTR_TEXTCALLBACKW can be 2-3 times faster for loading in this loop. */ } UInt32 attrib = 0; @@ -687,14 +706,35 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool listViewItemCount++; } - // OutputDebugStringA("End2\n"); + /* + xp-64: there is different order when Windows calls CPanel::OnNotify for _listView modes: + Details : after whole code + List : 2 times: + 1) - ListView.SotRedraw() + 2) - after whole code + Small Icons : + Large icons : 2 times: + 1) - ListView.Sort() + 2) - after whole code (calls with reverse order of items) + + So we need to allow Notify(), when windows requests names during the following code. + */ + + Print_OnNotify("after Load"); + + disableNotify.SetMemMode_Enable(); + disableNotify.Restore(); if (_listView.GetItemCount() > 0 && cursorIndex >= 0) SetFocusedSelectedItem(cursorIndex, selectFocused); - // DWORD tickCount3 = GetTickCount(); + + Print_OnNotify("after SetFocusedSelectedItem"); + SetSortRawStatus(); _listView.SortItems(CompareItems, (LPARAM)this); - // DWORD tickCount4 = GetTickCount(); + + Print_OnNotify("after Sort"); + if (cursorIndex < 0 && _listView.GetItemCount() > 0) { if (focusedPos >= _listView.GetItemCount()) @@ -702,23 +742,29 @@ HRESULT CPanel::RefreshListCtrl(const UString &focusedName, int focusedPos, bool // we select item only in showDots mode. SetFocusedSelectedItem(focusedPos, showDots); } + // m_RedrawEnabled = true; - // DWORD tickCount5 = GetTickCount(); + + Print_OnNotify("after SetFocusedSelectedItem2"); + _listView.EnsureVisible(_listView.GetFocusedItem(), false); - // DWORD tickCount6 = GetTickCount(); - disableNotify.SetMemMode_Enable(); - disableNotify.Restore(); + // disableNotify.SetMemMode_Enable(); + // disableNotify.Restore(); + + Print_OnNotify("after EnsureVisible"); + _listView.SetRedraw(true); - // DWORD tickCount7 = GetTickCount(); + + Print_OnNotify("after SetRedraw"); + _listView.InvalidateRect(NULL, true); - // DWORD tickCount8 = GetTickCount(); - // OutputDebugStringA("End1\n"); + + Print_OnNotify("after InvalidateRect"); /* _listView.UpdateWindow(); */ Refresh_StatusBar(); - // DWORD tickCount9 = GetTickCount(); /* char s[256]; sprintf(s, diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index 39c29681..cc84f712 100644 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -356,8 +356,8 @@ LRESULT CPanel::SetItemText(LVITEMW &item) i += t; } } - text[dest] = 0; + // OutputDebugStringW(text); return 0; } } diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index bd128695..3331a4cf 100644 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -348,7 +348,7 @@ BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) // We need clear all items to disable GetText before Reload: // number of items can change. - // _listView.DeleteAllItems(); + // DeleteListItems(); // But seems it can still call GetText (maybe for current item) // so we can't delete items. diff --git a/CPP/7zip/UI/FileManager/StringUtils.cpp b/CPP/7zip/UI/FileManager/StringUtils.cpp index 10056549..7c814f7f 100644 --- a/CPP/7zip/UI/FileManager/StringUtils.cpp +++ b/CPP/7zip/UI/FileManager/StringUtils.cpp @@ -9,24 +9,19 @@ void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2) dest1.Empty(); dest2.Empty(); bool quoteMode = false; - unsigned i; - for (i = 0; i < src.Len(); i++) + for (unsigned i = 0; i < src.Len(); i++) { - wchar_t c = src[i]; + const wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { - if (!quoteMode) - { - i++; - break; - } + dest2 = src.Ptr(i + 1); + return; } else dest1 += c; } - dest2 = src.Ptr(i); } void SplitString(const UString &srcString, UStringVector &destStrings) diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index c7d13bc2..4fba3dc3 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -767,7 +767,7 @@ static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) HRESULT Benchmark( DECL_EXTERNAL_CODECS_LOC_VARS - const CObjectVector<CProperty> props, HWND hwndParent) + const CObjectVector<CProperty> &props, HWND hwndParent) { CThreadBenchmark benchmarker; #ifdef EXTERNAL_CODECS diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.h b/CPP/7zip/UI/GUI/BenchmarkDialog.h index a5f0292a..0d88d217 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.h +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.h @@ -175,6 +175,6 @@ public: HRESULT Benchmark( DECL_EXTERNAL_CODECS_LOC_VARS - const CObjectVector<CProperty> props, HWND hwndParent = NULL); + const CObjectVector<CProperty> &props, HWND hwndParent = NULL); #endif diff --git a/CPP/Common/DynLimBuf.h b/CPP/Common/DynLimBuf.h index 962f2e61..93aa144f 100644 --- a/CPP/Common/DynLimBuf.h +++ b/CPP/Common/DynLimBuf.h @@ -27,7 +27,7 @@ public: ~CDynLimBuf() { MyFree(_chars); } size_t Len() const { return _pos; } - void Empty() { _pos = 0; } + void Empty() { _pos = 0; _error = false; } operator const Byte *() const { return _chars; } // const char *Ptr() const { return _chars; } diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp index a83f9f10..5e6ddfc6 100644 --- a/CPP/Common/Wildcard.cpp +++ b/CPP/Common/Wildcard.cpp @@ -484,7 +484,7 @@ unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts) #endif -static unsigned GetNumPrefixParts(const UStringVector pathParts) +static unsigned GetNumPrefixParts(const UStringVector &pathParts) { if (pathParts.IsEmpty()) return 0; diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index 94486977..05196f92 100644 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp @@ -130,7 +130,10 @@ WinXP-64 FindFirstFile(): \\Server\ - ERROR_INVALID_NAME \\Server\Share - ERROR_BAD_NETPATH - \\Server\Share - ERROR_BAD_NET_NAME (Win7) + \\Server\Share - ERROR_BAD_NET_NAME (Win7). + !!! There is problem : Win7 makes some requests for "\\Server\Shar" (look in Procmon), + when we call it for "\\Server\Share" + \\Server\Share\ - ERROR_FILE_NOT_FOUND \\?\UNC\Server\Share - ERROR_INVALID_NAME @@ -508,11 +511,10 @@ bool CFileInfo::Find(CFSTR path) #endif CFindFile finder; - if (finder.FindFirst(path, *this)) - return true; - + #if defined(_WIN32) && !defined(UNDER_CE) { + /* DWORD lastError = GetLastError(); if (lastError == ERROR_FILE_NOT_FOUND || lastError == ERROR_BAD_NETPATH // XP64: "\\Server\Share" @@ -520,36 +522,39 @@ bool CFileInfo::Find(CFSTR path) || lastError == ERROR_INVALID_NAME // XP64: "\\?\UNC\Server\Share" || lastError == ERROR_BAD_PATHNAME // Win7: "\\?\UNC\Server\Share" ) + */ + + unsigned rootSize = 0; + if (IsSuperPath(path)) + rootSize = kSuperPathPrefixSize; + + if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0) { - unsigned rootSize = 0; - if (IsSuperPath(path)) - rootSize = kSuperPathPrefixSize; - if (IS_PATH_SEPAR(path[0]) && path[1] == 0) + DWORD attrib = GetFileAttrib(path); + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) { - DWORD attrib = GetFileAttrib(path); - if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) - { - ClearBase(); - Name.Empty(); - Attrib = attrib; - return true; - } + ClearBase(); + Attrib = attrib; + Name = path + rootSize; + Name.DeleteFrom(2); // we don't need backslash (C:) + return true; } - else if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0) + } + else if (IS_PATH_SEPAR(path[0])) + if (path[1] == 0) { DWORD attrib = GetFileAttrib(path); if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) { ClearBase(); + Name.Empty(); Attrib = attrib; - Name = path + rootSize; - Name.DeleteFrom(2); // we don't need backslash (C:) return true; } } else { - unsigned prefixSize = GetNetworkServerPrefixSize(path); + const unsigned prefixSize = GetNetworkServerPrefixSize(path); if (prefixSize > 0 && path[prefixSize] != 0) { if (NName::FindSepar(path + prefixSize) < 0) @@ -563,7 +568,7 @@ bool CFileInfo::Find(CFSTR path) { if (Name == FTEXT(".")) { - Name = path + prefixSize;; + Name = path + prefixSize; return true; } isOK = true; @@ -583,17 +588,17 @@ bool CFileInfo::Find(CFSTR path) return true; } } - ::SetLastError(lastError); + // ::SetLastError(lastError); } } } - } } #endif - - return false; + + return finder.FindFirst(path, *this); } + bool DoesFileExist(CFSTR name) { CFileInfo fi; @@ -706,7 +711,7 @@ bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings) driveStrings.Add(fas2fs(s)); } } - return prev == newSize;; + return prev == newSize; } else #endif diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp index 382c2e56..908ed53f 100644 --- a/CPP/Windows/FileName.cpp +++ b/CPP/Windows/FileName.cpp @@ -374,54 +374,66 @@ static bool ResolveDotsFolders(UString &s) #ifdef _WIN32 // s.Replace(L'/', WCHAR_PATH_SEPARATOR); #endif + for (unsigned i = 0;;) { - wchar_t c = s[i]; + const wchar_t c = s[i]; if (c == 0) return true; if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1]))) { - wchar_t c1 = s[i + 1]; + const wchar_t c1 = s[i + 1]; if (c1 == '.') { - wchar_t c2 = s[i + 2]; + const wchar_t c2 = s[i + 2]; if (IS_SEPAR(c2) || c2 == 0) { if (i == 0) return false; int k = i - 2; - for (; k >= 0; k--) - if (IS_SEPAR(s[(unsigned)k])) + i += 2; + + for (;; k--) + { + if (k < 0) + return false; + if (!IS_SEPAR(s[(unsigned)k])) break; + } + + do + k--; + while (k >= 0 && !IS_SEPAR(s[(unsigned)k])); + unsigned num; + if (k >= 0) { - num = i + 2 - k; + num = i - k; i = k; } else { - num = (c2 == 0 ? (i + 2) : (i + 3)); + num = (c2 == 0 ? i : (i + 1)); i = 0; } + s.Delete(i, num); continue; } } - else + else if (IS_SEPAR(c1) || c1 == 0) { - if (IS_SEPAR(c1) || c1 == 0) - { - unsigned num = 2; - if (i != 0) - i--; - else if (c1 == 0) - num = 1; - s.Delete(i, num); - continue; - } + unsigned num = 2; + if (i != 0) + i--; + else if (c1 == 0) + num = 1; + s.Delete(i, num); + continue; } } + i++; } } |