From 8af85f702f82596dbe7bf128f3edc6254a215dfd Mon Sep 17 00:00:00 2001 From: Daniel Scharrer Date: Mon, 19 Aug 2019 00:25:51 +0200 Subject: [PATCH] setup: Don't hardcode codepage for non-Unicode installers --- CHANGELOG | 1 + src/cli/extract.cpp | 6 +-- src/cli/gog.cpp | 2 +- src/setup/component.cpp | 36 ++++++------- src/setup/component.hpp | 4 +- src/setup/data.cpp | 47 ++++++++--------- src/setup/data.hpp | 4 +- src/setup/delete.cpp | 11 ++-- src/setup/delete.hpp | 4 +- src/setup/directory.cpp | 23 +++++---- src/setup/directory.hpp | 4 +- src/setup/file.cpp | 74 ++++++++++++++------------- src/setup/file.hpp | 4 +- src/setup/header.cpp | 98 +++++++++++++++++++++++------------ src/setup/header.hpp | 3 ++ src/setup/icon.cpp | 45 ++++++++-------- src/setup/icon.hpp | 4 +- src/setup/info.cpp | 107 ++++++++++++++++++++------------------- src/setup/info.hpp | 13 ++++- src/setup/ini.cpp | 19 +++---- src/setup/ini.hpp | 4 +- src/setup/item.cpp | 25 ++++----- src/setup/item.hpp | 3 +- src/setup/language.cpp | 41 +++++++++------ src/setup/language.hpp | 8 ++- src/setup/message.cpp | 12 ++--- src/setup/message.hpp | 7 +-- src/setup/permission.cpp | 5 +- src/setup/permission.hpp | 4 +- src/setup/registry.cpp | 41 +++++++-------- src/setup/registry.hpp | 4 +- src/setup/run.cpp | 47 ++++++++--------- src/setup/run.hpp | 4 +- src/setup/task.cpp | 31 ++++++------ src/setup/task.hpp | 4 +- src/setup/type.cpp | 21 ++++---- src/setup/type.hpp | 4 +- src/setup/version.hpp | 3 -- 38 files changed, 427 insertions(+), 350 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8ef2e2e..871837d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,6 +9,7 @@ innoextract 1.8 (WIP) - Added support for installers using an alternative setup loader magic - Added support for using boost_{zlib,bzip2} when statically linking Boost - Added support for automatically reading external setup.0 files + - Encoding for non-Unicode installers is now determined from the languages supported by the installer - Implemented parsing of GOG Galaxy architecture constraints - The architecture-specific suffixes @32bit and @64bit are now used to disambiguate colliding files - Fixed extracting files from slices larger than 2 GiB with 32-bit builds diff --git a/src/cli/extract.cpp b/src/cli/extract.cpp index 089a98f..ef22398 100644 --- a/src/cli/extract.cpp +++ b/src/cli/extract.cpp @@ -660,10 +660,10 @@ bool print_file_info(const extract_options & o, const setup::info & info) { std::cout << '\n'; } if(o.silent) { - std::cout << util::encoding_name(info.version.codepage()) << '\n'; + std::cout << util::encoding_name(info.codepage) << '\n'; } else { std::cout << "Password encoding: " << color::yellow - << util::encoding_name(info.version.codepage()) << color::reset << '\n'; + << util::encoding_name(info.codepage) << color::reset << '\n'; } } else if(!o.quiet) { std::cout << "Setup is not passworded!\n"; @@ -945,7 +945,7 @@ void process_file(const fs::path & file, const extract_options & o) { log_warning << "Setup contains encrypted files, use the --password option to extract them"; } } else { - util::from_utf8(o.password, password, info.version.codepage()); + util::from_utf8(o.password, password, info.codepage); if(info.header.options & setup::header::Password) { crypto::hasher checksum(info.header.password.type); checksum.update(info.header.password_salt.c_str(), info.header.password_salt.length()); diff --git a/src/cli/gog.cpp b/src/cli/gog.cpp index 0779fb2..05d00fe 100644 --- a/src/cli/gog.cpp +++ b/src/cli/gog.cpp @@ -75,7 +75,7 @@ std::string get_game_id(const setup::info & info) { if(boost::iequals(entry.name, "gameID")) { id = entry.value; - util::to_utf8(id, info.version.codepage()); + util::to_utf8(id, info.codepage); break; } diff --git a/src/setup/component.cpp b/src/setup/component.cpp index e576083..19f7138 100644 --- a/src/setup/component.cpp +++ b/src/setup/component.cpp @@ -20,6 +20,7 @@ #include "setup/component.hpp" +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -53,51 +54,52 @@ STORED_FLAGS_MAP(stored_component_flags_2, } // anonymous namespace -void component_entry::load(std::istream & is, const version & version) { +void component_entry::load(std::istream & is, const info & i) { - is >> util::encoded_string(name, version.codepage()); - is >> util::encoded_string(description, version.codepage()); - is >> util::encoded_string(types, version.codepage()); - if(version >= INNO_VERSION(4, 0, 1)) { - is >> util::encoded_string(languages, version.codepage()); + is >> util::encoded_string(name, i.codepage); + is >> util::encoded_string(description, i.codepage); + is >> util::encoded_string(types, i.codepage); + if(i.version >= INNO_VERSION(4, 0, 1)) { + is >> util::encoded_string(languages, i.codepage); } else { languages.clear(); } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { - is >> util::encoded_string(check, version.codepage()); + if(i.version >= INNO_VERSION(4, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(1, 3, 24))) { + is >> util::encoded_string(check, i.codepage); } else { check.clear(); } - if(version >= INNO_VERSION(4, 0, 0)) { + if(i.version >= INNO_VERSION(4, 0, 0)) { extra_disk_pace_required = util::load(is); } else { extra_disk_pace_required = util::load(is); } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 3))) { + if(i.version >= INNO_VERSION(4, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(3, 0, 3))) { level = util::load(is); } else { level = 0; } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 4))) { + if(i.version >= INNO_VERSION(4, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(3, 0, 4))) { used = util::load_bool(is); } else { used = true; } - winver.load(is, version); + winver.load(is, i.version); - if(version >= INNO_VERSION(4, 2, 3)) { + if(i.version >= INNO_VERSION(4, 2, 3)) { options = stored_flags(is).get(); - } else if(version >= INNO_VERSION(3, 0, 8) || - (version.is_isx() && version >= INNO_VERSION_EXT(3, 0, 6, 1))) { + } else if(i.version >= INNO_VERSION(3, 0, 8) || + (i.version.is_isx() && i.version >= INNO_VERSION_EXT(3, 0, 6, 1))) { options = stored_flags(is).get(); } else { options = stored_flags(is).get(); } - if(version >= INNO_VERSION(4, 0, 0)) { + if(i.version >= INNO_VERSION(4, 0, 0)) { size = util::load(is); - } else if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { + } else if(i.version >= INNO_VERSION(2, 0, 0) || + (i.version.is_isx() && i.version >= INNO_VERSION(1, 3, 24))) { size = util::load(is); } } diff --git a/src/setup/component.hpp b/src/setup/component.hpp index d713504..531cddd 100644 --- a/src/setup/component.hpp +++ b/src/setup/component.hpp @@ -37,7 +37,7 @@ namespace setup { -struct version; +struct info; struct component_entry { @@ -68,7 +68,7 @@ struct component_entry { boost::uint64_t size; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/data.cpp b/src/setup/data.cpp index 212e94a..66bba5b 100644 --- a/src/setup/data.cpp +++ b/src/setup/data.cpp @@ -22,6 +22,7 @@ #include +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/log.hpp" @@ -31,11 +32,11 @@ namespace setup { -void data_entry::load(std::istream & is, const version & version) { +void data_entry::load(std::istream & is, const info & i) { - chunk.first_slice = util::load(is, version.bits()); - chunk.last_slice = util::load(is, version.bits()); - if(version < INNO_VERSION(4, 0, 0)) { + chunk.first_slice = util::load(is, i.version.bits()); + chunk.last_slice = util::load(is, i.version.bits()); + if(i.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; @@ -46,13 +47,13 @@ void data_entry::load(std::istream & is, const version & version) { chunk.offset = util::load(is); - if(version >= INNO_VERSION(4, 0, 1)) { + if(i.version >= INNO_VERSION(4, 0, 1)) { file.offset = util::load(is); } else { file.offset = 0; } - if(version >= INNO_VERSION(4, 0, 0)) { + if(i.version >= INNO_VERSION(4, 0, 0)) { file.size = util::load(is); chunk.size = util::load(is); } else { @@ -61,13 +62,13 @@ void data_entry::load(std::istream & is, const version & version) { } uncompressed_size = file.size; - if(version >= INNO_VERSION(5, 3, 9)) { + if(i.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)) { + } else if(i.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)) { + } else if(i.version >= INNO_VERSION(4, 0, 1)) { file.checksum.crc32 = util::load(is); file.checksum.type = crypto::CRC32; } else { @@ -75,7 +76,7 @@ void data_entry::load(std::istream & is, const version & version) { file.checksum.type = crypto::Adler32; } - if(version.bits() == 16) { + if(i.version.bits() == 16) { // 16-bit installers use the FAT filetime format @@ -118,37 +119,37 @@ void data_entry::load(std::istream & is, const version & version) { options = 0; - stored_flag_reader flagreader(is, version.bits()); + stored_flag_reader flagreader(is, i.version.bits()); flagreader.add(VersionInfoValid); flagreader.add(VersionInfoNotValid); - if(version >= INNO_VERSION(2, 0, 17) && version < INNO_VERSION(4, 0, 1)) { + if(i.version >= INNO_VERSION(2, 0, 17) && i.version < INNO_VERSION(4, 0, 1)) { flagreader.add(BZipped); } - if(version >= INNO_VERSION(4, 0, 10)) { + if(i.version >= INNO_VERSION(4, 0, 10)) { flagreader.add(TimeStampInUTC); } - if(version >= INNO_VERSION(4, 1, 0)) { + if(i.version >= INNO_VERSION(4, 1, 0)) { flagreader.add(IsUninstallerExe); } - if(version >= INNO_VERSION(4, 1, 8)) { + if(i.version >= INNO_VERSION(4, 1, 8)) { flagreader.add(CallInstructionOptimized); } - if(version >= INNO_VERSION(4, 2, 0)) { + if(i.version >= INNO_VERSION(4, 2, 0)) { flagreader.add(Touch); } - if(version >= INNO_VERSION(4, 2, 2)) { + if(i.version >= INNO_VERSION(4, 2, 2)) { flagreader.add(ChunkEncrypted); } - if(version >= INNO_VERSION(4, 2, 5)) { + if(i.version >= INNO_VERSION(4, 2, 5)) { flagreader.add(ChunkCompressed); } else { options |= ChunkCompressed; } - if(version >= INNO_VERSION(5, 1, 13)) { + if(i.version >= INNO_VERSION(5, 1, 13)) { flagreader.add(SolidBreak); } - if(version >= INNO_VERSION(5, 5, 7)) { + if(i.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); @@ -167,7 +168,7 @@ void data_entry::load(std::istream & is, const version & version) { } if(options & ChunkEncrypted) { - if(version >= INNO_VERSION(5, 3, 9)) { + if(i.version >= INNO_VERSION(5, 3, 9)) { chunk.encryption = stream::ARC4_SHA1; } else { chunk.encryption = stream::ARC4_MD5; @@ -177,9 +178,9 @@ void data_entry::load(std::istream & is, const version & version) { } if(options & CallInstructionOptimized) { - if(version < INNO_VERSION(5, 2, 0)) { + if(i.version < INNO_VERSION(5, 2, 0)) { file.filter = stream::InstructionFilter4108; - } else if(version < INNO_VERSION(5, 3, 9)) { + } else if(i.version < INNO_VERSION(5, 3, 9)) { file.filter = stream::InstructionFilter5200; } else { file.filter = stream::InstructionFilter5309; diff --git a/src/setup/data.hpp b/src/setup/data.hpp index 91aa4d0..eecd724 100644 --- a/src/setup/data.hpp +++ b/src/setup/data.hpp @@ -39,7 +39,7 @@ namespace setup { -struct version; +struct info; struct data_entry { @@ -79,7 +79,7 @@ struct data_entry { * * \note This function may not be thread-safe on all operating systems. */ - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/delete.cpp b/src/setup/delete.cpp index 8898c76..70ec571 100644 --- a/src/setup/delete.cpp +++ b/src/setup/delete.cpp @@ -20,6 +20,7 @@ #include "setup/delete.hpp" +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -36,17 +37,17 @@ STORED_ENUM_MAP(delete_target_type_map, delete_entry::Files, } // anonymous namespace -void delete_entry::load(std::istream & is, const version & version) { +void delete_entry::load(std::istream & is, const info & i) { - if(version < INNO_VERSION(1, 3, 0)) { + if(i.version < INNO_VERSION(1, 3, 0)) { (void)util::load(is); // uncompressed size of the entry } - is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(name, i.codepage); - load_condition_data(is, version); + load_condition_data(is, i); - load_version_data(is, version); + load_version_data(is, i.version); type = stored_enum(is).get(); } diff --git a/src/setup/delete.hpp b/src/setup/delete.hpp index 1002f5e..6c82eea 100644 --- a/src/setup/delete.hpp +++ b/src/setup/delete.hpp @@ -34,7 +34,7 @@ namespace setup { -struct version; +struct info; struct delete_entry : public item { @@ -48,7 +48,7 @@ struct delete_entry : public item { target_type type; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/directory.cpp b/src/setup/directory.cpp index 10f86ce..b67775a 100644 --- a/src/setup/directory.cpp +++ b/src/setup/directory.cpp @@ -20,6 +20,7 @@ #include "setup/directory.hpp" +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -45,39 +46,39 @@ STORED_FLAGS_MAP(stored_inno_directory_options_1, } // anonymous namespace -void directory_entry::load(std::istream & is, const version & version) { +void directory_entry::load(std::istream & is, const info & i) { - if(version < INNO_VERSION(1, 3, 0)) { + if(i.version < INNO_VERSION(1, 3, 0)) { (void)util::load(is); // uncompressed size of the entry } - is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(name, i.codepage); - load_condition_data(is, version); + load_condition_data(is, i); - if(version >= INNO_VERSION(4, 0, 11) && version < INNO_VERSION(4, 1, 0)) { - is >> util::encoded_string(permissions, version.codepage()); + if(i.version >= INNO_VERSION(4, 0, 11) && i.version < INNO_VERSION(4, 1, 0)) { + is >> util::binary_string(permissions); } else { permissions.clear(); } - if(version >= INNO_VERSION(2, 0, 11)) { + if(i.version >= INNO_VERSION(2, 0, 11)) { attributes = util::load(is); } else { attributes = 0; } - load_version_data(is, version); + load_version_data(is, i.version); - if(version >= INNO_VERSION(4, 1, 0)) { + if(i.version >= INNO_VERSION(4, 1, 0)) { permission = util::load(is); } else { permission = boost::int16_t(-1); } - if(version >= INNO_VERSION(5, 2, 0)) { + if(i.version >= INNO_VERSION(5, 2, 0)) { options = stored_flags(is).get(); - } else if(version.bits() != 16) { + } else if(i.version.bits() != 16) { options = stored_flags(is).get(); } else { options = stored_flags(is).get(); diff --git a/src/setup/directory.hpp b/src/setup/directory.hpp index a541e03..0106ae8 100644 --- a/src/setup/directory.hpp +++ b/src/setup/directory.hpp @@ -37,7 +37,7 @@ namespace setup { -struct version; +struct info; struct directory_entry : public item { @@ -58,7 +58,7 @@ struct directory_entry : public item { flags options; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/file.cpp b/src/setup/file.cpp index fb78ba1..8a93a6e 100644 --- a/src/setup/file.cpp +++ b/src/setup/file.cpp @@ -20,6 +20,7 @@ #include "setup/file.hpp" +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/log.hpp" @@ -70,35 +71,35 @@ NAMES(setup::file_copy_mode, "File Copy Mode", namespace setup { -void file_entry::load(std::istream & is, const version & version) { +void file_entry::load(std::istream & is, const info & i) { USE_ENUM_NAMES(file_copy_mode) options = 0; - if(version < INNO_VERSION(1, 3, 0)) { + if(i.version < INNO_VERSION(1, 3, 0)) { (void)util::load(is); // uncompressed size of the entry } - is >> util::encoded_string(source, version.codepage()); - is >> util::encoded_string(destination, version.codepage()); - is >> util::encoded_string(install_font_name, version.codepage()); - if(version >= INNO_VERSION(5, 2, 5)) { - is >> util::encoded_string(strong_assembly_name, version.codepage()); + is >> util::encoded_string(source, i.codepage); + is >> util::encoded_string(destination, i.codepage); + is >> util::encoded_string(install_font_name, i.codepage); + if(i.version >= INNO_VERSION(5, 2, 5)) { + is >> util::encoded_string(strong_assembly_name, i.codepage); } else { strong_assembly_name.clear(); } - load_condition_data(is, version); + load_condition_data(is, i); - load_version_data(is, version); + load_version_data(is, i.version); - location = util::load(is, version.bits()); - attributes = util::load(is, version.bits()); - external_size = (version >= INNO_VERSION(4, 0, 0)) ? util::load(is) - : util::load(is); + location = util::load(is, i.version.bits()); + attributes = util::load(is, i.version.bits()); + external_size = (i.version >= INNO_VERSION(4, 0, 0)) ? util::load(is) + : util::load(is); - if(version < INNO_VERSION(3, 0, 5)) { + if(i.version < INNO_VERSION(3, 0, 5)) { file_copy_mode copyMode = stored_enum(is).get(); switch(copyMode) { case cmNormal: options |= PromptIfOlder; break; @@ -108,89 +109,90 @@ void file_entry::load(std::istream & is, const version & version) { } } - if(version >= INNO_VERSION(4, 1, 0)) { + if(i.version >= INNO_VERSION(4, 1, 0)) { permission = util::load(is); } else { permission = boost::int16_t(-1); } - stored_flag_reader flagreader(is, version.bits()); + stored_flag_reader flagreader(is, i.version.bits()); flagreader.add(ConfirmOverwrite); flagreader.add(NeverUninstall); flagreader.add(RestartReplace); flagreader.add(DeleteAfterInstall); - if(version.bits() != 16) { + if(i.version.bits() != 16) { flagreader.add(RegisterServer); flagreader.add(RegisterTypeLib); flagreader.add(SharedFile); } - if(version < INNO_VERSION(2, 0, 0) && !version.is_isx()) { + if(i.version < INNO_VERSION(2, 0, 0) && !i.version.is_isx()) { flagreader.add(IsReadmeFile); } flagreader.add(CompareTimeStamp); flagreader.add(FontIsNotTrueType); - if(version >= INNO_VERSION(1, 2, 5)) { + if(i.version >= INNO_VERSION(1, 2, 5)) { flagreader.add(SkipIfSourceDoesntExist); } - if(version >= INNO_VERSION(1, 2, 6)) { + if(i.version >= INNO_VERSION(1, 2, 6)) { flagreader.add(OverwriteReadOnly); } - if(version >= INNO_VERSION(1, 3, 21)) { + if(i.version >= INNO_VERSION(1, 3, 21)) { flagreader.add(OverwriteSameVersion); flagreader.add(CustomDestName); } - if(version >= INNO_VERSION(1, 3, 25)) { + if(i.version >= INNO_VERSION(1, 3, 25)) { flagreader.add(OnlyIfDestFileExists); } - if(version >= INNO_VERSION(2, 0, 5)) { + if(i.version >= INNO_VERSION(2, 0, 5)) { flagreader.add(NoRegError); } - if(version >= INNO_VERSION(3, 0, 1)) { + if(i.version >= INNO_VERSION(3, 0, 1)) { flagreader.add(UninsRestartDelete); } - if(version >= INNO_VERSION(3, 0, 5)) { + if(i.version >= INNO_VERSION(3, 0, 5)) { flagreader.add(OnlyIfDoesntExist); flagreader.add(IgnoreVersion); flagreader.add(PromptIfOlder); } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION_EXT(3, 0, 6, 1))) { + if(i.version >= INNO_VERSION(4, 0, 0) || + (i.version.is_isx() && i.version >= INNO_VERSION_EXT(3, 0, 6, 1))) { flagreader.add(DontCopy); } - if(version >= INNO_VERSION(4, 0, 5)) { + if(i.version >= INNO_VERSION(4, 0, 5)) { flagreader.add(UninsRemoveReadOnly); } - if(version >= INNO_VERSION(4, 1, 8)) { + if(i.version >= INNO_VERSION(4, 1, 8)) { flagreader.add(RecurseSubDirsExternal); } - if(version >= INNO_VERSION(4, 2, 1)) { + if(i.version >= INNO_VERSION(4, 2, 1)) { flagreader.add(ReplaceSameVersionIfContentsDiffer); } - if(version >= INNO_VERSION(4, 2, 5)) { + if(i.version >= INNO_VERSION(4, 2, 5)) { flagreader.add(DontVerifyChecksum); } - if(version >= INNO_VERSION(5, 0, 3)) { + if(i.version >= INNO_VERSION(5, 0, 3)) { flagreader.add(UninsNoSharedFilePrompt); } - if(version >= INNO_VERSION(5, 1, 0)) { + if(i.version >= INNO_VERSION(5, 1, 0)) { flagreader.add(CreateAllSubDirs); } - if(version >= INNO_VERSION(5, 1, 2)) { + if(i.version >= INNO_VERSION(5, 1, 2)) { flagreader.add(Bits32); flagreader.add(Bits64); } - if(version >= INNO_VERSION(5, 2, 0)) { + if(i.version >= INNO_VERSION(5, 2, 0)) { flagreader.add(ExternalSizePreset); flagreader.add(SetNtfsCompression); flagreader.add(UnsetNtfsCompression); } - if(version >= INNO_VERSION(5, 2, 5)) { + if(i.version >= INNO_VERSION(5, 2, 5)) { flagreader.add(GacInstall); } options |= flagreader; - if(version.bits() == 16 || version >= INNO_VERSION(5, 0, 0)) { + if(i.version.bits() == 16 || i.version >= INNO_VERSION(5, 0, 0)) { type = stored_enum(is).get(); } else { type = stored_enum(is).get(); diff --git a/src/setup/file.hpp b/src/setup/file.hpp index b7857e8..303a5b8 100644 --- a/src/setup/file.hpp +++ b/src/setup/file.hpp @@ -39,7 +39,7 @@ namespace setup { -struct version; +struct info; struct file_entry : public item { @@ -113,7 +113,7 @@ struct file_entry : public item { crypto::checksum checksum; boost::uint64_t size; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/header.cpp b/src/setup/header.cpp index 00edacf..74b14a7 100644 --- a/src/setup/header.cpp +++ b/src/setup/header.cpp @@ -26,7 +26,6 @@ #include #include "setup/version.hpp" -#include "util/encoding.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -152,38 +151,40 @@ void header::load(std::istream & is, const version & version) { (void)util::load(is); // uncompressed size of the setup header } - is >> util::encoded_string(app_name, version.codepage()); - is >> util::encoded_string(app_versioned_name, version.codepage()); + is >> util::binary_string(app_name); + is >> util::binary_string(app_versioned_name); if(version >= INNO_VERSION(1, 3, 0)) { - is >> util::encoded_string(app_id, version.codepage()); + is >> util::binary_string(app_id); + } else { + app_id.clear(); } - is >> util::encoded_string(app_copyright, version.codepage()); + is >> util::binary_string(app_copyright); if(version >= INNO_VERSION(1, 3, 0)) { - is >> util::encoded_string(app_publisher, version.codepage()); - is >> util::encoded_string(app_publisher_url, version.codepage()); + is >> util::binary_string(app_publisher); + is >> util::binary_string(app_publisher_url); } else { app_publisher.clear(), app_publisher_url.clear(); } if(version >= INNO_VERSION(5, 1, 13)) { - is >> util::encoded_string(app_support_phone, version.codepage()); + is >> util::binary_string(app_support_phone); } else { app_support_phone.clear(); } if(version >= INNO_VERSION(1, 3, 0)) { - is >> util::encoded_string(app_support_url, version.codepage()); - is >> util::encoded_string(app_updates_url, version.codepage()); - is >> util::encoded_string(app_version, version.codepage()); + is >> util::binary_string(app_support_url); + is >> util::binary_string(app_updates_url); + is >> util::binary_string(app_version); } else { app_support_url.clear(), app_updates_url.clear(), app_version.clear(); } - is >> util::encoded_string(default_dir_name, version.codepage()); - is >> util::encoded_string(default_group_name, version.codepage()); + is >> util::binary_string(default_dir_name); + is >> util::binary_string(default_group_name); if(version < INNO_VERSION(3, 0, 0)) { is >> util::ansi_string(uninstall_icon_name); } else { uninstall_icon_name.clear(); } - is >> util::encoded_string(base_filename, version.codepage()); + is >> util::binary_string(base_filename); if(version >= INNO_VERSION(1, 3, 0) && version < INNO_VERSION(5, 2, 5)) { is >> util::ansi_string(license_text); is >> util::ansi_string(info_before); @@ -192,29 +193,29 @@ void header::load(std::istream & is, const version & version) { license_text.clear(), info_before.clear(), info_after.clear(); } if(version >= INNO_VERSION(1, 3, 3)) { - is >> util::encoded_string(uninstall_files_dir, version.codepage()); + is >> util::binary_string(uninstall_files_dir); } else { uninstall_files_dir.clear(); } if(version >= INNO_VERSION(1, 3, 6)) { - is >> util::encoded_string(uninstall_name, version.codepage()); - is >> util::encoded_string(uninstall_icon, version.codepage()); + is >> util::binary_string(uninstall_name); + is >> util::binary_string(uninstall_icon); } else { uninstall_name.clear(), uninstall_icon.clear(); } if(version >= INNO_VERSION(1, 3, 14)) { - is >> util::encoded_string(app_mutex, version.codepage()); + is >> util::binary_string(app_mutex); } else { app_mutex.clear(); } if(version >= INNO_VERSION(3, 0, 0)) { - is >> util::encoded_string(default_user_name, version.codepage()); - is >> util::encoded_string(default_user_organisation, version.codepage()); + is >> util::binary_string(default_user_name); + is >> util::binary_string(default_user_organisation); } else { default_user_name.clear(), default_user_organisation.clear(); } if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION_EXT(3, 0, 6, 1))) { - is >> util::encoded_string(default_serial, version.codepage()); + is >> util::binary_string(default_serial); } else { default_serial.clear(); } @@ -225,37 +226,37 @@ void header::load(std::istream & is, const version & version) { compiled_code.clear(); } if(version >= INNO_VERSION(4, 2, 4)) { - is >> util::encoded_string(app_readme_file, version.codepage()); - is >> util::encoded_string(app_contact, version.codepage()); - is >> util::encoded_string(app_comments, version.codepage()); - is >> util::encoded_string(app_modify_path, version.codepage()); + is >> util::binary_string(app_readme_file); + is >> util::binary_string(app_contact); + is >> util::binary_string(app_comments); + is >> util::binary_string(app_modify_path); } else { app_readme_file.clear(), app_contact.clear(); app_comments.clear(), app_modify_path.clear(); } if(version >= INNO_VERSION(5, 3, 8)) { - is >> util::encoded_string(create_uninstall_registry_key, version.codepage()); + is >> util::binary_string(create_uninstall_registry_key); } else { create_uninstall_registry_key.clear(); } if(version >= INNO_VERSION(5, 3, 10)) { - is >> util::encoded_string(uninstallable, version.codepage()); + is >> util::binary_string(uninstallable); } else { uninstallable.clear(); } if(version >= INNO_VERSION(5, 5, 0)) { - is >> util::encoded_string(close_applications_filter, version.codepage()); + is >> util::binary_string(close_applications_filter); } else { close_applications_filter.clear(); } if(version >= INNO_VERSION(5, 5, 6)) { - is >> util::encoded_string(setup_mutex, version.codepage()); + is >> util::binary_string(setup_mutex); } else { setup_mutex.clear(); } if(version >= INNO_VERSION(5, 6, 1)) { - is >> util::encoded_string(changes_environment, version.codepage()); - is >> util::encoded_string(changes_associations, version.codepage()); + is >> util::binary_string(changes_environment); + is >> util::binary_string(changes_associations); } else { changes_environment.clear(); changes_associations.clear(); @@ -702,6 +703,41 @@ void header::load(std::istream & is, const version & version) { } +void header::decode(util::codepage_id codepage) { + + util::to_utf8(app_name, codepage); + util::to_utf8(app_versioned_name, codepage); + util::to_utf8(app_id, codepage); + util::to_utf8(app_copyright, codepage); + util::to_utf8(app_publisher, codepage); + util::to_utf8(app_publisher_url, codepage); + util::to_utf8(app_support_phone, codepage); + util::to_utf8(app_support_url, codepage); + util::to_utf8(app_updates_url, codepage); + util::to_utf8(app_version, codepage); + util::to_utf8(default_dir_name, codepage); + util::to_utf8(default_group_name, codepage); + util::to_utf8(base_filename, codepage); + util::to_utf8(uninstall_files_dir, codepage); + util::to_utf8(uninstall_name, codepage); + util::to_utf8(uninstall_icon, codepage); + util::to_utf8(app_mutex, codepage); + util::to_utf8(default_user_name, codepage); + util::to_utf8(default_user_organisation, codepage); + util::to_utf8(default_serial, codepage); + util::to_utf8(app_readme_file, codepage); + util::to_utf8(app_contact, codepage); + util::to_utf8(app_comments, codepage); + util::to_utf8(app_modify_path, codepage); + util::to_utf8(create_uninstall_registry_key, codepage); + util::to_utf8(uninstallable, codepage); + util::to_utf8(close_applications_filter, codepage); + util::to_utf8(setup_mutex, codepage); + util::to_utf8(changes_environment, codepage); + util::to_utf8(changes_associations, codepage); + +} + } // namespace setup NAMES(setup::header::flags, "Setup Option", diff --git a/src/setup/header.hpp b/src/setup/header.hpp index 0069d71..645376c 100644 --- a/src/setup/header.hpp +++ b/src/setup/header.hpp @@ -36,6 +36,7 @@ #include "crypto/checksum.hpp" #include "setup/windows.hpp" #include "stream/chunk.hpp" +#include "util/encoding.hpp" #include "util/enum.hpp" #include "util/flags.hpp" @@ -278,6 +279,8 @@ struct header { void load(std::istream & is, const version & version); + void decode(util::codepage_id codepage); + }; } // namespace setup diff --git a/src/setup/icon.cpp b/src/setup/icon.cpp index 3c202c9..b55aeae 100644 --- a/src/setup/icon.cpp +++ b/src/setup/icon.cpp @@ -20,6 +20,7 @@ #include "setup/icon.hpp" +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -36,65 +37,65 @@ STORED_ENUM_MAP(stored_close_setting, icon_entry::NoSetting, } // anonymous namespace -void icon_entry::load(std::istream & is, const version & version) { +void icon_entry::load(std::istream & is, const info & i) { - if(version < INNO_VERSION(1, 3, 0)) { + if(i.version < INNO_VERSION(1, 3, 0)) { (void)util::load(is); // uncompressed size of the entry } - is >> util::encoded_string(name, version.codepage()); - is >> util::encoded_string(filename, version.codepage()); - is >> util::encoded_string(parameters, version.codepage()); - is >> util::encoded_string(working_dir, version.codepage()); - is >> util::encoded_string(icon_file, version.codepage()); - is >> util::encoded_string(comment, version.codepage()); + is >> util::encoded_string(name, i.codepage); + is >> util::encoded_string(filename, i.codepage); + is >> util::encoded_string(parameters, i.codepage); + is >> util::encoded_string(working_dir, i.codepage); + is >> util::encoded_string(icon_file, i.codepage); + is >> util::encoded_string(comment, i.codepage); - load_condition_data(is, version); + load_condition_data(is, i); - if(version >= INNO_VERSION(5, 3, 5)) { - is >> util::encoded_string(app_user_model_id, version.codepage()); + if(i.version >= INNO_VERSION(5, 3, 5)) { + is >> util::encoded_string(app_user_model_id, i.codepage); } else { app_user_model_id.clear(); } - load_version_data(is, version); + load_version_data(is, i.version); - icon_index = util::load(is, version.bits()); + icon_index = util::load(is, i.version.bits()); - if(version >= INNO_VERSION(1, 3, 24)) { + if(i.version >= INNO_VERSION(1, 3, 24)) { show_command = util::load(is); } else { show_command = 1; } - if(version >= INNO_VERSION(1, 3, 15)) { + if(i.version >= INNO_VERSION(1, 3, 15)) { close_on_exit = stored_enum(is).get(); } else { close_on_exit = NoSetting; } - if(version >= INNO_VERSION(2, 0, 7)) { + if(i.version >= INNO_VERSION(2, 0, 7)) { hotkey = util::load(is); } else { hotkey = 0; } - stored_flag_reader flagreader(is, version.bits()); + stored_flag_reader flagreader(is, i.version.bits()); flagreader.add(NeverUninstall); - if(version < INNO_VERSION(1, 3, 26)) { + if(i.version < INNO_VERSION(1, 3, 26)) { flagreader.add(RunMinimized); } flagreader.add(CreateOnlyIfFileExists); - if(version.bits() != 16) { + if(i.version.bits() != 16) { flagreader.add(UseAppPaths); } - if(version >= INNO_VERSION(5, 0, 3)) { + if(i.version >= INNO_VERSION(5, 0, 3)) { flagreader.add(FolderShortcut); } - if(version >= INNO_VERSION(5, 4, 2)) { + if(i.version >= INNO_VERSION(5, 4, 2)) { flagreader.add(ExcludeFromShowInNewInstall); } - if(version >= INNO_VERSION(5, 5, 0)) { + if(i.version >= INNO_VERSION(5, 5, 0)) { flagreader.add(PreventPinning); } diff --git a/src/setup/icon.hpp b/src/setup/icon.hpp index e8330d3..41da3c3 100644 --- a/src/setup/icon.hpp +++ b/src/setup/icon.hpp @@ -37,7 +37,7 @@ namespace setup { -struct version; +struct info; struct icon_entry : public item { @@ -76,7 +76,7 @@ struct icon_entry : public item { flags options; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/info.cpp b/src/setup/info.cpp index 7d0f112..4c16bf4 100644 --- a/src/setup/info.cpp +++ b/src/setup/info.cpp @@ -42,54 +42,32 @@ #include "setup/task.hpp" #include "setup/type.hpp" #include "stream/block.hpp" +#include "util/fstream.hpp" #include "util/load.hpp" #include "util/log.hpp" +#include "util/output.hpp" namespace setup { -namespace { - -struct no_arg { }; - -template -void load_entry(std::istream & is, const setup::version & version, - Entry & entity, Arg arg) { - entity.load(is, version, arg); -} template -void load_entry(std::istream & is, const setup::version & version, - Entry & entity, no_arg arg) { - (void)arg; - entity.load(is, version); -} - -template -void load_entries(std::istream & is, const setup::version & version, - info::entry_types entry_types, size_t count, - std::vector & entries, info::entry_types::enum_type entry_type, - Arg arg = Arg()) { +void info::load_entries(std::istream & is, info::entry_types entry_types, size_t count, + std::vector & entries, info::entry_types::enum_type entry_type) { entries.clear(); if(entry_types & entry_type) { entries.resize(count); for(size_t i = 0; i < count; i++) { - Entry & entry = entries[i]; - load_entry(is, version, entry, arg); + entries[i].load(is, *this); } } else { for(size_t i = 0; i < count; i++) { Entry entry; - load_entry(is, version, entry, arg); + entry.load(is, *this); } } } -template -void load_entries(std::istream & is, const setup::version & version, - info::entry_types entry_types, size_t count, - std::vector & entries, info::entry_types::enum_type entry_type) { - load_entries(is, version, entry_types, count, entries, entry_type); -} +namespace { void load_wizard_images(std::istream & is, const setup::version & version, std::vector & images, info::entry_types entries) { @@ -162,9 +140,11 @@ void check_is_end(stream::block_reader::pointer & is, const char * what) { } // anonymous namespace -void info::load(std::istream & is, entry_types entries, const setup::version & version) { +void info::try_load(std::istream & is, entry_types entries, util::codepage_id force_codepage) { - if(entries & (Messages | NoSkip)) { + debug("trying to load setup headers for version " << version); + + if((entries & (Messages | NoSkip)) || (!version.is_unicode() && !force_codepage)) { entries |= Languages; } @@ -172,27 +152,52 @@ void info::load(std::istream & is, entry_types entries, const setup::version & v header.load(*reader, version); - load_entries(*reader, version, entries, header.language_count, languages, Languages); + load_entries(*reader, entries, header.language_count, languages, Languages); + + if(version.is_unicode()) { + // Unicode installers are always UTF16-LE, do not allow users to override that. + codepage = util::cp_utf16le; + } else if(force_codepage) { + codepage = force_codepage; + } else if(languages.empty()) { + codepage = util::cp_windows1252; + } else { + // Non-Unicode installers do not have a defined codepage but instead just assume the + // codepage of the system the installer is run on. + // Look at the list of available languages to guess a suitable codepage. + codepage = languages[0].codepage; + BOOST_FOREACH(const language_entry & language, languages) { + if(language.codepage == util::cp_windows1252) { + codepage = util::cp_windows1252; + break; + } + } + } + + header.decode(codepage); + BOOST_FOREACH(language_entry & language, languages) { + language.decode(codepage); + } if(version < INNO_VERSION(4, 0, 0)) { load_wizard_and_decompressor(*reader, version, header, *this, entries); } - load_entries(*reader, version, entries, header.message_count, messages, Messages, languages); - load_entries(*reader, version, entries, header.permission_count, permissions, Permissions); - load_entries(*reader, version, entries, header.type_count, types, Types); - load_entries(*reader, version, entries, header.component_count, components, Components); - load_entries(*reader, version, entries, header.task_count, tasks, Tasks); - load_entries(*reader, version, entries, header.directory_count, directories, Directories); - load_entries(*reader, version, entries, header.file_count, files, Files); - load_entries(*reader, version, entries, header.icon_count, icons, Icons); - load_entries(*reader, version, entries, header.ini_entry_count, ini_entries, IniEntries); - load_entries(*reader, version, entries, header.registry_entry_count, registry_entries, RegistryEntries); - load_entries(*reader, version, entries, header.delete_entry_count, delete_entries, DeleteEntries); - load_entries(*reader, version, entries, header.uninstall_delete_entry_count, uninstall_delete_entries, + load_entries(*reader, entries, header.message_count, messages, Messages); + load_entries(*reader, entries, header.permission_count, permissions, Permissions); + load_entries(*reader, entries, header.type_count, types, Types); + load_entries(*reader, entries, header.component_count, components, Components); + load_entries(*reader, entries, header.task_count, tasks, Tasks); + load_entries(*reader, entries, header.directory_count, directories, Directories); + load_entries(*reader, entries, header.file_count, files, Files); + load_entries(*reader, entries, header.icon_count, icons, Icons); + load_entries(*reader, entries, header.ini_entry_count, ini_entries, IniEntries); + load_entries(*reader, entries, header.registry_entry_count, registry_entries, RegistryEntries); + load_entries(*reader, entries, header.delete_entry_count, delete_entries, DeleteEntries); + load_entries(*reader, entries, header.uninstall_delete_entry_count, uninstall_delete_entries, UninstallDeleteEntries); - load_entries(*reader, version, entries, header.run_entry_count, run_entries, RunEntries); - load_entries(*reader, version, entries, header.uninstall_run_entry_count, uninstall_run_entries, + load_entries(*reader, entries, header.run_entry_count, run_entries, RunEntries); + load_entries(*reader, entries, header.uninstall_run_entry_count, uninstall_run_entries, UninstallRunEntries); if(version >= INNO_VERSION(4, 0, 0)) { @@ -203,12 +208,12 @@ void info::load(std::istream & is, entry_types entries, const setup::version & v check_is_end(reader, "unknown data at end of primary header stream"); reader = stream::block_reader::get(is, version); - load_entries(*reader, version, entries, header.data_entry_count, data_entries, DataEntries); + load_entries(*reader, entries, header.data_entry_count, data_entries, DataEntries); check_is_end(reader, "unknown data at end of secondary header stream"); } -void info::load(std::istream & is, entry_types entries) { +void info::load(std::istream & is, entry_types entries, util::codepage_id force_codepage) { version.load(is); @@ -242,7 +247,7 @@ void info::load(std::istream & is, entry_types entries) { try { // Try to parse headers for this version - load(is, entries, version); + try_load(is, entries, force_codepage); if(warnings) { // Parsed without errors but with warnings - try other versions first @@ -268,7 +273,7 @@ void info::load(std::istream & is, entry_types entries) { // Rewind to a previous version that had better results and report those version.value = listed_version; warnings.restore(); - load(is, entries, version); + try_load(is, entries, force_codepage); } else { // Otherwise. report results for the current version warnings.flush(); @@ -289,7 +294,7 @@ void info::load(std::istream & is, entry_types entries) { } -info::info() { } +info::info() : codepage(0) { } info::~info() { } } // namespace setup diff --git a/src/setup/info.hpp b/src/setup/info.hpp index ff1fcde..4873eb0 100644 --- a/src/setup/info.hpp +++ b/src/setup/info.hpp @@ -31,6 +31,7 @@ #include "setup/header.hpp" #include "setup/version.hpp" +#include "util/encoding.hpp" #include "util/flags.hpp" namespace setup { @@ -85,6 +86,8 @@ struct info { setup::version version; + util::codepage_id codepage; + setup::header header; std::vector components; //! \c Components @@ -126,7 +129,9 @@ struct info { * \ref loader::offsets::header_offset. * \param entries What kinds of entries to load. */ - void load(std::istream & is, entry_types entries); + void load(std::istream & is, entry_types entries, util::codepage_id force_codepage = 0); + +private: /*! * Load setup headers for a specific version. @@ -141,7 +146,11 @@ struct info { * * This function does not set the \ref version member. */ - void load(std::istream & is, entry_types entries, const setup::version & version); + void try_load(std::istream & is, entry_types entries, util::codepage_id force_codepage); + + template + void load_entries(std::istream & is, entry_types entry_types, size_t count, + std::vector & entries, entry_types::enum_type entry_type); }; diff --git a/src/setup/ini.cpp b/src/setup/ini.cpp index e1bc19e..b1d0e0b 100644 --- a/src/setup/ini.cpp +++ b/src/setup/ini.cpp @@ -22,6 +22,7 @@ #include +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -40,25 +41,25 @@ STORED_FLAGS_MAP(stored_ini_flags, } // anonymous namespace -void ini_entry::load(std::istream & is, const version & version) { +void ini_entry::load(std::istream & is, const info & i) { - if(version < INNO_VERSION(1, 3, 0)) { + if(i.version < INNO_VERSION(1, 3, 0)) { (void)util::load(is); // uncompressed size of the entry } - is >> util::encoded_string(inifile, version.codepage()); + is >> util::encoded_string(inifile, i.codepage); if(inifile.empty()) { inifile = "{windows}/WIN.INI"; } - is >> util::encoded_string(section, version.codepage()); - is >> util::encoded_string(key, version.codepage()); - is >> util::encoded_string(value, version.codepage()); + is >> util::encoded_string(section, i.codepage); + is >> util::encoded_string(key, i.codepage); + is >> util::encoded_string(value, i.codepage); - load_condition_data(is, version); + load_condition_data(is, i); - load_version_data(is, version); + load_version_data(is, i.version); - if(version.bits() != 16) { + if(i.version.bits() != 16) { options = stored_flags(is).get(); } else { options = stored_flags(is).get(); diff --git a/src/setup/ini.hpp b/src/setup/ini.hpp index c9c805a..c9bae52 100644 --- a/src/setup/ini.hpp +++ b/src/setup/ini.hpp @@ -35,7 +35,7 @@ namespace setup { -struct version; +struct info; struct ini_entry : public item { @@ -54,7 +54,7 @@ struct ini_entry : public item { flags options; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/item.cpp b/src/setup/item.cpp index 6bca6ab..e747711 100644 --- a/src/setup/item.cpp +++ b/src/setup/item.cpp @@ -20,37 +20,38 @@ #include "setup/item.hpp" +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" namespace setup { -void item::load_condition_data(std::istream & is, const version & version) { +void item::load_condition_data(std::istream & is, const info & i) { - if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 8))) { - is >> util::encoded_string(components, version.codepage()); + if(i.version >= INNO_VERSION(2, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(1, 3, 8))) { + is >> util::encoded_string(components, i.codepage); } else { components.clear(); } - if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 17))) { - is >> util::encoded_string(tasks, version.codepage()); + if(i.version >= INNO_VERSION(2, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(1, 3, 17))) { + is >> util::encoded_string(tasks, i.codepage); } else { tasks.clear(); } - if(version >= INNO_VERSION(4, 0, 1)) { - is >> util::encoded_string(languages, version.codepage()); + if(i.version >= INNO_VERSION(4, 0, 1)) { + is >> util::encoded_string(languages, i.codepage); } else { languages.clear(); } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { - is >> util::encoded_string(check, version.codepage()); + if(i.version >= INNO_VERSION(4, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(1, 3, 24))) { + is >> util::encoded_string(check, i.codepage); } else { check.clear(); } - if(version >= INNO_VERSION(4, 1, 0)) { - is >> util::encoded_string(after_install, version.codepage()); - is >> util::encoded_string(before_install, version.codepage()); + if(i.version >= INNO_VERSION(4, 1, 0)) { + is >> util::encoded_string(after_install, i.codepage); + is >> util::encoded_string(before_install, i.codepage); } else { after_install.clear(), before_install.clear(); } diff --git a/src/setup/item.hpp b/src/setup/item.hpp index 5db1916..3137954 100644 --- a/src/setup/item.hpp +++ b/src/setup/item.hpp @@ -33,6 +33,7 @@ namespace setup { +struct info; struct version; struct item { @@ -49,7 +50,7 @@ struct item { protected: - void load_condition_data(std::istream & is, const version & version); + void load_condition_data(std::istream & is, const info & i); void load_version_data(std::istream & is, const version & version) { winver.load(is, version); diff --git a/src/setup/language.cpp b/src/setup/language.cpp index 83ca7f2..425cd78 100644 --- a/src/setup/language.cpp +++ b/src/setup/language.cpp @@ -25,6 +25,7 @@ #include "boost/range/begin.hpp" #include "boost/range/end.hpp" +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" @@ -119,17 +120,15 @@ util::codepage_id default_codepage_for_language(boost::uint32_t language) { } // anonymous namespace -void language_entry::load(std::istream & is, const version & version) { +void language_entry::load(std::istream & is, const info & i) { - if(version >= INNO_VERSION(4, 0, 0)) { - is >> util::encoded_string(name, version.codepage()); - } else { - name = "default"; + if(i.version >= INNO_VERSION(4, 0, 0)) { + is >> util::binary_string(name); } is >> util::binary_string(language_name); - if(version == INNO_VERSION_EXT(5, 5, 7, 1)) { + if(i.version == INNO_VERSION_EXT(5, 5, 7, 1)) { util::binary_string::skip(is); } @@ -138,11 +137,11 @@ void language_entry::load(std::istream & is, const version & version) { is >> util::binary_string(welcome_font); is >> util::binary_string(copyright_font); - if(version >= INNO_VERSION(4, 0, 0)) { + if(i.version >= INNO_VERSION(4, 0, 0)) { is >> util::binary_string(data); } - if(version >= INNO_VERSION(4, 0, 1)) { + if(i.version >= INNO_VERSION(4, 0, 1)) { is >> util::binary_string(license_text); is >> util::binary_string(info_before); is >> util::binary_string(info_after); @@ -152,18 +151,21 @@ void language_entry::load(std::istream & is, const version & version) { language_id = util::load(is); - if(version < INNO_VERSION(4, 2, 2)) { + if(i.version < INNO_VERSION(4, 2, 2)) { codepage = default_codepage_for_language(language_id); - } else if(version < INNO_VERSION(5, 3, 0) || !version.is_unicode()) { + } else if(!i.version.is_unicode()) { codepage = util::load(is); if(!codepage) { - codepage = version.codepage(); + codepage = util::cp_windows1252; } } else { + if(i.version < INNO_VERSION(5, 3, 0)) { + (void)util::load(is); + } codepage = util::cp_utf16le; } - if(version >= INNO_VERSION(4, 2, 2)) { + if(i.version >= INNO_VERSION(4, 2, 2)) { util::to_utf8(language_name, util::cp_utf16le); } else { util::to_utf8(language_name, codepage); @@ -171,7 +173,7 @@ void language_entry::load(std::istream & is, const version & version) { dialog_font_size = util::load(is); - if(version < INNO_VERSION(4, 1, 0)) { + if(i.version < INNO_VERSION(4, 1, 0)) { dialog_font_standard_height = util::load(is); } else { dialog_font_standard_height = 0; @@ -181,11 +183,11 @@ void language_entry::load(std::istream & is, const version & version) { welcome_font_size = util::load(is); copyright_font_size = util::load(is); - if(version == INNO_VERSION_EXT(5, 5, 7, 1)) { + if(i.version == INNO_VERSION_EXT(5, 5, 7, 1)) { util::load(is); // always 8 or 9? } - if(version >= INNO_VERSION(5, 2, 3)) { + if(i.version >= INNO_VERSION(5, 2, 3)) { right_to_left = util::load_bool(is); } else { right_to_left = false; @@ -193,4 +195,13 @@ void language_entry::load(std::istream & is, const version & version) { } +void language_entry::decode(util::codepage_id codepage) { + + util::to_utf8(name, codepage); + if(name.empty()) { + name = "default"; + } + +} + } // namespace setup diff --git a/src/setup/language.hpp b/src/setup/language.hpp index 17d0175..4a03c2f 100644 --- a/src/setup/language.hpp +++ b/src/setup/language.hpp @@ -31,9 +31,11 @@ #include +#include "util/encoding.hpp" + namespace setup { -struct version; +struct info; struct language_entry { @@ -60,7 +62,9 @@ struct language_entry { bool right_to_left; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); + + void decode(util::codepage_id codepage); }; diff --git a/src/setup/message.cpp b/src/setup/message.cpp index 88e5f0a..0834451 100644 --- a/src/setup/message.cpp +++ b/src/setup/message.cpp @@ -22,6 +22,7 @@ #include +#include "setup/info.hpp" #include "setup/language.hpp" #include "setup/version.hpp" #include "util/encoding.hpp" @@ -29,23 +30,22 @@ namespace setup { -void message_entry::load(std::istream & is, const version & version, - const std::vector & languages) { +void message_entry::load(std::istream & is, const info & i) { - is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(name, i.codepage); is >> util::binary_string(value); language = util::load(is); boost::uint32_t codepage; if(language < 0) { - codepage = version.codepage(); - } else if(size_t(language) >= languages.size()) { + codepage = i.codepage; + } else if(size_t(language) >= i.languages.size()) { // Unknown language, don't try to decode value.clear(); return; } else { - codepage = languages[size_t(language)].codepage; + codepage = i.languages[size_t(language)].codepage; } util::to_utf8(value, codepage); diff --git a/src/setup/message.hpp b/src/setup/message.hpp index 8559a1d..0fe1aa9 100644 --- a/src/setup/message.hpp +++ b/src/setup/message.hpp @@ -28,12 +28,10 @@ #include #include -#include namespace setup { -struct version; -struct language_entry; +struct info; struct message_entry { @@ -48,8 +46,7 @@ struct message_entry { // Index into the default language entry list or -1. int language; - void load(std::istream & is, const version & version, - const std::vector & languages); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/permission.cpp b/src/setup/permission.cpp index 2b36fd1..c8d0d50 100644 --- a/src/setup/permission.cpp +++ b/src/setup/permission.cpp @@ -20,14 +20,13 @@ #include "setup/permission.hpp" -#include "setup/version.hpp" #include "util/load.hpp" namespace setup { -void permission_entry::load(std::istream & is, const version & version) { +void permission_entry::load(std::istream & is, const info & i) { - (void)version; + (void)i; is >> util::binary_string(permissions); // an array of TGrantPermissionEntry's diff --git a/src/setup/permission.hpp b/src/setup/permission.hpp index c30fcd1..6016af4 100644 --- a/src/setup/permission.hpp +++ b/src/setup/permission.hpp @@ -31,7 +31,7 @@ namespace setup { -struct version; +struct info; struct permission_entry { @@ -39,7 +39,7 @@ struct permission_entry { std::string permissions; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/registry.cpp b/src/setup/registry.cpp index 7d1f88e..48ae293 100644 --- a/src/setup/registry.cpp +++ b/src/setup/registry.cpp @@ -22,6 +22,7 @@ #include +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -58,73 +59,73 @@ STORED_ENUM_MAP(stored_registry_entry_type_2, registry_entry::None, } // anonymous namespace -void registry_entry::load(std::istream & is, const version & version) { +void registry_entry::load(std::istream & is, const info & i) { - if(version < INNO_VERSION(1, 3, 0)) { + if(i.version < INNO_VERSION(1, 3, 0)) { (void)util::load(is); // uncompressed size of the entry } - is >> util::encoded_string(key, version.codepage()); - if(version.bits() != 16) { - is >> util::encoded_string(name, version.codepage()); + is >> util::encoded_string(key, i.codepage); + if(i.version.bits() != 16) { + is >> util::encoded_string(name, i.codepage); } else { name.clear(); } is >> util::binary_string(value); - load_condition_data(is, version); + load_condition_data(is, i); - if(version >= INNO_VERSION(4, 0, 11) && version < INNO_VERSION(4, 1, 0)) { - is >> util::encoded_string(permissions, version.codepage()); + if(i.version >= INNO_VERSION(4, 0, 11) && i.version < INNO_VERSION(4, 1, 0)) { + is >> util::binary_string(permissions); } else { permissions.clear(); } - load_version_data(is, version); + load_version_data(is, i.version); - if(version.bits() != 16) { + if(i.version.bits() != 16) { hive = hive_name(util::load(is) & ~0x80000000); } else { hive = Unset; } - if(version >= INNO_VERSION(4, 1, 0)) { + if(i.version >= INNO_VERSION(4, 1, 0)) { permission = util::load(is); } else { permission = -1; } - if(version >= INNO_VERSION(5, 2, 5)) { + if(i.version >= INNO_VERSION(5, 2, 5)) { type = stored_enum(is).get(); - } else if(version.bits() != 16) { + } else if(i.version.bits() != 16) { type = stored_enum(is).get(); } else { type = stored_enum(is).get(); } - stored_flag_reader flagreader(is, version.bits()); + stored_flag_reader flagreader(is, i.version.bits()); - if(version.bits() != 16) { + if(i.version.bits() != 16) { flagreader.add(CreateValueIfDoesntExist); flagreader.add(UninsDeleteValue); } flagreader.add(UninsClearValue); flagreader.add(UninsDeleteEntireKey); flagreader.add(UninsDeleteEntireKeyIfEmpty); - if(version >= INNO_VERSION(1, 2, 6)) { + if(i.version >= INNO_VERSION(1, 2, 6)) { flagreader.add(PreserveStringType); } - if(version >= INNO_VERSION(1, 3, 9)) { + if(i.version >= INNO_VERSION(1, 3, 9)) { flagreader.add(DeleteKey); flagreader.add(DeleteValue); } - if(version >= INNO_VERSION(1, 3, 12)) { + if(i.version >= INNO_VERSION(1, 3, 12)) { flagreader.add(NoError); } - if(version >= INNO_VERSION(1, 3, 16)) { + if(i.version >= INNO_VERSION(1, 3, 16)) { flagreader.add(DontCreateKey); } - if(version >= INNO_VERSION(5, 1, 0)) { + if(i.version >= INNO_VERSION(5, 1, 0)) { flagreader.add(Bits32); flagreader.add(Bits64); } diff --git a/src/setup/registry.hpp b/src/setup/registry.hpp index 3fe4d22..a7d9a05 100644 --- a/src/setup/registry.hpp +++ b/src/setup/registry.hpp @@ -36,7 +36,7 @@ namespace setup { -struct version; +struct info; struct registry_entry : public item { @@ -90,7 +90,7 @@ struct registry_entry : public item { flags options; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/run.cpp b/src/setup/run.cpp index 9541f58..dbeaffa 100644 --- a/src/setup/run.cpp +++ b/src/setup/run.cpp @@ -22,6 +22,7 @@ #include +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -38,39 +39,39 @@ STORED_ENUM_MAP(stored_run_wait_condition, run_entry::WaitUntilTerminated, } // anonymous namespace -void run_entry::load(std::istream & is, const version & version) { +void run_entry::load(std::istream & is, const info & i) { - if(version < INNO_VERSION(1, 3, 0)) { + if(i.version < INNO_VERSION(1, 3, 0)) { (void)util::load(is); // uncompressed size of the entry } - is >> util::encoded_string(name, version.codepage()); - is >> util::encoded_string(parameters, version.codepage()); - is >> util::encoded_string(working_dir, version.codepage()); - if(version >= INNO_VERSION(1, 3, 9)) { - is >> util::encoded_string(run_once_id, version.codepage()); + is >> util::encoded_string(name, i.codepage); + is >> util::encoded_string(parameters, i.codepage); + is >> util::encoded_string(working_dir, i.codepage); + if(i.version >= INNO_VERSION(1, 3, 9)) { + is >> util::encoded_string(run_once_id, i.codepage); } else { run_once_id.clear(); } - if(version >= INNO_VERSION(2, 0, 2)) { - is >> util::encoded_string(status_message, version.codepage()); + if(i.version >= INNO_VERSION(2, 0, 2)) { + is >> util::encoded_string(status_message, i.codepage); } else { status_message.clear(); } - if(version >= INNO_VERSION(5, 1, 13)) { - is >> util::encoded_string(verb, version.codepage()); + if(i.version >= INNO_VERSION(5, 1, 13)) { + is >> util::encoded_string(verb, i.codepage); } else { verb.clear(); } - if(version >= INNO_VERSION(2, 0, 0) || version.is_isx()) { - is >> util::encoded_string(description, version.codepage()); + if(i.version >= INNO_VERSION(2, 0, 0) || i.version.is_isx()) { + is >> util::encoded_string(description, i.codepage); } - load_condition_data(is, version); + load_condition_data(is, i); - load_version_data(is, version); + load_version_data(is, i.version); - if(version >= INNO_VERSION(1, 3, 24)) { + if(i.version >= INNO_VERSION(1, 3, 24)) { show_command = util::load(is); } else { show_command = 0; @@ -78,28 +79,28 @@ void run_entry::load(std::istream & is, const version & version) { wait = stored_enum(is).get(); - stored_flag_reader flagreader(is, version.bits()); + stored_flag_reader flagreader(is, i.version.bits()); - if(version >= INNO_VERSION(1, 2, 3)) { + if(i.version >= INNO_VERSION(1, 2, 3)) { flagreader.add(ShellExec); } - if(version >= INNO_VERSION(1, 3, 9) || (version.is_isx() && version >= INNO_VERSION(1, 3, 8))) { + if(i.version >= INNO_VERSION(1, 3, 9) || (i.version.is_isx() && i.version >= INNO_VERSION(1, 3, 8))) { flagreader.add(SkipIfDoesntExist); } - if(version >= INNO_VERSION(2, 0, 0)) { + if(i.version >= INNO_VERSION(2, 0, 0)) { flagreader.add(PostInstall); flagreader.add(Unchecked); flagreader.add(SkipIfSilent); flagreader.add(SkipIfNotSilent); } - if(version >= INNO_VERSION(2, 0, 8)) { + if(i.version >= INNO_VERSION(2, 0, 8)) { flagreader.add(HideWizard); } - if(version >= INNO_VERSION(5, 1, 10)) { + if(i.version >= INNO_VERSION(5, 1, 10)) { flagreader.add(Bits32); flagreader.add(Bits64); } - if(version >= INNO_VERSION(5, 2, 0)) { + if(i.version >= INNO_VERSION(5, 2, 0)) { flagreader.add(RunAsOriginalUser); } diff --git a/src/setup/run.hpp b/src/setup/run.hpp index 3c1230c..e17fd46 100644 --- a/src/setup/run.hpp +++ b/src/setup/run.hpp @@ -35,7 +35,7 @@ namespace setup { -struct version; +struct info; struct run_entry : public item { @@ -72,7 +72,7 @@ struct run_entry : public item { flags options; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/task.cpp b/src/setup/task.cpp index e12dc18..2ee87f6 100644 --- a/src/setup/task.cpp +++ b/src/setup/task.cpp @@ -22,52 +22,53 @@ #include +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" namespace setup { -void task_entry::load(std::istream & is, const version & version) { +void task_entry::load(std::istream & is, const info & i) { - is >> util::encoded_string(name, version.codepage()); - is >> util::encoded_string(description, version.codepage()); - is >> util::encoded_string(group_description, version.codepage()); - is >> util::encoded_string(components, version.codepage()); - if(version >= INNO_VERSION(4, 0, 1)) { - is >> util::encoded_string(languages, version.codepage()); + is >> util::encoded_string(name, i.codepage); + is >> util::encoded_string(description, i.codepage); + is >> util::encoded_string(group_description, i.codepage); + is >> util::encoded_string(components, i.codepage); + if(i.version >= INNO_VERSION(4, 0, 1)) { + is >> util::encoded_string(languages, i.codepage); } else { languages.clear(); } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { - is >> util::encoded_string(check, version.codepage()); + if(i.version >= INNO_VERSION(4, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(1, 3, 24))) { + is >> util::encoded_string(check, i.codepage); } else { check.clear(); } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 3))) { + if(i.version >= INNO_VERSION(4, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(3, 0, 3))) { level = util::load(is); } else { level = 0; } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 4))) { + if(i.version >= INNO_VERSION(4, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(3, 0, 4))) { used = util::load_bool(is); } else { used = true; } - winver.load(is, version); + winver.load(is, i.version); stored_flag_reader flagreader(is); flagreader.add(Exclusive); flagreader.add(Unchecked); - if(version >= INNO_VERSION(2, 0, 5)) { + if(i.version >= INNO_VERSION(2, 0, 5)) { flagreader.add(Restart); } - if(version >= INNO_VERSION(2, 0, 6)) { + if(i.version >= INNO_VERSION(2, 0, 6)) { flagreader.add(CheckedOnce); } - if(version >= INNO_VERSION(4, 2, 3)) { + if(i.version >= INNO_VERSION(4, 2, 3)) { flagreader.add(DontInheritCheck); } diff --git a/src/setup/task.hpp b/src/setup/task.hpp index caa9521..a6acd52 100644 --- a/src/setup/task.hpp +++ b/src/setup/task.hpp @@ -35,7 +35,7 @@ namespace setup { -struct version; +struct info; struct task_entry { @@ -63,7 +63,7 @@ struct task_entry { flags options; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/type.cpp b/src/setup/type.cpp index 6bb81f3..b45c199 100644 --- a/src/setup/type.cpp +++ b/src/setup/type.cpp @@ -20,6 +20,7 @@ #include "setup/type.hpp" +#include "setup/info.hpp" #include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -51,35 +52,35 @@ NAMED_FLAGS(setup::type_flags) namespace setup { -void type_entry::load(std::istream & is, const version & version) { +void type_entry::load(std::istream & is, const info & i) { USE_FLAG_NAMES(setup::type_flags) - is >> util::encoded_string(name, version.codepage()); - is >> util::encoded_string(description, version.codepage()); - if(version >= INNO_VERSION(4, 0, 1)) { - is >> util::encoded_string(languages, version.codepage()); + is >> util::encoded_string(name, i.codepage); + is >> util::encoded_string(description, i.codepage); + if(i.version >= INNO_VERSION(4, 0, 1)) { + is >> util::encoded_string(languages, i.codepage); } else { languages.clear(); } - if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { - is >> util::encoded_string(check, version.codepage()); + if(i.version >= INNO_VERSION(4, 0, 0) || (i.version.is_isx() && i.version >= INNO_VERSION(1, 3, 24))) { + is >> util::encoded_string(check, i.codepage); } else { check.clear(); } - winver.load(is, version); + winver.load(is, i.version); type_flags options = stored_flags(is).get(); custom_type = ((options & CustomSetupType) != 0); - if(version >= INNO_VERSION(4, 0, 3)) { + if(i.version >= INNO_VERSION(4, 0, 3)) { type = stored_enum(is).get(); } else { type = User; } - if(version >= INNO_VERSION(4, 0, 0)) { + if(i.version >= INNO_VERSION(4, 0, 0)) { size = util::load(is); } else { size = util::load(is); diff --git a/src/setup/type.hpp b/src/setup/type.hpp index 83d571b..8ba0594 100644 --- a/src/setup/type.hpp +++ b/src/setup/type.hpp @@ -37,7 +37,7 @@ namespace setup { -struct version; +struct info; struct type_entry { @@ -63,7 +63,7 @@ struct type_entry { boost::uint64_t size; - void load(std::istream & is, const version & version); + void load(std::istream & is, const info & i); }; diff --git a/src/setup/version.hpp b/src/setup/version.hpp index 8b2e306..568797f 100644 --- a/src/setup/version.hpp +++ b/src/setup/version.hpp @@ -81,9 +81,6 @@ struct version { bool is_unicode() const { return (variant & Unicode) != 0; } bool is_isx() const { return (variant & ISX) != 0; } - //! \return the Windows codepage used to encode strings - boost::uint32_t codepage() const { return boost::uint32_t(is_unicode() ? 1200 : 1252); } - //! \return true if the version stored might not be correct bool is_ambiguous() const;