You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
6.0 KiB
204 lines
6.0 KiB
/* |
|
* Copyright (C) 2011-2018 Daniel Scharrer |
|
* |
|
* This software is provided 'as-is', without any express or implied |
|
* warranty. In no event will the author(s) be held liable for any damages |
|
* arising from the use of this software. |
|
* |
|
* Permission is granted to anyone to use this software for any purpose, |
|
* including commercial applications, and to alter it and redistribute it |
|
* freely, subject to the following restrictions: |
|
* |
|
* 1. The origin of this software must not be misrepresented; you must not |
|
* claim that you wrote the original software. If you use this software |
|
* in a product, an acknowledgment in the product documentation would be |
|
* appreciated but is not required. |
|
* 2. Altered source versions must be plainly marked as such, and must not be |
|
* misrepresented as being the original software. |
|
* 3. This notice may not be removed or altered from any source distribution. |
|
*/ |
|
|
|
#include "setup/data.hpp" |
|
|
|
#include "setup/version.hpp" |
|
#include "util/load.hpp" |
|
#include "util/log.hpp" |
|
#include "util/output.hpp" |
|
#include "util/storedenum.hpp" |
|
#include "util/time.hpp" |
|
|
|
namespace setup { |
|
|
|
void data_entry::load(std::istream & is, const version & version) { |
|
|
|
chunk.first_slice = util::load<boost::uint32_t>(is, version.bits); |
|
chunk.last_slice = util::load<boost::uint32_t>(is, version.bits); |
|
if(version < INNO_VERSION(4, 0, 0)) { |
|
if(chunk.first_slice < 1 || chunk.last_slice < 1) { |
|
log_warning << "Unexpected slice number: " << chunk.first_slice |
|
<< " to " << chunk.last_slice; |
|
} else { |
|
chunk.first_slice--, chunk.last_slice--; |
|
} |
|
} |
|
|
|
chunk.offset = util::load<boost::uint32_t>(is); |
|
|
|
if(version >= INNO_VERSION(4, 0, 1)) { |
|
file.offset = util::load<boost::uint64_t>(is); |
|
} else { |
|
file.offset = 0; |
|
} |
|
|
|
if(version >= INNO_VERSION(4, 0, 0)) { |
|
file.size = util::load<boost::uint64_t>(is); |
|
chunk.size = util::load<boost::uint64_t>(is); |
|
} else { |
|
file.size = util::load<boost::uint32_t>(is); |
|
chunk.size = util::load<boost::uint32_t>(is); |
|
} |
|
uncompressed_size = file.size; |
|
|
|
if(version >= INNO_VERSION(5, 3, 9)) { |
|
is.read(file.checksum.sha1, std::streamsize(sizeof(file.checksum.sha1))); |
|
file.checksum.type = crypto::SHA1; |
|
} else if(version >= INNO_VERSION(4, 2, 0)) { |
|
is.read(file.checksum.md5, std::streamsize(sizeof(file.checksum.md5))); |
|
file.checksum.type = crypto::MD5; |
|
} else if(version >= INNO_VERSION(4, 0, 1)) { |
|
file.checksum.crc32 = util::load<boost::uint32_t>(is); |
|
file.checksum.type = crypto::CRC32; |
|
} else { |
|
file.checksum.adler32 = util::load<boost::uint32_t>(is); |
|
file.checksum.type = crypto::Adler32; |
|
} |
|
|
|
if(version.bits == 16) { |
|
|
|
// 16-bit installers use the FAT filetime format |
|
|
|
boost::uint16_t time = util::load<boost::uint16_t>(is); |
|
boost::uint16_t date = util::load<boost::uint16_t>(is); |
|
|
|
struct tm t; |
|
t.tm_sec = util::get_bits(time, 0, 4) * 2; // [0, 58] |
|
t.tm_min = util::get_bits(time, 5, 10); // [0, 59] |
|
t.tm_hour = util::get_bits(time, 11, 15); // [0, 23] |
|
t.tm_mday = util::get_bits(date, 0, 4); // [1, 31] |
|
t.tm_mon = util::get_bits(date, 5, 8) - 1; // [0, 11] |
|
t.tm_year = util::get_bits(date, 9, 15) + 1980 - 1900; // [80, 199] |
|
|
|
timestamp = util::parse_time(t); |
|
timestamp_nsec = 0; |
|
|
|
} else { |
|
|
|
// 32-bit installers use the Win32 FILETIME format |
|
|
|
boost::int64_t filetime = util::load<boost::int64_t>(is); |
|
|
|
static const boost::int64_t FiletimeOffset = 0x19DB1DED53E8000ll; |
|
if(filetime < FiletimeOffset) { |
|
log_warning << "Unexpected filetime: " << filetime; |
|
} |
|
filetime -= FiletimeOffset; |
|
|
|
timestamp = filetime / 10000000; |
|
timestamp_nsec = boost::uint32_t(filetime % 10000000) * 100; |
|
|
|
} |
|
|
|
boost::uint32_t file_version_ms = util::load<boost::uint32_t>(is); |
|
boost::uint32_t file_version_ls = util::load<boost::uint32_t>(is); |
|
file_version = (boost::uint64_t(file_version_ms) << 32) |
|
| boost::uint64_t(file_version_ls); |
|
|
|
options = 0; |
|
|
|
stored_flag_reader<flags> flagreader(is, version.bits); |
|
|
|
flagreader.add(VersionInfoValid); |
|
flagreader.add(VersionInfoNotValid); |
|
if(version >= INNO_VERSION(2, 0, 17) && version < INNO_VERSION(4, 0, 1)) { |
|
flagreader.add(BZipped); |
|
} |
|
if(version >= INNO_VERSION(4, 0, 10)) { |
|
flagreader.add(TimeStampInUTC); |
|
} |
|
if(version >= INNO_VERSION(4, 1, 0)) { |
|
flagreader.add(IsUninstallerExe); |
|
} |
|
if(version >= INNO_VERSION(4, 1, 8)) { |
|
flagreader.add(CallInstructionOptimized); |
|
} |
|
if(version >= INNO_VERSION(4, 2, 0)) { |
|
flagreader.add(Touch); |
|
} |
|
if(version >= INNO_VERSION(4, 2, 2)) { |
|
flagreader.add(ChunkEncrypted); |
|
} |
|
if(version >= INNO_VERSION(4, 2, 5)) { |
|
flagreader.add(ChunkCompressed); |
|
} else { |
|
options |= ChunkCompressed; |
|
} |
|
if(version >= INNO_VERSION(5, 1, 13)) { |
|
flagreader.add(SolidBreak); |
|
} |
|
if(version >= INNO_VERSION(5, 5, 7)) { |
|
// Actually added in Inno Setup 5.5.9 but the data version was not bumped |
|
flagreader.add(Sign); |
|
flagreader.add(SignOnce); |
|
} |
|
|
|
options |= flagreader; |
|
|
|
if(options & ChunkCompressed) { |
|
chunk.compression = stream::UnknownCompression; |
|
} else { |
|
chunk.compression = stream::Stored; |
|
} |
|
if(options & BZipped) { |
|
options |= ChunkCompressed; |
|
chunk.compression = stream::BZip2; |
|
} |
|
|
|
if(options & ChunkEncrypted) { |
|
if(version >= INNO_VERSION(5, 3, 9)) { |
|
chunk.encryption = stream::ARC4_SHA1; |
|
} else { |
|
chunk.encryption = stream::ARC4_MD5; |
|
} |
|
} else { |
|
chunk.encryption = stream::Plaintext; |
|
} |
|
|
|
if(options & CallInstructionOptimized) { |
|
if(version < INNO_VERSION(5, 2, 0)) { |
|
file.filter = stream::InstructionFilter4108; |
|
} else if(version < INNO_VERSION(5, 3, 9)) { |
|
file.filter = stream::InstructionFilter5200; |
|
} else { |
|
file.filter = stream::InstructionFilter5309; |
|
} |
|
} else { |
|
file.filter = stream::NoFilter; |
|
} |
|
} |
|
|
|
} // namespace setup |
|
|
|
NAMES(setup::data_entry::flags, "File Location Option", |
|
"version info valid", |
|
"version info not valid", |
|
"timestamp in UTC", |
|
"is uninstaller exe", |
|
"call instruction optimized", |
|
"touch", |
|
"chunk encrypted", |
|
"chunk compressed", |
|
"solid break", |
|
"sign", |
|
"sign once", |
|
"bzipped", |
|
)
|
|
|