1 /*
2 * Copyright (C) 2011-2020 Daniel Scharrer
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the author(s) be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 */
20
21 #include "setup/file.hpp"
22
23 #include "setup/info.hpp"
24 #include "setup/version.hpp"
25 #include "util/load.hpp"
26 #include "util/log.hpp"
27 #include "util/storedenum.hpp"
28
29 namespace setup {
30
31 namespace {
32
33 enum file_copy_mode {
34 cmNormal,
35 cmIfDoesntExist,
36 cmAlwaysOverwrite,
37 cmAlwaysSkipIfSameOrOlder,
38 };
39
40 STORED_ENUM_MAP(stored_file_copy_mode, cmNormal,
41 cmNormal,
42 cmIfDoesntExist,
43 cmAlwaysOverwrite,
44 cmAlwaysSkipIfSameOrOlder,
45 );
46
47 STORED_ENUM_MAP(stored_file_type_0, file_entry::UserFile,
48 file_entry::UserFile,
49 file_entry::UninstExe,
50 );
51
52 // win32, before 5.0.0
53 STORED_ENUM_MAP(stored_file_type_1, file_entry::UserFile,
54 file_entry::UserFile,
55 file_entry::UninstExe,
56 file_entry::RegSvrExe,
57 );
58
59 } // anonymous namespace
60
61 } // namespace setup
62
63 NAMED_ENUM(setup::file_copy_mode)
64
65 NAMES(setup::file_copy_mode, "File Copy Mode",
66 "normal",
67 "if doesn't exist",
68 "always overwrite",
69 "always skip if same or older",
70 )
71
72 namespace setup {
73
load(std::istream & is,const info & i)74 void file_entry::load(std::istream & is, const info & i) {
75
76 USE_ENUM_NAMES(file_copy_mode)
77
78 options = 0;
79
80 if(i.version < INNO_VERSION(1, 3, 0)) {
81 (void)util::load<boost::uint32_t>(is); // uncompressed size of the entry
82 }
83
84 is >> util::encoded_string(source, i.codepage, i.header.lead_bytes);
85 is >> util::encoded_string(destination, i.codepage, i.header.lead_bytes);
86 is >> util::encoded_string(install_font_name, i.codepage, i.header.lead_bytes);
87 if(i.version >= INNO_VERSION(5, 2, 5)) {
88 is >> util::encoded_string(strong_assembly_name, i.codepage, i.header.lead_bytes);
89 } else {
90 strong_assembly_name.clear();
91 }
92
93 load_condition_data(is, i);
94
95 load_version_data(is, i.version);
96
97 location = util::load<boost::uint32_t>(is, i.version.bits());
98 attributes = util::load<boost::uint32_t>(is, i.version.bits());
99 external_size = (i.version >= INNO_VERSION(4, 0, 0)) ? util::load<boost::uint64_t>(is)
100 : util::load<boost::uint32_t>(is);
101
102 if(i.version < INNO_VERSION(3, 0, 5)) {
103 file_copy_mode copyMode = stored_enum<stored_file_copy_mode>(is).get();
104 switch(copyMode) {
105 case cmNormal: options |= PromptIfOlder; break;
106 case cmIfDoesntExist: options |= OnlyIfDoesntExist | PromptIfOlder; break;
107 case cmAlwaysOverwrite: options |= IgnoreVersion | PromptIfOlder; break;
108 case cmAlwaysSkipIfSameOrOlder: break;
109 }
110 }
111
112 if(i.version >= INNO_VERSION(4, 1, 0)) {
113 permission = util::load<boost::int16_t>(is);
114 } else {
115 permission = boost::int16_t(-1);
116 }
117
118 stored_flag_reader<flags> flagreader(is, i.version.bits());
119
120 flagreader.add(ConfirmOverwrite);
121 flagreader.add(NeverUninstall);
122 flagreader.add(RestartReplace);
123 flagreader.add(DeleteAfterInstall);
124 if(i.version.bits() != 16) {
125 flagreader.add(RegisterServer);
126 flagreader.add(RegisterTypeLib);
127 flagreader.add(SharedFile);
128 }
129 if(i.version < INNO_VERSION(2, 0, 0) && !i.version.is_isx()) {
130 flagreader.add(IsReadmeFile);
131 }
132 flagreader.add(CompareTimeStamp);
133 flagreader.add(FontIsNotTrueType);
134 if(i.version >= INNO_VERSION(1, 2, 5)) {
135 flagreader.add(SkipIfSourceDoesntExist);
136 }
137 if(i.version >= INNO_VERSION(1, 2, 6)) {
138 flagreader.add(OverwriteReadOnly);
139 }
140 if(i.version >= INNO_VERSION(1, 3, 21)) {
141 flagreader.add(OverwriteSameVersion);
142 flagreader.add(CustomDestName);
143 }
144 if(i.version >= INNO_VERSION(1, 3, 25)) {
145 flagreader.add(OnlyIfDestFileExists);
146 }
147 if(i.version >= INNO_VERSION(2, 0, 5)) {
148 flagreader.add(NoRegError);
149 }
150 if(i.version >= INNO_VERSION(3, 0, 1)) {
151 flagreader.add(UninsRestartDelete);
152 }
153 if(i.version >= INNO_VERSION(3, 0, 5)) {
154 flagreader.add(OnlyIfDoesntExist);
155 flagreader.add(IgnoreVersion);
156 flagreader.add(PromptIfOlder);
157 }
158 if(i.version >= INNO_VERSION(4, 0, 0) ||
159 (i.version.is_isx() && i.version >= INNO_VERSION_EXT(3, 0, 6, 1))) {
160 flagreader.add(DontCopy);
161 }
162 if(i.version >= INNO_VERSION(4, 0, 5)) {
163 flagreader.add(UninsRemoveReadOnly);
164 }
165 if(i.version >= INNO_VERSION(4, 1, 8)) {
166 flagreader.add(RecurseSubDirsExternal);
167 }
168 if(i.version >= INNO_VERSION(4, 2, 1)) {
169 flagreader.add(ReplaceSameVersionIfContentsDiffer);
170 }
171 if(i.version >= INNO_VERSION(4, 2, 5)) {
172 flagreader.add(DontVerifyChecksum);
173 }
174 if(i.version >= INNO_VERSION(5, 0, 3)) {
175 flagreader.add(UninsNoSharedFilePrompt);
176 }
177 if(i.version >= INNO_VERSION(5, 1, 0)) {
178 flagreader.add(CreateAllSubDirs);
179 }
180 if(i.version >= INNO_VERSION(5, 1, 2)) {
181 flagreader.add(Bits32);
182 flagreader.add(Bits64);
183 }
184 if(i.version >= INNO_VERSION(5, 2, 0)) {
185 flagreader.add(ExternalSizePreset);
186 flagreader.add(SetNtfsCompression);
187 flagreader.add(UnsetNtfsCompression);
188 }
189 if(i.version >= INNO_VERSION(5, 2, 5)) {
190 flagreader.add(GacInstall);
191 }
192
193 options |= flagreader;
194
195 if(i.version.bits() == 16 || i.version >= INNO_VERSION(5, 0, 0)) {
196 type = stored_enum<stored_file_type_0>(is).get();
197 } else {
198 type = stored_enum<stored_file_type_1>(is).get();
199 }
200
201 additional_locations.clear();
202 checksum.type = crypto::None;
203 size = 0;
204
205 }
206
207 } // namespace setup
208
209 NAMES(setup::file_entry::flags, "File Option",
210 "confirm overwrite",
211 "never uninstall",
212 "restart replace",
213 "delete after install",
214 "register server",
215 "register type lib",
216 "shared file",
217 "compare timestamp",
218 "font isn't truetype",
219 "skip if source doesn't exist",
220 "overwrite readonly",
221 "overwrite same version",
222 "custom destination name",
223 "only if destination exists",
224 "no reg error",
225 "uninstall restart delete",
226 "only if doesn't exist",
227 "ignore version",
228 "prompt if older",
229 "don't copy",
230 "uninstall remove readonly",
231 "recurse subdirectories external",
232 "replace same version if contents differ",
233 "don't verify checksum",
234 "uninstall no shared file prompt",
235 "create all sub dirs",
236 "32 bit",
237 "64 bit",
238 "external size preset",
239 "set ntfs compression",
240 "unset ntfs compression",
241 "gac install",
242 "readme",
243 )
244
245 NAMES(setup::file_entry::file_type, "File Entry Type",
246 "user file",
247 "uninstaller exe",
248 "reg server exe",
249 )
250