123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.WinPackager = void 0;
- const bluebird_lst_1 = require("bluebird-lst");
- const builder_util_1 = require("builder-util");
- const builder_util_runtime_1 = require("builder-util-runtime");
- const fs_1 = require("builder-util/out/fs");
- const crypto_1 = require("crypto");
- const promises_1 = require("fs/promises");
- const isCI = require("is-ci");
- const lazy_val_1 = require("lazy-val");
- const path = require("path");
- const codesign_1 = require("./codeSign/codesign");
- const windowsCodeSign_1 = require("./codeSign/windowsCodeSign");
- const core_1 = require("./core");
- const platformPackager_1 = require("./platformPackager");
- const NsisTarget_1 = require("./targets/nsis/NsisTarget");
- const nsisUtil_1 = require("./targets/nsis/nsisUtil");
- const WebInstallerTarget_1 = require("./targets/nsis/WebInstallerTarget");
- const targetFactory_1 = require("./targets/targetFactory");
- const cacheManager_1 = require("./util/cacheManager");
- const flags_1 = require("./util/flags");
- const timer_1 = require("./util/timer");
- const vm_1 = require("./vm/vm");
- const wine_1 = require("./wine");
- class WinPackager extends platformPackager_1.PlatformPackager {
- constructor(info) {
- super(info, core_1.Platform.WINDOWS);
- this.cscInfo = new lazy_val_1.Lazy(() => {
- const platformSpecificBuildOptions = this.platformSpecificBuildOptions;
- if (platformSpecificBuildOptions.certificateSubjectName != null || platformSpecificBuildOptions.certificateSha1 != null) {
- return this.vm.value
- .then(vm => (0, windowsCodeSign_1.getCertificateFromStoreInfo)(platformSpecificBuildOptions, vm))
- .catch((e) => {
- // https://github.com/electron-userland/electron-builder/pull/2397
- if (platformSpecificBuildOptions.sign == null) {
- throw e;
- }
- else {
- builder_util_1.log.debug({ error: e }, "getCertificateFromStoreInfo error");
- return null;
- }
- });
- }
- const certificateFile = platformSpecificBuildOptions.certificateFile;
- if (certificateFile != null) {
- const certificatePassword = this.getCscPassword();
- return Promise.resolve({
- file: certificateFile,
- password: certificatePassword == null ? null : certificatePassword.trim(),
- });
- }
- const cscLink = this.getCscLink("WIN_CSC_LINK");
- if (cscLink == null) {
- return Promise.resolve(null);
- }
- return ((0, codesign_1.importCertificate)(cscLink, this.info.tempDirManager, this.projectDir)
- // before then
- .catch((e) => {
- if (e instanceof builder_util_1.InvalidConfigurationError) {
- throw new builder_util_1.InvalidConfigurationError(`Env WIN_CSC_LINK is not correct, cannot resolve: ${e.message}`);
- }
- else {
- throw e;
- }
- })
- .then(path => {
- return {
- file: path,
- password: this.getCscPassword(),
- };
- }));
- });
- this._iconPath = new lazy_val_1.Lazy(() => this.getOrConvertIcon("ico"));
- this.vm = new lazy_val_1.Lazy(() => (process.platform === "win32" ? Promise.resolve(new vm_1.VmManager()) : (0, vm_1.getWindowsVm)(this.debugLogger)));
- this.computedPublisherName = new lazy_val_1.Lazy(async () => {
- const publisherName = this.platformSpecificBuildOptions.publisherName;
- if (publisherName === null) {
- return null;
- }
- else if (publisherName != null) {
- return (0, builder_util_1.asArray)(publisherName);
- }
- const certInfo = await this.lazyCertInfo.value;
- return certInfo == null ? null : [certInfo.commonName];
- });
- this.lazyCertInfo = new lazy_val_1.Lazy(async () => {
- const cscInfo = await this.cscInfo.value;
- if (cscInfo == null) {
- return null;
- }
- if ("subject" in cscInfo) {
- const bloodyMicrosoftSubjectDn = cscInfo.subject;
- return {
- commonName: (0, builder_util_runtime_1.parseDn)(bloodyMicrosoftSubjectDn).get("CN"),
- bloodyMicrosoftSubjectDn,
- };
- }
- const cscFile = cscInfo.file;
- if (cscFile == null) {
- return null;
- }
- return await (0, windowsCodeSign_1.getCertInfo)(cscFile, cscInfo.password || "");
- });
- }
- get isForceCodeSigningVerification() {
- return this.platformSpecificBuildOptions.verifyUpdateCodeSignature !== false;
- }
- get defaultTarget() {
- return ["nsis"];
- }
- doGetCscPassword() {
- return (0, platformPackager_1.chooseNotNull)((0, platformPackager_1.chooseNotNull)(this.platformSpecificBuildOptions.certificatePassword, process.env.WIN_CSC_KEY_PASSWORD), super.doGetCscPassword());
- }
- createTargets(targets, mapper) {
- let copyElevateHelper;
- const getCopyElevateHelper = () => {
- if (copyElevateHelper == null) {
- copyElevateHelper = new nsisUtil_1.CopyElevateHelper();
- }
- return copyElevateHelper;
- };
- let helper;
- const getHelper = () => {
- if (helper == null) {
- helper = new nsisUtil_1.AppPackageHelper(getCopyElevateHelper());
- }
- return helper;
- };
- for (const name of targets) {
- if (name === core_1.DIR_TARGET) {
- continue;
- }
- if (name === "nsis" || name === "portable") {
- mapper(name, outDir => new NsisTarget_1.NsisTarget(this, outDir, name, getHelper()));
- }
- else if (name === "nsis-web") {
- // package file format differs from nsis target
- mapper(name, outDir => new WebInstallerTarget_1.WebInstallerTarget(this, path.join(outDir, name), name, new nsisUtil_1.AppPackageHelper(getCopyElevateHelper())));
- }
- else {
- const targetClass = (() => {
- switch (name) {
- case "squirrel":
- try {
- return require("electron-builder-squirrel-windows").default;
- }
- catch (e) {
- throw new builder_util_1.InvalidConfigurationError(`Module electron-builder-squirrel-windows must be installed in addition to build Squirrel.Windows: ${e.stack || e}`);
- }
- case "appx":
- return require("./targets/AppxTarget").default;
- case "msi":
- return require("./targets/MsiTarget").default;
- case "msiwrapped":
- return require("./targets/MsiWrappedTarget").default;
- default:
- return null;
- }
- })();
- mapper(name, outDir => (targetClass === null ? (0, targetFactory_1.createCommonTarget)(name, outDir, this) : new targetClass(this, outDir, name)));
- }
- }
- }
- getIconPath() {
- return this._iconPath.value;
- }
- async sign(file, logMessagePrefix) {
- const signOptions = {
- path: file,
- name: this.appInfo.productName,
- site: await this.appInfo.computePackageUrl(),
- options: this.platformSpecificBuildOptions,
- };
- const cscInfo = await this.cscInfo.value;
- if (cscInfo == null) {
- if (this.platformSpecificBuildOptions.sign != null) {
- return (0, windowsCodeSign_1.sign)(signOptions, this);
- }
- else if (this.forceCodeSigning) {
- throw new builder_util_1.InvalidConfigurationError(`App is not signed and "forceCodeSigning" is set to true, please ensure that code signing configuration is correct, please see https://electron.build/code-signing`);
- }
- return false;
- }
- if (logMessagePrefix == null) {
- logMessagePrefix = "signing";
- }
- if ("file" in cscInfo) {
- builder_util_1.log.info({
- file: builder_util_1.log.filePath(file),
- certificateFile: cscInfo.file,
- }, logMessagePrefix);
- }
- else {
- const info = cscInfo;
- builder_util_1.log.info({
- file: builder_util_1.log.filePath(file),
- subject: info.subject,
- thumbprint: info.thumbprint,
- store: info.store,
- user: info.isLocalMachineStore ? "local machine" : "current user",
- }, logMessagePrefix);
- }
- return this.doSign({
- ...signOptions,
- cscInfo,
- options: {
- ...this.platformSpecificBuildOptions,
- },
- });
- }
- async doSign(options) {
- for (let i = 0; i < 3; i++) {
- try {
- await (0, windowsCodeSign_1.sign)(options, this);
- return true;
- }
- catch (e) {
- // https://github.com/electron-userland/electron-builder/issues/1414
- const message = e.message;
- if (message != null && message.includes("Couldn't resolve host name")) {
- builder_util_1.log.warn({ error: message, attempt: i + 1 }, `cannot sign`);
- continue;
- }
- throw e;
- }
- }
- return false;
- }
- async signAndEditResources(file, arch, outDir, internalName, requestedExecutionLevel) {
- const appInfo = this.appInfo;
- const files = [];
- const args = [
- file,
- "--set-version-string",
- "FileDescription",
- appInfo.productName,
- "--set-version-string",
- "ProductName",
- appInfo.productName,
- "--set-version-string",
- "LegalCopyright",
- appInfo.copyright,
- "--set-file-version",
- appInfo.shortVersion || appInfo.buildVersion,
- "--set-product-version",
- appInfo.shortVersionWindows || appInfo.getVersionInWeirdWindowsForm(),
- ];
- if (internalName != null) {
- args.push("--set-version-string", "InternalName", internalName, "--set-version-string", "OriginalFilename", "");
- }
- if (requestedExecutionLevel != null && requestedExecutionLevel !== "asInvoker") {
- args.push("--set-requested-execution-level", requestedExecutionLevel);
- }
- (0, builder_util_1.use)(appInfo.companyName, it => args.push("--set-version-string", "CompanyName", it));
- (0, builder_util_1.use)(this.platformSpecificBuildOptions.legalTrademarks, it => args.push("--set-version-string", "LegalTrademarks", it));
- const iconPath = await this.getIconPath();
- (0, builder_util_1.use)(iconPath, it => {
- files.push(it);
- args.push("--set-icon", it);
- });
- const config = this.config;
- const cscInfoForCacheDigest = !(0, flags_1.isBuildCacheEnabled)() || isCI || config.electronDist != null ? null : await this.cscInfo.value;
- let buildCacheManager = null;
- // resources editing doesn't change executable for the same input and executed quickly - no need to complicate
- if (cscInfoForCacheDigest != null) {
- const cscFile = cscInfoForCacheDigest.file;
- if (cscFile != null) {
- files.push(cscFile);
- }
- const timer = (0, timer_1.time)("executable cache");
- const hash = (0, crypto_1.createHash)("sha512");
- hash.update(config.electronVersion || "no electronVersion");
- hash.update(JSON.stringify(this.platformSpecificBuildOptions));
- hash.update(JSON.stringify(args));
- hash.update(this.platformSpecificBuildOptions.certificateSha1 || "no certificateSha1");
- hash.update(this.platformSpecificBuildOptions.certificateSubjectName || "no subjectName");
- buildCacheManager = new cacheManager_1.BuildCacheManager(outDir, file, arch);
- if (await buildCacheManager.copyIfValid(await (0, cacheManager_1.digest)(hash, files))) {
- timer.end();
- return;
- }
- timer.end();
- }
- const timer = (0, timer_1.time)("wine&sign");
- // rcedit crashed of executed using wine, resourcehacker works
- if (process.platform === "win32" || process.platform === "darwin") {
- await (0, builder_util_1.executeAppBuilder)(["rcedit", "--args", JSON.stringify(args)], undefined /* child-process */, {}, 3 /* retry three times */);
- }
- else if (this.info.framework.name === "electron") {
- const vendorPath = await (0, windowsCodeSign_1.getSignVendorPath)();
- await (0, wine_1.execWine)(path.join(vendorPath, "rcedit-ia32.exe"), path.join(vendorPath, "rcedit-x64.exe"), args);
- }
- await this.sign(file);
- timer.end();
- if (buildCacheManager != null) {
- await buildCacheManager.save();
- }
- }
- shouldSignFile(file) {
- var _a;
- const shouldSignDll = this.platformSpecificBuildOptions.signDlls === true && file.endsWith(".dll");
- const shouldSignExplicit = !!((_a = this.platformSpecificBuildOptions.signExts) === null || _a === void 0 ? void 0 : _a.some(ext => file.endsWith(ext)));
- return shouldSignDll || shouldSignExplicit || file.endsWith(".exe");
- }
- createTransformerForExtraFiles(packContext) {
- if (this.platformSpecificBuildOptions.signAndEditExecutable === false) {
- return null;
- }
- return file => {
- if (this.shouldSignFile(file)) {
- const parentDir = path.dirname(file);
- if (parentDir !== packContext.appOutDir) {
- return new fs_1.CopyFileTransformer(file => this.sign(file));
- }
- }
- return null;
- };
- }
- async signApp(packContext, isAsar) {
- const exeFileName = `${this.appInfo.productFilename}.exe`;
- if (this.platformSpecificBuildOptions.signAndEditExecutable === false) {
- return false;
- }
- await bluebird_lst_1.default.map((0, promises_1.readdir)(packContext.appOutDir), (file) => {
- if (file === exeFileName) {
- return this.signAndEditResources(path.join(packContext.appOutDir, exeFileName), packContext.arch, packContext.outDir, path.basename(exeFileName, ".exe"), this.platformSpecificBuildOptions.requestedExecutionLevel);
- }
- else if (this.shouldSignFile(file)) {
- return this.sign(path.join(packContext.appOutDir, file));
- }
- return null;
- });
- if (!isAsar) {
- return true;
- }
- const filesPromise = (filepath) => {
- const outDir = path.join(packContext.appOutDir, ...filepath);
- return (0, fs_1.walk)(outDir, (file, stat) => stat.isDirectory() || this.shouldSignFile(file));
- };
- const filesToSign = await Promise.all([filesPromise(["resources", "app.asar.unpacked"]), filesPromise(["swiftshader"])]);
- await bluebird_lst_1.default.map(filesToSign.flat(1), file => this.sign(file), { concurrency: 4 });
- return true;
- }
- }
- exports.WinPackager = WinPackager;
- //# sourceMappingURL=winPackager.js.map
|