diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2008-05-05 04:00:00 +0400 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:55 +0300 |
commit | 3901bf0ab88106a5b031cba7bc18d60cdebf7eef (patch) | |
tree | 808a2489abed822223b118b64e0553db80af6087 /CPP/7zip/Archive/Nsis | |
parent | bd1fa36322ac27f5715433b388742893d6524516 (diff) |
4.58 beta
Diffstat (limited to 'CPP/7zip/Archive/Nsis')
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisDecode.cpp | 4 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisDecode.h | 2 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisHandler.cpp | 32 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisIn.cpp | 232 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisIn.h | 53 |
5 files changed, 236 insertions, 87 deletions
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp index b50ec5e0..7e126bd4 100755 --- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp +++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp @@ -133,9 +133,9 @@ HRESULT CDecoder::Init( return S_OK; } -HRESULT CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +HRESULT CDecoder::Read(void *data, size_t *processedSize) { - return ReadStream(_decoderInStream, data, size, processedSize);; + return ReadStream(_decoderInStream, data, processedSize);; } }} diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h index 1a2fa41f..36aeb2b1 100755 --- a/CPP/7zip/Archive/Nsis/NsisDecode.h +++ b/CPP/7zip/Archive/Nsis/NsisDecode.h @@ -39,7 +39,7 @@ public: HRESULT Init( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter); - HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); + HRESULT Read(void *data, size_t *processedSize); }; }} diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp index 62c7ab38..b24d966d 100755 --- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp @@ -12,6 +12,7 @@ #include "Windows/PropVariant.h" #include "../Common/ItemNameUtils.h" +#include "../../Common/StreamUtils.h" using namespace NWindows; @@ -233,8 +234,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - const UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetReducedName(), CP_ACP)); - prop = (const wchar_t *)s; + UString s; + if (_archive.IsUnicode) + s = item.GetReducedNameU(); + else + s = MultiByteToUnicodeString(item.GetReducedNameA(), CP_ACP); + s = NItemName::WinNameToOSName(s); + if (!s.IsEmpty()) + prop = (const wchar_t *)s; break; } case kpidIsFolder: @@ -348,7 +355,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, continue; RINOK(extractCallback->PrepareOperation(askMode)); if (!testMode) - RINOK(realOutStream->Write((const char *)_archive.Script, (UInt32)_archive.Script.Length(), NULL)); + RINOK(WriteStream(realOutStream, (const char *)_archive.Script, (UInt32)_archive.Script.Length())); } else #endif @@ -379,9 +386,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt64 pos = _archive.GetPosOfSolidItem(index); while(streamPos < pos) { - UInt32 curSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength); - UInt32 processedSize; - HRESULT res = _archive.Decoder.Read(buffer, curSize, &processedSize); + size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength); + HRESULT res = _archive.Decoder.Read(buffer, &processedSize); if (res != S_OK) { if (res != S_FALSE) @@ -398,8 +404,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, } if (streamPos == pos) { - UInt32 processedSize; - RINOK(_archive.Decoder.Read(buffer, 4, &processedSize)); + size_t processedSize = 4; + RINOK(_archive.Decoder.Read(buffer, &processedSize)); if (processedSize != 4) return E_FAIL; streamPos += processedSize; @@ -433,8 +439,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, UInt32 curSize = kBufferLength; if (sizeIsKnown && curSize > fullSize) curSize = fullSize; - UInt32 processedSize; - HRESULT res = _archive.Decoder.Read(buffer, curSize, &processedSize); + size_t processedSize = curSize; + HRESULT res = _archive.Decoder.Read(buffer, &processedSize); if (res != S_OK) { if (res != S_FALSE) @@ -449,7 +455,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, break; } - fullSize -= processedSize; + fullSize -= (UInt32)processedSize; streamPos += processedSize; offset += processedSize; @@ -460,7 +466,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, completed = currentTotalSize + offset; RINOK(extractCallback->SetCompleted(&completed)); if (!testMode) - RINOK(realOutStream->Write(buffer, processedSize, NULL)); + RINOK(WriteStream(realOutStream, buffer, processedSize)); } } else @@ -478,7 +484,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, fullSize -= processedSize; streamPos += processedSize; if (!testMode) - RINOK(realOutStream->Write(buffer, processedSize, 0)); + RINOK(WriteStream(realOutStream, buffer, processedSize)); } } } diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index 83080448..5c5c872f 100755 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +// #include <stdio.h> + #include "NsisIn.h" #include "NsisDecode.h" @@ -9,6 +11,7 @@ #include "../../Common/StreamUtils.h" +#include "Common/StringConvert.h" #include "Common/IntToString.h" namespace NArchive { @@ -27,6 +30,14 @@ public: static const char *kCrLf = "\x0D\x0A"; #endif +#define NS_UN_SKIP_CODE 0xE000 +#define NS_UN_VAR_CODE 0xE001 +#define NS_UN_SHELL_CODE 0xE002 +#define NS_UN_LANG_CODE 0xE003 +#define NS_UN_CODES_START NS_UN_SKIP_CODE +#define NS_UN_CODES_END NS_UN_LANG_CODE + + UInt32 GetUInt32FromMemLE(const Byte *p) { return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); @@ -60,12 +71,20 @@ static int CompareItems(void *const *p1, void *const *p2, void * /* param */) const CItem &i1 = **(CItem **)p1; const CItem &i2 = **(CItem **)p2; RINOZ(MyCompare(i1.Pos, i2.Pos)); - RINOZ(i1.Prefix.Compare(i2.Prefix)); - RINOZ(i1.Name.Compare(i2.Name)); + if (i1.IsUnicode) + { + RINOZ(i1.PrefixU.Compare(i2.PrefixU)); + RINOZ(i1.NameU.Compare(i2.NameU)); + } + else + { + RINOZ(i1.PrefixA.Compare(i2.PrefixA)); + RINOZ(i1.NameA.Compare(i2.NameA)); + } return 0; } -AString CInArchive::ReadString(UInt32 pos) +AString CInArchive::ReadStringA(UInt32 pos) { AString s; UInt32 offset = GetOffset() + _stringsPos + pos; @@ -81,6 +100,24 @@ AString CInArchive::ReadString(UInt32 pos) return s; } +UString CInArchive::ReadStringU(UInt32 pos) +{ + UString s; + UInt32 offset = GetOffset() + _stringsPos + (pos * 2); + for (;;) + { + if (offset >= _size || offset + 1 >= _size) + throw 1; + char c0 = _data[offset++]; + char c1 = _data[offset++]; + wchar_t c = (c0 | ((wchar_t)c1 << 8)); + if (c == 0) + break; + s += c; + } + return s; +} + /* static AString ParsePrefix(const AString &prefix) { @@ -466,13 +503,27 @@ static AString GetVar(UInt32 index) return res; } -// $0..$9, $INSTDIR, etc are encoded as ASCII bytes starting from this value. #define NS_SKIP_CODE 252 #define NS_VAR_CODE 253 #define NS_SHELL_CODE 254 #define NS_LANG_CODE 255 #define NS_CODES_START NS_SKIP_CODE +static AString GetShellString(int index) +{ + AString res = "$"; + if (index < kNumShellStrings) + { + const char *sz = kShellStrings[index]; + if (sz[0] != 0) + return res + sz; + } + res += "SHELL["; + res += UIntToString(index); + res += "]"; + return res; +} + // Based on Dave Laundon's simplified process_string AString GetNsisString(const AString &s) { @@ -487,26 +538,7 @@ AString GetNsisString(const AString &s) nData |= (((int)(c1 & 0x7F)) << 7); if (nVarIdx == NS_SHELL_CODE) - { - UInt32 index = c1; - bool needPrint = true; - res += "$"; - if (index < kNumShellStrings) - { - const char *sz = kShellStrings[index]; - if (sz[0] != 0) - { - res += sz; - needPrint = false; - } - } - if (needPrint) - { - res += "SHELL["; - res += UIntToString(index); - res += "]"; - } - } + res += GetShellString(c1); else if (nVarIdx == NS_VAR_CODE) res += GetVar(nData); else if (nVarIdx == NS_LANG_CODE) @@ -523,9 +555,53 @@ AString GetNsisString(const AString &s) return res; } +UString GetNsisString(const UString &s) +{ + UString res; + for (int i = 0; i < s.Length();) + { + wchar_t nVarIdx = s[i++]; + if (nVarIdx > NS_UN_CODES_START && nVarIdx <= NS_UN_CODES_END) + { + if (i == s.Length()) + break; + int nData = s[i++] & 0x7FFF; + + if (nVarIdx == NS_UN_SHELL_CODE) + res += GetUnicodeString(GetShellString(nData >> 8)); + else if (nVarIdx == NS_UN_VAR_CODE) + res += GetUnicodeString(GetVar(nData)); + else if (nVarIdx == NS_UN_LANG_CODE) + res += L"NS_LANG_CODE"; + } + else if (nVarIdx == NS_UN_SKIP_CODE) + { + if (i == s.Length()) + break; + res += s[i++]; + } + else // Normal char + res += (char)nVarIdx; + } + return res; +} + +AString CInArchive::ReadString2A(UInt32 pos) +{ + return GetNsisString(ReadStringA(pos)); +} + +UString CInArchive::ReadString2U(UInt32 pos) +{ + return GetNsisString(ReadStringU(pos)); +} + AString CInArchive::ReadString2(UInt32 pos) { - return GetNsisString(ReadString(pos)); + if (IsUnicode) + return UnicodeStringToMultiByte(ReadString2U(pos)); + else + return ReadString2A(pos); } #define DEL_DIR 1 @@ -566,7 +642,8 @@ AString CEntry::GetParamsString(int numParams) HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) { _posInData = bh.Offset + GetOffset(); - AString prefix; + AString prefixA; + UString prefixU; for (UInt32 i = 0; i < bh.Num; i++) { CEntry e; @@ -585,11 +662,22 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) { case EW_CREATEDIR: { - prefix.Empty(); - prefix = ReadString2(e.Params[0]); + if (IsUnicode) + { + prefixU.Empty(); + prefixU = ReadString2U(e.Params[0]); + } + else + { + prefixA.Empty(); + prefixA = ReadString2A(e.Params[0]); + } #ifdef NSIS_SCRIPT Script += " "; - Script += prefix; + if (IsUnicode) + Script += UnicodeStringToMultiByte(prefixU); + else + Script += prefixA; #endif break; } @@ -597,9 +685,18 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) case EW_EXTRACTFILE: { CItem item; - item.Prefix = prefix; + item.IsUnicode = IsUnicode; + if (IsUnicode) + { + item.PrefixU = prefixU; + item.NameU = ReadString2U(e.Params[1]); + } + else + { + item.PrefixA = prefixA; + item.NameA = ReadString2A(e.Params[1]); + } /* UInt32 overwriteFlag = e.Params[0]; */ - item.Name = ReadString2(e.Params[1]); item.Pos = e.Params[2]; item.DateTime.dwLowDateTime = e.Params[3]; item.DateTime.dwHighDateTime = e.Params[4]; @@ -614,7 +711,11 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) Items.Add(item); #ifdef NSIS_SCRIPT Script += " "; - Script += item.Name; + + if (IsUnicode) + Script += UnicodeStringToMultiByte(item.NameU); + else + Script += item.NameA; #endif break; } @@ -908,7 +1009,10 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) // if (IsSolid) for (i = 0; i + 1 < Items.Size();) { - if (Items[i].Pos == Items[i + 1].Pos && (IsSolid || Items[i].Name == Items[i + 1].Name)) + bool sameName = IsUnicode ? + (Items[i].NameU == Items[i + 1].NameU) : + (Items[i].NameA == Items[i + 1].NameA); + if (Items[i].Pos == Items[i + 1].Pos && (IsSolid || sameName)) Items.Delete(i + 1); else i++; @@ -927,8 +1031,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL)); const UInt32 kSigSize = 4 + 1 + 5; BYTE sig[kSigSize]; - UInt32 processedSize; - RINOK(ReadStream(_stream, sig, kSigSize, &processedSize)); + size_t processedSize = kSigSize; + RINOK(ReadStream(_stream, sig, &processedSize)); if (processedSize < 4) return S_FALSE; UInt32 size = GetUInt32FromMemLE(sig); @@ -977,7 +1081,37 @@ HRESULT CInArchive::Parse() ReadBlockHeader(bhData); _stringsPos = bhStrings.Offset; + UInt32 pos = GetOffset() + _stringsPos; + int numZeros0 = 0; + int numZeros1 = 0; + int i; + const kBlockSize = 256; + for (i = 0; i < kBlockSize; i++) + { + if (pos >= _size || pos + 1 >= _size) + break; + char c0 = _data[pos++]; + char c1 = _data[pos++]; + wchar_t c = (c0 | ((wchar_t)c1 << 8)); + if (c >= NS_UN_CODES_START && c < NS_UN_CODES_END) + { + if (pos >= _size || pos + 1 >= _size) + break; + pos += 2; + numZeros1++; + } + else + { + if (c0 == 0 && c1 != 0) + numZeros0++; + if (c1 == 0) + numZeros1++; + } + // printf("\nnumZeros0 = %2x %2x", _data[pos + 0], _data[pos + 1]); + } + IsUnicode = (numZeros1 > numZeros0 * 3 + kBlockSize / 16); + // printf("\nnumZeros0 = %3d numZeros1 = %3d", numZeros0, numZeros1); return ReadEntries(bhEntries); } @@ -1010,10 +1144,7 @@ HRESULT CInArchive::Open2( const UInt32 kSigSize = 4 + 1 + 5 + 1; // size, flag, lzma props, lzma first byte BYTE sig[kSigSize]; - UInt32 processedSize; - RINOK(ReadStream(_stream, sig, kSigSize, &processedSize)); - if (processedSize != kSigSize) - return S_FALSE; + RINOK(ReadStream_FALSE(_stream, sig, kSigSize)); UInt64 position; RINOK(_stream->Seek(StreamOffset, STREAM_SEEK_SET, &position)); @@ -1065,11 +1196,11 @@ HRESULT CInArchive::Open2( RINOK(Decoder.Init( EXTERNAL_CODECS_LOC_VARS _stream, Method, FilterFlag, UseFilter)); - UInt32 processedSize; - RINOK(Decoder.Read(_data, unpackSize, &processedSize)); + size_t processedSize = unpackSize; + RINOK(Decoder.Read(_data, &processedSize)); if (processedSize != unpackSize) return S_FALSE; - _size = (size_t)processedSize; + _size = processedSize; if (IsSolid) { UInt32 size2 = ReadUInt32(); @@ -1081,9 +1212,7 @@ HRESULT CInArchive::Open2( { _data.SetCapacity(unpackSize); _size = (size_t)unpackSize; - RINOK(ReadStream(_stream, (Byte *)_data, unpackSize, &processedSize)); - if (processedSize != unpackSize) - return S_FALSE; + RINOK(ReadStream_FALSE(_stream, (Byte *)_data, unpackSize)); } return Parse(); } @@ -1138,22 +1267,17 @@ HRESULT CInArchive::Open( UInt64 headerPosition = 0; while (position <= maxSize) { - UInt32 processedSize; - RINOK(ReadStream(inStream, buffer, kStartHeaderSize, &processedSize)); - if (processedSize != kStartHeaderSize) - return S_FALSE; + RINOK(ReadStream_FALSE(inStream, buffer, kStartHeaderSize)); headerPosition = position; - position += processedSize; + position += kStartHeaderSize; if(memcmp(buffer + 4, kSignature, kSignatureSize) == 0) { found = true; break; } const UInt32 kRem = kStep - kStartHeaderSize; - RINOK(ReadStream(inStream, buffer + kStartHeaderSize, kRem, &processedSize)); - if (processedSize != kRem) - return S_FALSE; - position += processedSize; + RINOK(ReadStream_FALSE(inStream, buffer + kStartHeaderSize, kRem)); + position += kRem; } if (!found) return S_FALSE; diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 22c050f1..e7908862 100755 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -56,41 +56,56 @@ struct CBlockHeader struct CItem { - AString Prefix; - AString Name; - UInt32 Pos; + AString PrefixA; + UString PrefixU; + AString NameA; + UString NameU; + FILETIME DateTime; + bool IsUnicode; + bool UseFilter; + bool IsCompressed; bool SizeIsDefined; bool CompressedSizeIsDefined; bool EstimatedSizeIsDefined; + UInt32 Pos; UInt32 Size; UInt32 CompressedSize; UInt32 EstimatedSize; - FILETIME DateTime; UInt32 DictionarySize; - bool IsCompressed; - bool UseFilter; - CItem(): UseFilter(false), SizeIsDefined(false), EstimatedSizeIsDefined(false), - IsCompressed(true), CompressedSizeIsDefined(false), Size(0) {} + + CItem(): IsUnicode(false), UseFilter(false), IsCompressed(true), SizeIsDefined(false), + CompressedSizeIsDefined(false), EstimatedSizeIsDefined(false), Size(0) {} bool IsINSTDIR() const { - if (Prefix.Length() < 3) - return false; - return true; + return (PrefixA.Length() >= 3 || PrefixU.Length() >= 3); } - AString GetReducedName() const + AString GetReducedNameA() const { - AString prefix = Prefix; + AString prefix = PrefixA; if (prefix.Length() > 0) if (prefix[prefix.Length() - 1] != '\\') prefix += '\\'; - AString s2 = prefix + Name; + AString s2 = prefix + NameA; const int len = 9; if (s2.Left(len).CompareNoCase("$INSTDIR\\") == 0) s2 = s2.Mid(len); return s2; } + + UString GetReducedNameU() const + { + UString prefix = PrefixU; + if (prefix.Length() > 0) + if (prefix[prefix.Length() - 1] != L'\\') + prefix += L'\\'; + UString s2 = prefix + NameU; + const int len = 9; + if (s2.Left(len).CompareNoCase(L"$INSTDIR\\") == 0) + s2 = s2.Mid(len); + return s2; + } }; @@ -105,7 +120,10 @@ class CInArchive DECL_EXTERNAL_CODECS_LOC_VARS2 ); void ReadBlockHeader(CBlockHeader &bh); - AString ReadString(UInt32 pos); + AString ReadStringA(UInt32 pos); + UString ReadStringU(UInt32 pos); + AString ReadString2A(UInt32 pos); + UString ReadString2U(UInt32 pos); AString ReadString2(UInt32 pos); HRESULT ReadEntries(const CBlockHeader &bh); HRESULT Parse(); @@ -129,12 +147,13 @@ public: UInt64 StreamOffset; CDecoder Decoder; CObjectVector<CItem> Items; - bool IsSolid; CFirstHeader FirstHeader; NMethodType::EEnum Method; - bool UseFilter; UInt32 DictionarySize; + bool IsSolid; + bool UseFilter; bool FilterFlag; + bool IsUnicode; #ifdef NSIS_SCRIPT AString Script; |