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/NsisIn.cpp | |
parent | bd1fa36322ac27f5715433b388742893d6524516 (diff) |
4.58 beta
Diffstat (limited to 'CPP/7zip/Archive/Nsis/NsisIn.cpp')
-rwxr-xr-x | CPP/7zip/Archive/Nsis/NsisIn.cpp | 232 |
1 files changed, 178 insertions, 54 deletions
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; |