UNPKG

11.3 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.NsisUpdater = void 0;
7
8function _builderUtilRuntime() {
9 const data = require("builder-util-runtime");
10
11 _builderUtilRuntime = function () {
12 return data;
13 };
14
15 return data;
16}
17
18function _child_process() {
19 const data = require("child_process");
20
21 _child_process = function () {
22 return data;
23 };
24
25 return data;
26}
27
28var path = _interopRequireWildcard(require("path"));
29
30function _BaseUpdater() {
31 const data = require("./BaseUpdater");
32
33 _BaseUpdater = function () {
34 return data;
35 };
36
37 return data;
38}
39
40function _FileWithEmbeddedBlockMapDifferentialDownloader() {
41 const data = require("./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader");
42
43 _FileWithEmbeddedBlockMapDifferentialDownloader = function () {
44 return data;
45 };
46
47 return data;
48}
49
50function _GenericDifferentialDownloader() {
51 const data = require("./differentialDownloader/GenericDifferentialDownloader");
52
53 _GenericDifferentialDownloader = function () {
54 return data;
55 };
56
57 return data;
58}
59
60function _main() {
61 const data = require("./main");
62
63 _main = function () {
64 return data;
65 };
66
67 return data;
68}
69
70function _Provider() {
71 const data = require("./providers/Provider");
72
73 _Provider = function () {
74 return data;
75 };
76
77 return data;
78}
79
80function _fsExtra() {
81 const data = require("fs-extra");
82
83 _fsExtra = function () {
84 return data;
85 };
86
87 return data;
88}
89
90function _windowsExecutableCodeSignatureVerifier() {
91 const data = require("./windowsExecutableCodeSignatureVerifier");
92
93 _windowsExecutableCodeSignatureVerifier = function () {
94 return data;
95 };
96
97 return data;
98}
99
100function _url() {
101 const data = require("url");
102
103 _url = function () {
104 return data;
105 };
106
107 return data;
108}
109
110function _zlib() {
111 const data = require("zlib");
112
113 _zlib = function () {
114 return data;
115 };
116
117 return data;
118}
119
120function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
121
122function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
123
124class NsisUpdater extends _BaseUpdater().BaseUpdater {
125 constructor(options, app) {
126 super(options, app);
127 }
128 /*** @private */
129
130
131 doDownloadUpdate(downloadUpdateOptions) {
132 const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
133 const fileInfo = (0, _Provider().findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "exe");
134 return this.executeDownload({
135 fileExtension: "exe",
136 downloadUpdateOptions,
137 fileInfo,
138 task: async (destinationFile, downloadOptions, packageFile, removeTempDirIfAny) => {
139 if (hasQuotes(destinationFile) || packageFile != null && hasQuotes(packageFile)) {
140 throw (0, _builderUtilRuntime().newError)(`destinationFile or packageFile contains illegal chars`, "ERR_UPDATER_ILLEGAL_FILE_NAME");
141 }
142
143 const packageInfo = fileInfo.packageInfo;
144 const isWebInstaller = packageInfo != null && packageFile != null;
145
146 if (isWebInstaller || (await this.differentialDownloadInstaller(fileInfo, downloadUpdateOptions, destinationFile, provider))) {
147 await this.httpExecutor.download(fileInfo.url, destinationFile, downloadOptions);
148 }
149
150 const signatureVerificationStatus = await this.verifySignature(destinationFile);
151
152 if (signatureVerificationStatus != null) {
153 await removeTempDirIfAny(); // noinspection ThrowInsideFinallyBlockJS
154
155 throw (0, _builderUtilRuntime().newError)(`New version ${downloadUpdateOptions.updateInfoAndProvider.info.version} is not signed by the application owner: ${signatureVerificationStatus}`, "ERR_UPDATER_INVALID_SIGNATURE");
156 }
157
158 if (isWebInstaller) {
159 if (await this.differentialDownloadWebPackage(packageInfo, packageFile, provider)) {
160 try {
161 await this.httpExecutor.download(new (_url().URL)(packageInfo.path), packageFile, {
162 headers: downloadUpdateOptions.requestHeaders,
163 cancellationToken: downloadUpdateOptions.cancellationToken,
164 sha512: packageInfo.sha512
165 });
166 } catch (e) {
167 try {
168 await (0, _fsExtra().unlink)(packageFile);
169 } catch (ignored) {// ignore
170 }
171
172 throw e;
173 }
174 }
175 }
176 }
177 });
178 } // $certificateInfo = (Get-AuthenticodeSignature 'xxx\yyy.exe'
179 // | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains("CN=siemens.com")})
180 // | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }
181
182
183 async verifySignature(tempUpdateFile) {
184 let publisherName;
185
186 try {
187 publisherName = (await this.configOnDisk.value).publisherName;
188
189 if (publisherName == null) {
190 return null;
191 }
192 } catch (e) {
193 if (e.code === "ENOENT") {
194 // no app-update.yml
195 return null;
196 }
197
198 throw e;
199 }
200
201 return await (0, _windowsExecutableCodeSignatureVerifier().verifySignature)(Array.isArray(publisherName) ? publisherName : [publisherName], tempUpdateFile, this._logger);
202 }
203
204 doInstall(options) {
205 const args = ["--updated"];
206
207 if (options.isSilent) {
208 args.push("/S");
209 }
210
211 if (options.isForceRunAfter) {
212 args.push("--force-run");
213 }
214
215 const packagePath = this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.packageFile;
216
217 if (packagePath != null) {
218 // only = form is supported
219 args.push(`--package-file=${packagePath}`);
220 }
221
222 const callUsingElevation = () => {
223 _spawn(path.join(process.resourcesPath, "elevate.exe"), [options.installerPath].concat(args)).catch(e => this.dispatchError(e));
224 };
225
226 if (options.isAdminRightsRequired) {
227 this._logger.info("isAdminRightsRequired is set to true, run installer using elevate.exe");
228
229 callUsingElevation();
230 return true;
231 }
232
233 _spawn(options.installerPath, args).catch(e => {
234 // https://github.com/electron-userland/electron-builder/issues/1129
235 // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors
236 const errorCode = e.code;
237
238 this._logger.info(`Cannot run installer: error code: ${errorCode}, error message: "${e.message}", will be executed again using elevate if EACCES"`);
239
240 if (errorCode === "UNKNOWN" || errorCode === "EACCES") {
241 callUsingElevation();
242 } else {
243 this.dispatchError(e);
244 }
245 });
246
247 return true;
248 }
249
250 async differentialDownloadInstaller(fileInfo, downloadUpdateOptions, installerPath, provider) {
251 try {
252 if (this._testOnlyOptions != null && !this._testOnlyOptions.isUseDifferentialDownload) {
253 return true;
254 }
255
256 const newBlockMapUrl = (0, _main().newUrlFromBase)(`${fileInfo.url.pathname}.blockmap`, fileInfo.url);
257 const oldBlockMapUrl = (0, _main().newUrlFromBase)(`${fileInfo.url.pathname.replace(new RegExp(downloadUpdateOptions.updateInfoAndProvider.info.version, "g"), this.app.version)}.blockmap`, fileInfo.url);
258
259 this._logger.info(`Download block maps (old: "${oldBlockMapUrl.href}", new: ${newBlockMapUrl.href})`);
260
261 const downloadBlockMap = async url => {
262 const data = await this.httpExecutor.downloadToBuffer(url, {
263 headers: downloadUpdateOptions.requestHeaders,
264 cancellationToken: downloadUpdateOptions.cancellationToken
265 });
266
267 if (data == null || data.length === 0) {
268 throw new Error(`Blockmap "${url.href}" is empty`);
269 }
270
271 try {
272 return JSON.parse((0, _zlib().inflateSync)(data).toString());
273 } catch (e) {
274 throw new Error(`Cannot parse blockmap "${url.href}", error: ${e}, raw data: ${data}`);
275 }
276 };
277
278 const blockMapDataList = await Promise.all([downloadBlockMap(oldBlockMapUrl), downloadBlockMap(newBlockMapUrl)]);
279 await new (_GenericDifferentialDownloader().GenericDifferentialDownloader)(fileInfo.info, this.httpExecutor, {
280 newUrl: fileInfo.url,
281 oldFile: path.join(this.downloadedUpdateHelper.cacheDir, _builderUtilRuntime().CURRENT_APP_INSTALLER_FILE_NAME),
282 logger: this._logger,
283 newFile: installerPath,
284 isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
285 requestHeaders: downloadUpdateOptions.requestHeaders
286 }).download(blockMapDataList[0], blockMapDataList[1]);
287 return false;
288 } catch (e) {
289 this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`);
290
291 if (this._testOnlyOptions != null) {
292 // test mode
293 throw e;
294 }
295
296 return true;
297 }
298 }
299
300 async differentialDownloadWebPackage(packageInfo, packagePath, provider) {
301 if (packageInfo.blockMapSize == null) {
302 return true;
303 }
304
305 try {
306 await new (_FileWithEmbeddedBlockMapDifferentialDownloader().FileWithEmbeddedBlockMapDifferentialDownloader)(packageInfo, this.httpExecutor, {
307 newUrl: new (_url().URL)(packageInfo.path),
308 oldFile: path.join(this.downloadedUpdateHelper.cacheDir, _builderUtilRuntime().CURRENT_APP_PACKAGE_FILE_NAME),
309 logger: this._logger,
310 newFile: packagePath,
311 requestHeaders: this.requestHeaders,
312 isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest
313 }).download();
314 } catch (e) {
315 this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`); // during test (developer machine mac or linux) we must throw error
316
317
318 return process.platform === "win32";
319 }
320
321 return false;
322 }
323
324}
325/**
326 * This handles both node 8 and node 10 way of emitting error when spawning a process
327 * - node 8: Throws the error
328 * - node 10: Emit the error(Need to listen with on)
329 */
330
331
332exports.NsisUpdater = NsisUpdater;
333
334async function _spawn(exe, args) {
335 return new Promise((resolve, reject) => {
336 try {
337 const process = (0, _child_process().spawn)(exe, args, {
338 detached: true,
339 stdio: "ignore"
340 });
341 process.on("error", error => {
342 reject(error);
343 });
344 process.unref();
345
346 if (process.pid !== undefined) {
347 resolve(true);
348 }
349 } catch (error) {
350 reject(error);
351 }
352 });
353}
354
355function hasQuotes(name) {
356 return name.includes("'") || name.includes('"') || name.includes('`');
357}
358// __ts-babel@6.0.4
359//# sourceMappingURL=NsisUpdater.js.map
\No newline at end of file