Ejemplo n.º 1
0
block_reader::pointer block_reader::get(std::istream & base, const setup::version & version) {
	
	USE_ENUM_NAMES(block_compression)
	
	uint32_t expected_checksum = load_number<uint32_t>(base);
	crypto::crc32 actual_checksum;
	actual_checksum.init();
	
	uint32_t stored_size;
	block_compression compression;
	
	if(version >= INNO_VERSION(4, 0, 9)) {
		
		stored_size = actual_checksum.load_number<uint32_t>(base);
		uint8_t compressed = actual_checksum.load_number<uint8_t>(base);
		
		compression = compressed ? (version >= INNO_VERSION(4, 1, 6) ? LZMA1 : Zlib) : Stored;
		
	} else {
		
		uint32_t compressed_size = actual_checksum.load_number<uint32_t>(base);
		uint32_t uncompressed_size = actual_checksum.load_number<uint32_t>(base);
		
		if(compressed_size == uint32_t(-1)) {
			stored_size = uncompressed_size, compression = Stored;
		} else {
			stored_size = compressed_size, compression = Zlib;
		}
		
		// Add the size of a CRC32 checksum for each 4KiB subblock.
		stored_size += uint32_t(ceildiv<uint64_t>(stored_size, 4096) * 4);
	}
	
	if(actual_checksum.finalize() != expected_checksum) {
		throw block_error("block CRC32 mismatch");
	}
	
	debug("[block] size: " << stored_size << "  compression: " << compression);
	
	boost::shared_ptr<io::filtering_istream> fis = boost::make_shared<io::filtering_istream>();
	
	switch(compression) {
		case Stored: break;
		case Zlib: fis->push(io::zlib_decompressor(), 8192); break;
	#if INNOEXTRACT_HAVE_LZMA
		case LZMA1: fis->push(inno_lzma1_decompressor(), 8192); break;
	#else
		case LZMA1: throw block_error("LZMA decompression not supported by this "
			                  + std::string(innoextract_name) + " build");
	#endif
	}
	
	fis->push(inno_block_filter(), 4096);
	
	fis->push(io::restrict(base, 0, stored_size));
	
	return fis;
}
Ejemplo n.º 2
0
void run_entry::load(std::istream & is, const version & version) {

    if(version < INNO_VERSION(1, 3, 21)) {
        ::load<uint32_t>(is); // uncompressed size of the directory entry structure
    }

    is >> encoded_string(name, version.codepage());
    is >> encoded_string(parameters, version.codepage());
    is >> encoded_string(working_dir, version.codepage());
    if(version >= INNO_VERSION(1, 3, 21)) {
        is >> encoded_string(run_once_id, version.codepage());
    } else {
Ejemplo n.º 3
0
void header::load(std::istream & is, const version & version) {
	
	options = 0;
	
	if(version < INNO_VERSION(1, 3, 21)) {
		(void)util::load<boost::uint32_t>(is); // uncompressed size of the setup header
	}
	
	is >> util::encoded_string(app_name, version.codepage());
	is >> util::encoded_string(app_versioned_name, version.codepage());
	if(version >= INNO_VERSION(1, 3, 21)) {
		is >> util::encoded_string(app_id, version.codepage());
	}
Ejemplo n.º 4
0
void registry_entry::load(std::istream & is, const version & version) {
	
	if(version < INNO_VERSION(1, 3, 21)) {
		(void)util::load<boost::uint32_t>(is); // uncompressed size of the entry
	}
	
	is >> util::encoded_string(key, version.codepage());
	if(version.bits != 16) {
		is >> util::encoded_string(name, version.codepage());
	} else {
Ejemplo n.º 5
0
static void load_wizard_and_decompressor(std::istream & is, const setup::version & version,
                                        const setup::header & header,
                                        setup::info & info, info::entry_types entries) {
	
	(void)entries;
	
	info.wizard_image.clear();
	info.wizard_image_small.clear();
	if(entries & (info::WizardImages | info::NoSkip)) {
		is >> util::binary_string(info.wizard_image);
		if(version >= INNO_VERSION(2, 0, 0)) {
			is >> util::binary_string(info.wizard_image_small);
		}
Ejemplo n.º 6
0
bool version::is_ambiguous() const {
	
	if(value == INNO_VERSION(2, 0, 1)) {
		// might be either 2.0.1 or 2.0.2
		return true;
	}
	
	if(value == INNO_VERSION(3, 0, 3)) {
		// might be either 3.0.3 or 3.0.4
		return true;
	}
	
	if(value == INNO_VERSION(4, 2, 3)) {
		// might be either 4.2.3 or 4.2.4
		return true;
	}
	
	if(value == INNO_VERSION(5, 5, 0)) {
		// might be either 5.5.0 or 5.5.0.1
		return true;
	}
	
	return false;
}
Ejemplo n.º 7
0
void ini_entry::load(std::istream & is, const version & version) {
	
	if(version < INNO_VERSION(1, 3, 21)) {
		::load<uint32_t>(is); // uncompressed size of the ini entry structure
	}
	
	is >> encoded_string(inifile, version.codepage());
	if(inifile.empty()) {
		inifile = "{windows}/WIN.INI";
	}
	is >> encoded_string(section, version.codepage());
	is >> encoded_string(key, version.codepage());
	is >> encoded_string(value, version.codepage());
	
	load_condition_data(is, version);
	
	load_version_data(is, version);
	
	if(version.bits != 16) {
		options = stored_flags<stored_ini_flags>(is).get();
	} else {
		options = stored_flags<stored_ini_flags, 16>(is).get();
	}
}
Ejemplo n.º 8
0
void version::load(std::istream & is) {
	
	static const char digits[] = "0123456789";
	
	BOOST_STATIC_ASSERT(sizeof(stored_legacy_version) <= sizeof(stored_version));
	
	stored_legacy_version legacy_version;
	is.read(legacy_version, std::streamsize(sizeof(legacy_version)));
	
	if(legacy_version[0] == 'i' && legacy_version[sizeof(legacy_version) - 1] == '\x1a') {
		
		for(size_t i = 0; i < size_t(boost::size(legacy_versions)); i++) {
			if(!memcmp(legacy_version, legacy_versions[i].name, sizeof(legacy_version))) {
				value = legacy_versions[i].version;
				bits = legacy_versions[i].bits;
				unicode = false;
				known = true;
				debug("known legacy version: \"" << versions[i].name << '"');
				return;
			}
		}
		
		debug("unknown legacy version: \""
		      << std::string(legacy_version, sizeof(legacy_version)) << '"');
		
		if(legacy_version[0] != 'i' || legacy_version[2] != '.' || legacy_version[4] != '.'
		   || legacy_version[7] != '-' || legacy_version[8] != '-') {
			throw version_error();
		}
		
		if(legacy_version[9] == '1' && legacy_version[10] == '6') {
			bits = 16;
		} else if(legacy_version[9] == '3' && legacy_version[10] == '2') {
			bits = 32;
		} else {
			throw version_error();
		}
		
		std::string version_str(legacy_version, sizeof(legacy_version));
		
		try {
			unsigned a = util::to_unsigned(version_str.data() + 1, 1);
			unsigned b = util::to_unsigned(version_str.data() + 3, 1);
			unsigned c = util::to_unsigned(version_str.data() + 5, 2);
			value = INNO_VERSION(a, b, c);
		} catch(boost::bad_lexical_cast) {
			throw version_error();
		}
		
		unicode = false;
		known = false;
		
		return;
	}
	
	stored_version version;
	BOOST_STATIC_ASSERT(sizeof(legacy_version) <= sizeof(version));
	memcpy(version, legacy_version, sizeof(legacy_version));
	is.read(version + sizeof(legacy_version),
	        std::streamsize(sizeof(version) - sizeof(legacy_version)));
	
	
	for(size_t i = 0; i < size_t(boost::size(versions)); i++) {
		if(!memcmp(version, versions[i].name, sizeof(version))) {
			value = versions[i].version;
			bits = 32;
			unicode = versions[i].unicode;
			known = true;
			debug("known version: \"" << versions[i].name << '"');
			return;
		}
	}
	
	char * end = std::find(version, version + boost::size(version), '\0');
	std::string version_str(version, end);
	debug("unknown version: \"" << version_str << '"');
	if(version_str.find("Inno Setup") == std::string::npos) {
		throw version_error();
	}
	
	size_t bracket = version_str.find('(');
	for(; bracket != std::string::npos; bracket = version_str.find('(', bracket + 1)) {
		
		if(version_str.length() - bracket < 6) {
			continue;
		}
		
		try {
			
			size_t a_start = bracket + 1;
			size_t a_end = version_str.find_first_not_of(digits, a_start);
			if(a_end == std::string::npos || version_str[a_end] != '.') {
				continue;
			}
			unsigned a = util::to_unsigned(version_str.data() + a_start, a_end - a_start);
			
			size_t b_start = a_end + 1;
			size_t b_end = version_str.find_first_not_of(digits, b_start);
			if(b_end == std::string::npos || version_str[b_end] != '.') {
				continue;
			}
			unsigned b = util::to_unsigned(version_str.data() + b_start, b_end - b_start);
			
			size_t c_start = b_end + 1;
			size_t c_end = version_str.find_first_not_of(digits, c_start);
			if(c_end == std::string::npos) {
				continue;
			}
			unsigned c = util::to_unsigned(version_str.data() + c_start, c_end - c_start);
			
			size_t d_start = c_end;
			if(version_str[d_start] == 'a') {
				if(d_start + 1 >= version_str.length()) {
					continue;
				}
				d_start++;
			}
			
			unsigned d = 0;
			if(version_str[d_start] == '.') {
				d_start++;
				size_t d_end = version_str.find_first_not_of(digits, d_start);
				if(d_end != std::string::npos && d_end != d_start) {
					d = util::to_unsigned(version_str.data() + d_start, d_end - d_start);
				}
			}
			
			value = INNO_VERSION_EXT(a, b, c, d);
			break;
			
		} catch(boost::bad_lexical_cast) {
			continue;
		}
	}
	if(bracket == std::string::npos) {
		throw version_error();
	}
	
	bits = 32;
	unicode = (version_str.find("(u)") != std::string::npos);
	known = false;
}
Ejemplo n.º 9
0
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 << "[file location] unexpected disk number: " << chunk.first_slice
			            << " / " << 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);
	}
	
	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 << "[file location] unexpected filetime: " << filetime;
		}
		filetime -= FiletimeOffset;
		
		timestamp = filetime / 10000000;
		timestamp_nsec = boost::uint32_t(filetime % 10000000) * 100;
		
	}
	
	file_version_ms = util::load<boost::uint32_t>(is);
	file_version_ls = util::load<boost::uint32_t>(is);
	
	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);
	}
	
	options |= flagreader;
	
	if(options & ChunkCompressed) {
		chunk.compression = stream::UnknownCompression;
	} else {
		chunk.compression = stream::Stored;
	}
	if(options & BZipped) {
		options |= ChunkCompressed;
		chunk.compression = stream::BZip2;
	}
	
	chunk.encrypted = ((options & ChunkEncrypted) != 0);
	
	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;
	}
}