diff --git a/CHANGELOG b/CHANGELOG index 2a97bfa..fc660e5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ innoextract 1.7 (TDB) - Added (preliminary) support for Inno Setup 5.6.0 installers - Fixed building in paths that contain regex expressions - Fixed case-sensitivity in parent directory when creating subdirectories + - Fixed .bin slice file names used with Inno Setup versions older than 4.1.7 innoextract 1.6 (2016-03-24) - Added support for Inno Setup 5.5.7 (and 5.5.8) installers diff --git a/src/cli/extract.cpp b/src/cli/extract.cpp index 60c457b..fa2c226 100644 --- a/src/cli/extract.cpp +++ b/src/cli/extract.cpp @@ -782,15 +782,22 @@ void process_file(const fs::path & file, const extract_options & o) { total_size += location.uncompressed_size; } - fs::path dir = file.parent_path(); - std::string basename = util::as_string(file.stem()); - boost::scoped_ptr slice_reader; if(o.extract || o.test) { if(offsets.data_offset) { slice_reader.reset(new stream::slice_reader(&ifs, offsets.data_offset)); } else { - slice_reader.reset(new stream::slice_reader(dir, basename, info.header.slices_per_disk)); + fs::path dir = file.parent_path(); + std::string basename = util::as_string(file.stem()); + std::string basename2 = info.header.base_filename; + // Prevent access to unexpected files + std::replace(basename2.begin(), basename2.end(), '/', '_'); + std::replace(basename2.begin(), basename2.end(), '\\', '_'); + // Older Inno Setup versions used the basename stored in the headers, change our default accordingly + if(info.version < INNO_VERSION(4, 1, 7) && !basename2.empty()) { + std::swap(basename2, basename); + } + slice_reader.reset(new stream::slice_reader(dir, basename, basename2, info.header.slices_per_disk)); } } @@ -963,7 +970,7 @@ void process_file(const fs::path & file, const extract_options & o) { extract_progress.clear(); if(o.warn_unused || o.gog) { - gog::probe_bin_files(o, info, dir, basename, offsets.data_offset == 0); + gog::probe_bin_files(o, info, file, offsets.data_offset == 0); } } diff --git a/src/cli/gog.cpp b/src/cli/gog.cpp index dfdb35f..3a27bb7 100644 --- a/src/cli/gog.cpp +++ b/src/cli/gog.cpp @@ -488,8 +488,11 @@ size_t probe_bin_file_series(const extract_options & o, const setup::info & info } // anonymous namespace -void probe_bin_files(const extract_options & o, const setup::info & info, const fs::path & dir, - const std::string & basename, bool external) { +void probe_bin_files(const extract_options & o, const setup::info & info, + const fs::path & setup_file, bool external) { + + boost::filesystem::path dir = setup_file.parent_path(); + std::string basename = util::as_string(setup_file.stem()); size_t bin_count = 0; bin_count += probe_bin_file_series(o, info, dir, basename + ".bin"); diff --git a/src/cli/gog.hpp b/src/cli/gog.hpp index 7b09435..281ecbb 100644 --- a/src/cli/gog.hpp +++ b/src/cli/gog.hpp @@ -41,7 +41,7 @@ namespace gog { std::string get_game_id(const setup::info & info); void probe_bin_files(const extract_options & o, const setup::info & info, - const boost::filesystem::path & dir, const std::string & basename, bool external); + const boost::filesystem::path & setup_file, bool external); } // namespace gog diff --git a/src/stream/slice.cpp b/src/stream/slice.cpp index 335ddea..d9eb55e 100644 --- a/src/stream/slice.cpp +++ b/src/stream/slice.cpp @@ -57,10 +57,10 @@ slice_reader::slice_reader(std::istream * istream, boost::uint32_t data_offset) } } -slice_reader::slice_reader(const path_type & dir, const std::string & base_file, - size_t slices_per_disk) +slice_reader::slice_reader(const path_type & dir, const std::string & basename, + const std::string & basename2, size_t slices_per_disk) : data_offset(0), - dir(dir), base_file(base_file), + dir(dir), base_file(basename), base_file2(basename2), slices_per_disk(slices_per_disk), current_slice(0), slice_size(0), is(&ifs) { } @@ -79,6 +79,10 @@ void slice_reader::seek(size_t slice) { bool slice_reader::open_file(const path_type & file) { + if(!boost::filesystem::exists(file)) { + return false; + } + log_info << "Opening \"" << color::cyan << file.string() << color::reset << '"'; ifs.close(); @@ -160,13 +164,20 @@ void slice_reader::open(size_t slice) { ifs.close(); path_type slice_file = slice_filename(base_file, slice, slices_per_disk); - if(open_file(dir / slice_file)) { return; } + path_type slice_file2 = slice_filename(base_file2, slice, slices_per_disk); + if(!base_file2.empty() && slice_file2 != slice_file && open_file(dir / slice_file2)) { + return; + } + std::ostringstream oss; oss << "could not open slice " << slice << ": " << slice_file; + if(!base_file2.empty() && slice_file2 != slice_file) { + oss << " or " << slice_file2; + } throw slice_error(oss.str()); } diff --git a/src/stream/slice.hpp b/src/stream/slice.hpp index 45be534..e0986ea 100644 --- a/src/stream/slice.hpp +++ b/src/stream/slice.hpp @@ -64,6 +64,7 @@ class slice_reader : public boost::iostreams::source { // Information for eading external setup data path_type dir; //!< Slice directory specified at construction. std::string base_file; //!< Base file name for slices. + std::string base_file2; //!< Fallback base filename for slices. const size_t slices_per_disk; //!< Number of slices grouped into each disk (for names). // Information about the current slice @@ -110,9 +111,11 @@ public: * * \param dir The directory containing the slice files. * \param basename The base name for slice files. + * \param basename2 Alternative base name for slice files. * \param slices_per_disk How many slices are grouped into one disk. Must not be \c 0. */ - slice_reader(const path_type & dir, const std::string & basename, size_t slices_per_disk); + slice_reader(const path_type & dir, const std::string & basename, const std::string & basename2, + size_t slices_per_disk); /*! * Attempt to seek to an offset within a slice.