metadidomi-builder 1.6.2812251812 → 1.7.3101261533
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -774
- package/package.json +4 -6
- package/build_tools/backup-manager.js +0 -3
- package/build_tools/build_apk.js +0 -3
- package/build_tools/builder.js +0 -2
- package/build_tools/certs/cert-1a25871e.key +0 -1
- package/build_tools/certs/cert-1a25871e.pfx +0 -0
- package/build_tools/check-apk.js +0 -211
- package/build_tools/commands-help.js +0 -465
- package/build_tools/create-example-app.js +0 -73
- package/build_tools/decrypt_pfx_password.js +0 -1
- package/build_tools/diagnose-apk.js +0 -61
- package/build_tools/generate-icons.js +0 -3
- package/build_tools/generate-resources.js +0 -3
- package/build_tools/manage-dependencies.js +0 -3
- package/build_tools/process-dependencies.js +0 -203
- package/build_tools/prune_modules.js +0 -147
- package/build_tools/resolve-transitive-deps.js +0 -3
- package/build_tools/restore-resources.js +0 -3
- package/build_tools/setup-androidx.js +0 -131
- package/build_tools/signing.js +0 -20
- package/build_tools/templates/bootstrap.template.js +0 -105
- package/build_tools/templates/default.ico +0 -1
- package/build_tools/templates/nsis_template.nsi +0 -380
- package/build_tools/templates/security_addons.js +0 -60
- package/build_tools/templates/sfx_config.txt.tpl +0 -5
- package/build_tools/test_sign_with_vendor.js +0 -35
- package/build_tools/upx_advanced.js +0 -68
- package/build_tools/verify-apk-dependencies.js +0 -261
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// (to be obfuscated and used as bootstrap.obf.js at runtime)
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const crypto = require('crypto');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const { spawnSync } = require('child_process');
|
|
7
|
-
|
|
8
|
-
(function(){
|
|
9
|
-
try {
|
|
10
|
-
const KEY = process.env.KEY || ''; // runtime key — ideally obtained via server
|
|
11
|
-
if (!KEY) {
|
|
12
|
-
console.error('KEY missing at runtime. Exiting.');
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Anti-debug basic checks
|
|
17
|
-
const execArgs = process.execArgv.join(' ');
|
|
18
|
-
if (execArgs.includes('--inspect') || execArgs.includes('--inspect-brk')) {
|
|
19
|
-
console.error('Debugger detected. Exiting.');
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
|
-
const envFlags = process.env.ELECTRON_ENABLE_LOGGING || process.env.ELECTRON_ENABLE_STACK_DUMPING;
|
|
23
|
-
if (envFlags) { console.error('Unsafe env flags detected. Exiting.'); process.exit(1); }
|
|
24
|
-
|
|
25
|
-
const base = process.resourcesPath || __dirname;
|
|
26
|
-
const resPath = path.join(base, 'resources', 'app', 'resources.bin');
|
|
27
|
-
const hmacPath = path.join(base, 'resources', 'app', 'resources.bin.hmac');
|
|
28
|
-
|
|
29
|
-
if (!fs.existsSync(resPath) || !fs.existsSync(hmacPath)) {
|
|
30
|
-
console.error('resources or hmac not found. Exiting.');
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
const payload = fs.readFileSync(resPath);
|
|
34
|
-
const hmacStored = fs.readFileSync(hmacPath);
|
|
35
|
-
|
|
36
|
-
// Verify HMAC (same derivation as build)
|
|
37
|
-
const hm = crypto.createHmac('sha256', crypto.createHash('sha256').update(KEY).digest());
|
|
38
|
-
hm.update(payload);
|
|
39
|
-
const computed = hm.digest();
|
|
40
|
-
|
|
41
|
-
if (!crypto.timingSafeEqual(computed, hmacStored)) {
|
|
42
|
-
console.error('HMAC verification failed - possible tampering. Exiting.');
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// parse watermark header (optional extract)
|
|
47
|
-
if (payload.slice(0,4).toString('ascii') === 'WMKT') {
|
|
48
|
-
const len = payload.readUInt32BE(4);
|
|
49
|
-
const jsonBuf = payload.slice(8, 8 + len);
|
|
50
|
-
try {
|
|
51
|
-
const meta = JSON.parse(jsonBuf.toString('utf8'));
|
|
52
|
-
// you can report meta to analytics server or use it in runtime policy
|
|
53
|
-
} catch(e) {}
|
|
54
|
-
// actual encrypted content starts after 8+len
|
|
55
|
-
const encrypted = payload.slice(8 + len);
|
|
56
|
-
// proceed to decrypt `encrypted` (AES-256-CBC) as in current bootstrap logic
|
|
57
|
-
const iv = encrypted.slice(0,16);
|
|
58
|
-
const derived = crypto.createHash('sha256').update(KEY).digest();
|
|
59
|
-
const decipher = crypto.createDecipheriv('aes-256-cbc', derived, iv);
|
|
60
|
-
const dec = Buffer.concat([decipher.update(encrypted.slice(16)), decipher.final()]);
|
|
61
|
-
|
|
62
|
-
// write dec to tmp app.asar and then extract/launch as before
|
|
63
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'monapp-'));
|
|
64
|
-
const asarPath = path.join(tmp, 'app.asar');
|
|
65
|
-
fs.writeFileSync(asarPath, dec);
|
|
66
|
-
|
|
67
|
-
// Load app from the temp directory directly
|
|
68
|
-
require(asarPath);
|
|
69
|
-
// Ne pas quitter - laisser l'application s'exécuter
|
|
70
|
-
} else {
|
|
71
|
-
console.error('Watermark header missing. Exiting.');
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
} catch (err) {
|
|
75
|
-
console.error('Bootstrap verify error', err);
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
})();
|
|
79
|
-
|
|
80
|
-
// --- Déchiffrement à la volée des fichiers protégés (JS/HTML/CSS) ---
|
|
81
|
-
function readDecryptedFile(filePath, keyStr) {
|
|
82
|
-
const buf = fs.readFileSync(filePath);
|
|
83
|
-
if (buf.slice(0,4).toString('ascii') !== 'ENC1') {
|
|
84
|
-
// Pas chiffré
|
|
85
|
-
return buf.toString('utf8');
|
|
86
|
-
}
|
|
87
|
-
const iv = buf.slice(4, 20);
|
|
88
|
-
const encrypted = buf.slice(20);
|
|
89
|
-
const key = crypto.createHash('sha256').update(keyStr || 'dev-key').digest();
|
|
90
|
-
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
|
|
91
|
-
const dec = Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
|
92
|
-
return dec.toString('utf8');
|
|
93
|
-
}
|
|
94
|
-
// --- Fin déchiffrement utilitaire ---
|
|
95
|
-
|
|
96
|
-
// --- Loader dynamique pour modules JS chiffrés ---
|
|
97
|
-
const Module = require('module');
|
|
98
|
-
const originalLoader = Module._extensions['.js'];
|
|
99
|
-
Module._extensions['.js'] = function(module, filename) {
|
|
100
|
-
// Utilise le déchiffrement si besoin
|
|
101
|
-
const key = process.env.KEY || '';
|
|
102
|
-
const content = readDecryptedFile(filename, key);
|
|
103
|
-
module._compile(content, filename);
|
|
104
|
-
};
|
|
105
|
-
// --- Fin loader dynamique ---
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAMMOAADDDgAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
|
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
!include "MUI2.nsh"
|
|
2
|
-
!include "nsDialogs.nsh"
|
|
3
|
-
!include "LogicLib.nsh"
|
|
4
|
-
!include "WinVer.nsh"
|
|
5
|
-
!include "x64.nsh"
|
|
6
|
-
!include "FileFunc.nsh"
|
|
7
|
-
|
|
8
|
-
; Déclaration des variables
|
|
9
|
-
Var Dialog
|
|
10
|
-
Var Label
|
|
11
|
-
Var SupportLink
|
|
12
|
-
Var CreateStartMenuShortcut
|
|
13
|
-
Var CreateDesktopShortcut
|
|
14
|
-
Var RunRadioNone
|
|
15
|
-
Var RunRadioAfter
|
|
16
|
-
Var RunRadioStartup
|
|
17
|
-
Var RunChoice
|
|
18
|
-
Var AppType ; "node" ou "python"
|
|
19
|
-
Var PythonExePath ; Chemin vers Python Embeddable
|
|
20
|
-
Var LauncherScript ; Chemin du script launcher Python
|
|
21
|
-
|
|
22
|
-
Unicode true
|
|
23
|
-
|
|
24
|
-
; Définitions des constantes (à remplacer par vos valeurs réelles)
|
|
25
|
-
!define PRODUCT_NAME "VotreApplication"
|
|
26
|
-
!define VERSION "1.0.0"
|
|
27
|
-
!define COMPANY_NAME "VotreSociété"
|
|
28
|
-
!define APP_DESCRIPTION "Description de votre application"
|
|
29
|
-
!define COPYRIGHT "Copyright © 2024"
|
|
30
|
-
!define HELP_LINK "https://example.com/help"
|
|
31
|
-
!define ABOUT_URL "https://example.com"
|
|
32
|
-
!define UPDATE_URL "https://example.com/update"
|
|
33
|
-
!define PAYLOAD_DIR ".\dist"
|
|
34
|
-
!define APP_ICON ".\assets\icon.ico" ; Chemin vers votre icône personnalisée (peut être vide)
|
|
35
|
-
!define APP_TYPE "node" ; "node" ou "python" - À définir selon le type d'application
|
|
36
|
-
!define PYTHON_EMBED_DIR ".\python_embeddable" ; Dossier Python Embeddable (pour projets Python)
|
|
37
|
-
|
|
38
|
-
; Définitions dérivées
|
|
39
|
-
!define PRODUCT_PUBLISHER "${COMPANY_NAME}"
|
|
40
|
-
!define INSTALL_DIR "$PROGRAMFILES64\${PRODUCT_NAME}"
|
|
41
|
-
!define APP_DISPLAY_NAME "${PRODUCT_NAME}"
|
|
42
|
-
!define UNINSTALL_DISPLAY_NAME "${PRODUCT_NAME}"
|
|
43
|
-
!define PYTHON_INSTALL_DIR "${INSTALL_DIR}\python_embeddable"
|
|
44
|
-
!define LAUNCHER_SCRIPT_NAME "${PRODUCT_NAME}_launcher.py"
|
|
45
|
-
|
|
46
|
-
; Requis pour les permissions administrateur
|
|
47
|
-
RequestExecutionLevel admin
|
|
48
|
-
|
|
49
|
-
; Configuration de l'interface MUI
|
|
50
|
-
; --- ICÔNES PERSONNALISÉES ---
|
|
51
|
-
!ifdef APP_ICON
|
|
52
|
-
!if "${APP_ICON}" != ""
|
|
53
|
-
!define MUI_ICON "${APP_ICON}" ; Icône de l'installateur
|
|
54
|
-
!define MUI_UNICON "${APP_ICON}" ; Icône du désinstallateur
|
|
55
|
-
!define MUI_WELCOMEFINISHPAGE_BITMAP "${APP_ICON}"
|
|
56
|
-
!endif
|
|
57
|
-
!endif
|
|
58
|
-
|
|
59
|
-
; Configuration de l'apparence
|
|
60
|
-
XPStyle on
|
|
61
|
-
BrandingText "${APP_DISPLAY_NAME} ${VERSION}"
|
|
62
|
-
!define MUI_COMPONENTSPAGE_NODESC
|
|
63
|
-
!define MUI_BRANDINGTEXT "${APP_DISPLAY_NAME} ${VERSION}"
|
|
64
|
-
|
|
65
|
-
; Pages MUI2 (réduites)
|
|
66
|
-
!insertmacro MUI_PAGE_WELCOME
|
|
67
|
-
!insertmacro MUI_PAGE_DIRECTORY
|
|
68
|
-
Page custom CustomOptionsPage CustomOptionsLeave
|
|
69
|
-
!insertmacro MUI_PAGE_INSTFILES
|
|
70
|
-
!insertmacro MUI_PAGE_FINISH
|
|
71
|
-
|
|
72
|
-
; Page de fin (simple) — lancement optionnel de l'application après installation
|
|
73
|
-
!define MUI_FINISHPAGE_RUN "$INSTDIR\${PRODUCT_NAME}.exe"
|
|
74
|
-
!define MUI_FINISHPAGE_RUN_TEXT "Lancer ${APP_DISPLAY_NAME} après l'installation"
|
|
75
|
-
!insertmacro MUI_PAGE_FINISH
|
|
76
|
-
|
|
77
|
-
; Pages de désinstallation
|
|
78
|
-
!insertmacro MUI_UNPAGE_CONFIRM
|
|
79
|
-
!insertmacro MUI_UNPAGE_INSTFILES
|
|
80
|
-
|
|
81
|
-
; Langues
|
|
82
|
-
!insertmacro MUI_LANGUAGE "French"
|
|
83
|
-
|
|
84
|
-
; Configuration générale
|
|
85
|
-
Name "${APP_DISPLAY_NAME}"
|
|
86
|
-
OutFile "${OUTPUT_SETUP_EXE}"
|
|
87
|
-
InstallDir "${INSTALL_DIR}"
|
|
88
|
-
ShowInstDetails show
|
|
89
|
-
ShowUnInstDetails show
|
|
90
|
-
|
|
91
|
-
; Informations de version
|
|
92
|
-
VIProductVersion "${VERSION}.0"
|
|
93
|
-
VIAddVersionKey "ProductName" "${APP_DISPLAY_NAME}"
|
|
94
|
-
VIAddVersionKey "CompanyName" "${COMPANY_NAME}"
|
|
95
|
-
VIAddVersionKey "FileVersion" "${VERSION}.0"
|
|
96
|
-
VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
|
|
97
|
-
VIAddVersionKey "FileDescription" "${APP_DESCRIPTION}"
|
|
98
|
-
VIAddVersionKey "Comments" "${APP_DESCRIPTION}"
|
|
99
|
-
VIAddVersionKey "ProductVersion" "${VERSION}"
|
|
100
|
-
|
|
101
|
-
; Section principale
|
|
102
|
-
Section "Application principale" SEC_MAIN
|
|
103
|
-
SectionIn RO
|
|
104
|
-
SetOutPath "$INSTDIR"
|
|
105
|
-
SetOverwrite on
|
|
106
|
-
|
|
107
|
-
; Vérifier que le répertoire source existe
|
|
108
|
-
IfFileExists "${PAYLOAD_DIR}\*.*" +3
|
|
109
|
-
MessageBox MB_ICONSTOP "Erreur: Les fichiers source sont introuvables dans ${PAYLOAD_DIR}"
|
|
110
|
-
Abort
|
|
111
|
-
|
|
112
|
-
; Copier tous les fichiers
|
|
113
|
-
File /r "${PAYLOAD_DIR}\*.*"
|
|
114
|
-
|
|
115
|
-
; Si c'est un projet Python, copier Python Embeddable (optionnel)
|
|
116
|
-
StrCmp "${APP_TYPE}" "python" 0 skipPythonEmbed
|
|
117
|
-
; Le builder gère l'inclusion de Python Embeddable. Si aucun
|
|
118
|
-
; dossier "python_embeddable" n'est présent, cette étape est ignorée.
|
|
119
|
-
; Pour éviter les erreurs NSIS quand le dossier est absent, la copie
|
|
120
|
-
; est effectuée par le builder et non par le script NSIS.
|
|
121
|
-
skipPythonEmbed:
|
|
122
|
-
|
|
123
|
-
; Créer le désinstallateur
|
|
124
|
-
WriteUninstaller "$INSTDIR\uninstall.exe"
|
|
125
|
-
|
|
126
|
-
; Écrire les clés de désinstallation
|
|
127
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${UNINSTALL_DISPLAY_NAME}"
|
|
128
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" "$INSTDIR\uninstall.exe"
|
|
129
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayIcon" "$INSTDIR\${PRODUCT_NAME}.exe"
|
|
130
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Publisher" "${COMPANY_NAME}"
|
|
131
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayVersion" "${VERSION}"
|
|
132
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Version" "${VERSION}"
|
|
133
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "URLInfoAbout" "${ABOUT_URL}"
|
|
134
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "HelpLink" "${HELP_LINK}"
|
|
135
|
-
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoModify" 1
|
|
136
|
-
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoRepair" 1
|
|
137
|
-
|
|
138
|
-
; Calculer la taille de l'installation
|
|
139
|
-
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
|
|
140
|
-
IntFmt $0 "0x%08X" $0
|
|
141
|
-
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "EstimatedSize" "$0"
|
|
142
|
-
|
|
143
|
-
; Pour les projets Python, enregistrer le type d'app
|
|
144
|
-
StrCmp "${APP_TYPE}" "python" 0 skipPythonReg
|
|
145
|
-
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "AppType" "python"
|
|
146
|
-
skipPythonReg:
|
|
147
|
-
SectionEnd
|
|
148
|
-
|
|
149
|
-
; Section pour les raccourcis
|
|
150
|
-
Section "Raccourcis" SEC_SHORTCUTS
|
|
151
|
-
; Raccourci dans le menu Démarrer (si demandé)
|
|
152
|
-
${If} $CreateStartMenuShortcut == 1
|
|
153
|
-
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
|
154
|
-
|
|
155
|
-
; Pour les applications Python, créer un raccourci qui appelle le launcher Python
|
|
156
|
-
StrCmp "${APP_TYPE}" "python" 0 nodeShortcut
|
|
157
|
-
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${APP_DISPLAY_NAME}.lnk" \
|
|
158
|
-
"$INSTDIR\python_embeddable\python.exe" \
|
|
159
|
-
'"$INSTDIR\${LAUNCHER_SCRIPT_NAME}"' \
|
|
160
|
-
"$INSTDIR\${PRODUCT_NAME}.exe" 0
|
|
161
|
-
Goto doneShortcut
|
|
162
|
-
nodeShortcut:
|
|
163
|
-
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${APP_DISPLAY_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe"
|
|
164
|
-
doneShortcut:
|
|
165
|
-
|
|
166
|
-
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Désinstaller ${APP_DISPLAY_NAME}.lnk" "$INSTDIR\uninstall.exe"
|
|
167
|
-
${EndIf}
|
|
168
|
-
|
|
169
|
-
; Raccourci Bureau (optionnel)
|
|
170
|
-
${If} $CreateDesktopShortcut == 1
|
|
171
|
-
; Pour les applications Python, créer un raccourci qui appelle le launcher Python
|
|
172
|
-
StrCmp "${APP_TYPE}" "python" 0 nodeDesktopShortcut
|
|
173
|
-
CreateShortCut "$DESKTOP\${APP_DISPLAY_NAME}.lnk" \
|
|
174
|
-
"$INSTDIR\python_embeddable\python.exe" \
|
|
175
|
-
'"$INSTDIR\${LAUNCHER_SCRIPT_NAME}"' \
|
|
176
|
-
"$INSTDIR\${PRODUCT_NAME}.exe" 0
|
|
177
|
-
Goto doneDesktopShortcut
|
|
178
|
-
nodeDesktopShortcut:
|
|
179
|
-
CreateShortCut "$DESKTOP\${APP_DISPLAY_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe"
|
|
180
|
-
doneDesktopShortcut:
|
|
181
|
-
${EndIf}
|
|
182
|
-
|
|
183
|
-
; Configuration du démarrage automatique si choisi via l'option de la page
|
|
184
|
-
${If} $RunChoice == 2
|
|
185
|
-
StrCmp "${APP_TYPE}" "python" 0 nodeAutorun
|
|
186
|
-
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "${PRODUCT_NAME}" \
|
|
187
|
-
"$INSTDIR\python_embeddable\python.exe $INSTDIR\${LAUNCHER_SCRIPT_NAME}"
|
|
188
|
-
Goto doneAutorun
|
|
189
|
-
nodeAutorun:
|
|
190
|
-
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "${PRODUCT_NAME}" "$INSTDIR\${PRODUCT_NAME}.exe"
|
|
191
|
-
doneAutorun:
|
|
192
|
-
${EndIf}
|
|
193
|
-
SectionEnd
|
|
194
|
-
|
|
195
|
-
; Page d'options personnalisée
|
|
196
|
-
Function CustomOptionsPage
|
|
197
|
-
!insertmacro MUI_HEADER_TEXT "Options d'installation" "Personnalisez votre installation"
|
|
198
|
-
|
|
199
|
-
nsDialogs::Create 1018
|
|
200
|
-
Pop $Dialog
|
|
201
|
-
|
|
202
|
-
${NSD_CreateLabel} 0 0 100% 20u "Choisissez les options d'installation :"
|
|
203
|
-
Pop $Label
|
|
204
|
-
|
|
205
|
-
; Option menu Démarrer
|
|
206
|
-
${NSD_CreateCheckbox} 0 30 100% 20u "Créer un raccourci dans le menu Démarrer"
|
|
207
|
-
Pop $CreateStartMenuShortcut
|
|
208
|
-
${NSD_SetState} $CreateStartMenuShortcut ${BST_CHECKED}
|
|
209
|
-
${NSD_OnClick} $CreateStartMenuShortcut EnableShortcutSection
|
|
210
|
-
|
|
211
|
-
; Option icône sur le bureau (optionnelle)
|
|
212
|
-
${NSD_CreateCheckbox} 0 60 100% 20u "Créer une icône sur le bureau"
|
|
213
|
-
Pop $CreateDesktopShortcut
|
|
214
|
-
${NSD_SetState} $CreateDesktopShortcut ${BST_UNCHECKED}
|
|
215
|
-
|
|
216
|
-
; Choix exclusif : comportement de lancement
|
|
217
|
-
${NSD_CreateLabel} 0 95 100% 20u "Après l'installation :"
|
|
218
|
-
Pop $Label
|
|
219
|
-
|
|
220
|
-
${NSD_CreateRadioButton} 0 120 100% 18u "Ne pas lancer l'application"
|
|
221
|
-
Pop $RunRadioNone
|
|
222
|
-
${NSD_CreateRadioButton} 0 140 100% 18u "Proposer de lancer l'application maintenant (optionnel)"
|
|
223
|
-
Pop $RunRadioAfter
|
|
224
|
-
${NSD_CreateRadioButton} 0 160 100% 18u "Ajouter au démarrage automatique (lancement au démarrage de Windows)"
|
|
225
|
-
Pop $RunRadioStartup
|
|
226
|
-
${NSD_SetState} $RunRadioNone ${BST_CHECKED}
|
|
227
|
-
|
|
228
|
-
; Bouton de soutien du projet
|
|
229
|
-
${NSD_CreateLink} 0 190 100% 18u "❤ Soutenir ETS METADIDOMI"
|
|
230
|
-
Pop $SupportLink
|
|
231
|
-
${NSD_OnClick} $SupportLink OpenSupportLink
|
|
232
|
-
|
|
233
|
-
nsDialogs::Show
|
|
234
|
-
FunctionEnd
|
|
235
|
-
|
|
236
|
-
Function OpenSupportLink
|
|
237
|
-
ExecShell "open" "https://pay.lygosapp.com/$etsmeta"
|
|
238
|
-
FunctionEnd
|
|
239
|
-
|
|
240
|
-
Function EnableShortcutSection
|
|
241
|
-
${NSD_GetState} $CreateStartMenuShortcut $0
|
|
242
|
-
${If} $0 == ${BST_CHECKED}
|
|
243
|
-
!insertmacro SelectSection ${SEC_SHORTCUTS}
|
|
244
|
-
${Else}
|
|
245
|
-
!insertmacro UnselectSection ${SEC_SHORTCUTS}
|
|
246
|
-
${EndIf}
|
|
247
|
-
FunctionEnd
|
|
248
|
-
|
|
249
|
-
Function CustomOptionsLeave
|
|
250
|
-
${NSD_GetState} $CreateStartMenuShortcut $0
|
|
251
|
-
StrCpy $CreateStartMenuShortcut $0
|
|
252
|
-
${NSD_GetState} $CreateDesktopShortcut $0
|
|
253
|
-
StrCpy $CreateDesktopShortcut $0
|
|
254
|
-
; Déterminer le choix de lancement
|
|
255
|
-
${NSD_GetState} $RunRadioAfter $0
|
|
256
|
-
StrCmp $0 ${BST_CHECKED} 0 +3
|
|
257
|
-
StrCpy $RunChoice 1
|
|
258
|
-
Goto doneRunChoice
|
|
259
|
-
${NSD_GetState} $RunRadioStartup $0
|
|
260
|
-
StrCmp $0 ${BST_CHECKED} 0 +3
|
|
261
|
-
StrCpy $RunChoice 2
|
|
262
|
-
Goto doneRunChoice
|
|
263
|
-
StrCpy $RunChoice 0
|
|
264
|
-
doneRunChoice:
|
|
265
|
-
FunctionEnd
|
|
266
|
-
|
|
267
|
-
; (Remarque) Le raccourci bureau est créé automatiquement dans la section des raccourcis (SEC_SHORTCUTS).
|
|
268
|
-
|
|
269
|
-
; Section de désinstallation
|
|
270
|
-
Section "Uninstall"
|
|
271
|
-
; Supprimer les raccourcis
|
|
272
|
-
Delete "$DESKTOP\${APP_DISPLAY_NAME}.lnk"
|
|
273
|
-
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${APP_DISPLAY_NAME}.lnk"
|
|
274
|
-
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Désinstaller ${APP_DISPLAY_NAME}.lnk"
|
|
275
|
-
RMDir "$SMPROGRAMS\${PRODUCT_NAME}"
|
|
276
|
-
|
|
277
|
-
; Supprimer le démarrage automatique
|
|
278
|
-
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "${PRODUCT_NAME}"
|
|
279
|
-
|
|
280
|
-
; Supprimer les fichiers installés
|
|
281
|
-
RMDir /r "$INSTDIR"
|
|
282
|
-
|
|
283
|
-
; Supprimer les données de l'application (optionnel)
|
|
284
|
-
; RMDir /r "$LOCALAPPDATA\${PRODUCT_NAME}"
|
|
285
|
-
|
|
286
|
-
; Supprimer les clés de registre
|
|
287
|
-
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
|
288
|
-
SectionEnd
|
|
289
|
-
|
|
290
|
-
; Utility: Create a Python launcher script that handles execution
|
|
291
|
-
Function CreatePythonLauncher
|
|
292
|
-
StrCmp "${APP_TYPE}" "python" 0 skipLauncherCreation
|
|
293
|
-
|
|
294
|
-
; Créer un script launcher.py simple qui charge et exécute l'app
|
|
295
|
-
FileOpen $0 "$INSTDIR\${LAUNCHER_SCRIPT_NAME}" w
|
|
296
|
-
FileWrite $0 "#!/usr/bin/env python3$\n"
|
|
297
|
-
FileWrite $0 "# Auto-generated launcher$\n"
|
|
298
|
-
FileWrite $0 "import sys$\n"
|
|
299
|
-
FileWrite $0 "import os$\n"
|
|
300
|
-
FileWrite $0 "$\n"
|
|
301
|
-
FileWrite $0 "# Ajouter le répertoire d'installation au chemin Python$\n"
|
|
302
|
-
FileWrite $0 "app_dir = os.path.dirname(os.path.abspath(__file__))$\n"
|
|
303
|
-
FileWrite $0 "sys.path.insert(0, app_dir)$\n"
|
|
304
|
-
FileWrite $0 "$\n"
|
|
305
|
-
FileWrite $0 "# Importer et lancer l'application$\n"
|
|
306
|
-
FileWrite $0 "try:$\n"
|
|
307
|
-
FileWrite $0 " from ${PRODUCT_NAME}_launcher import main$\n"
|
|
308
|
-
FileWrite $0 " main()$\n"
|
|
309
|
-
FileWrite $0 "except Exception as e:$\n"
|
|
310
|
-
FileWrite $0 " print(f'Erreur lors du lancement: {e}')$\n"
|
|
311
|
-
FileWrite $0 " sys.exit(1)$\n"
|
|
312
|
-
FileClose $0
|
|
313
|
-
|
|
314
|
-
skipLauncherCreation:
|
|
315
|
-
FunctionEnd
|
|
316
|
-
|
|
317
|
-
; Fonctions callback
|
|
318
|
-
Function .onInit
|
|
319
|
-
; Vérifier si une instance est déjà en cours d'exécution
|
|
320
|
-
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${PRODUCT_NAME}_Installer") i .r1 ?e'
|
|
321
|
-
Pop $R0
|
|
322
|
-
StrCmp $R0 0 +3
|
|
323
|
-
MessageBox MB_OK|MB_ICONEXCLAMATION "L'installateur est déjà en cours d'exécution."
|
|
324
|
-
Abort
|
|
325
|
-
|
|
326
|
-
; Vérifier si l'application est déjà installée
|
|
327
|
-
ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString"
|
|
328
|
-
StrCmp $R0 "" done
|
|
329
|
-
|
|
330
|
-
MessageBox MB_YESNO|MB_ICONQUESTION \
|
|
331
|
-
"${APP_DISPLAY_NAME} est déjà installé. $\n$\nVoulez-vous le désinstaller ?" \
|
|
332
|
-
IDYES uninst IDNO done
|
|
333
|
-
|
|
334
|
-
uninst:
|
|
335
|
-
ClearErrors
|
|
336
|
-
ExecWait '$R0 _?=$INSTDIR'
|
|
337
|
-
|
|
338
|
-
; Vérifier si la désinstallation a réussi
|
|
339
|
-
ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString"
|
|
340
|
-
StrCmp $R0 "" done
|
|
341
|
-
MessageBox MB_OK|MB_ICONSTOP "La désinstallation a échoué. Veuillez réessayer."
|
|
342
|
-
Abort
|
|
343
|
-
|
|
344
|
-
done:
|
|
345
|
-
|
|
346
|
-
; Initialiser les variables
|
|
347
|
-
StrCpy $CreateStartMenuShortcut 1
|
|
348
|
-
StrCpy $CreateDesktopShortcut 0
|
|
349
|
-
StrCpy $RunChoice 0
|
|
350
|
-
StrCpy $AppType "${APP_TYPE}"
|
|
351
|
-
FunctionEnd
|
|
352
|
-
|
|
353
|
-
Function .onInstSuccess
|
|
354
|
-
; Lancer l'application après installation si l'utilisateur a choisi cette option
|
|
355
|
-
StrCmp $RunChoice 1 0 doneOnInstSuccess
|
|
356
|
-
|
|
357
|
-
StrCmp "${APP_TYPE}" "python" 0 nodeLaunchPy
|
|
358
|
-
MessageBox MB_YESNO|MB_ICONQUESTION "L'installation s'est terminée avec succès. $\n$\nVoulez-vous lancer ${APP_DISPLAY_NAME} maintenant ?" \
|
|
359
|
-
IDYES launchAppPy IDNO doneOnInstSuccess
|
|
360
|
-
launchAppPy:
|
|
361
|
-
Exec "$INSTDIR\python_embeddable\python.exe $INSTDIR\${LAUNCHER_SCRIPT_NAME}"
|
|
362
|
-
Goto doneOnInstSuccess
|
|
363
|
-
nodeLaunchPy:
|
|
364
|
-
MessageBox MB_YESNO|MB_ICONQUESTION "L'installation s'est terminée avec succès. $\n$\nVoulez-vous lancer ${APP_DISPLAY_NAME} maintenant ?" \
|
|
365
|
-
IDYES launchApp IDNO doneOnInstSuccess
|
|
366
|
-
launchApp:
|
|
367
|
-
Exec '"$INSTDIR\${PRODUCT_NAME}.exe"'
|
|
368
|
-
|
|
369
|
-
doneOnInstSuccess:
|
|
370
|
-
; Si RunChoice != 1, ne rien faire (pour RunChoice==2 le démarrage est configuré)
|
|
371
|
-
FunctionEnd
|
|
372
|
-
|
|
373
|
-
; Descriptions des sections
|
|
374
|
-
LangString DESC_SEC_MAIN ${LANG_FRENCH} "Fichiers principaux de l'application."
|
|
375
|
-
LangString DESC_SEC_SHORTCUTS ${LANG_FRENCH} "Crée des raccourcis dans le menu Démarrer."
|
|
376
|
-
|
|
377
|
-
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
|
378
|
-
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MAIN} $(DESC_SEC_MAIN)
|
|
379
|
-
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_SHORTCUTS} $(DESC_SEC_SHORTCUTS)
|
|
380
|
-
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// build_tools/security_addons.js
|
|
2
|
-
// Ce que fait-il: Emballe un petit header WMKT + longueur + JSON watermark devant resources.bin.
|
|
3
|
-
// Calcule HMAC-SHA256 (clé dérivée de KEY) sur tout ça et écrit resources.bin.hmac.
|
|
4
|
-
// Ton bootstrap vérifiera ce HMAC avant d’accepter de déchiffrer.
|
|
5
|
-
// Usage: NODE_ENV=production KEY=your_build_key node build_tools/security_addons.js
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const crypto = require('crypto');
|
|
9
|
-
|
|
10
|
-
const BUILD = process.env.BUILD_DIR || path.resolve(__dirname, '..', '..', 'build');
|
|
11
|
-
const RES_BIN = path.join(BUILD, 'resources.bin');
|
|
12
|
-
const OUT_HMAC = path.join(BUILD, 'resources.bin.hmac');
|
|
13
|
-
|
|
14
|
-
// Vérification des chemins
|
|
15
|
-
console.log('Chemins utilisés:');
|
|
16
|
-
console.log('- BUILD:', BUILD);
|
|
17
|
-
console.log('- RES_BIN:', RES_BIN);
|
|
18
|
-
console.log('- OUT_HMAC:', OUT_HMAC);
|
|
19
|
-
|
|
20
|
-
// Récupérer les infos de l'application depuis les variables d'environnement
|
|
21
|
-
const APP_NAME = process.env.APP_NAME || 'unknown-app';
|
|
22
|
-
const APP_VERSION = process.env.APP_VERSION || '0.0.0';
|
|
23
|
-
const APP_AUTHOR = process.env.APP_AUTHOR || 'unknown-author';
|
|
24
|
-
|
|
25
|
-
const WATERMARK_META = {
|
|
26
|
-
app_name: APP_NAME,
|
|
27
|
-
app_version: APP_VERSION,
|
|
28
|
-
app_author: APP_AUTHOR,
|
|
29
|
-
build_ts: new Date().toISOString(),
|
|
30
|
-
build_id: crypto.randomBytes(8).toString('hex')
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
if (!fs.existsSync(RES_BIN)) {
|
|
34
|
-
console.error('resources.bin introuvable:', RES_BIN);
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
const KEY = process.env.KEY;
|
|
38
|
-
if (!KEY) {
|
|
39
|
-
console.error('ERREUR: définis la variable d\'env KEY (clé HMAC/chiffrement).');
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 1) prepend watermark JSON (small) to the encrypted payload in a deterministic envelope
|
|
44
|
-
const resData = fs.readFileSync(RES_BIN);
|
|
45
|
-
const wmJson = Buffer.from(JSON.stringify(WATERMARK_META), 'utf8');
|
|
46
|
-
const wmLen = Buffer.alloc(4);
|
|
47
|
-
wmLen.writeUInt32BE(wmJson.length, 0);
|
|
48
|
-
const payloadWithWm = Buffer.concat([Buffer.from('WMKT', 'ascii'), wmLen, wmJson, resData]);
|
|
49
|
-
|
|
50
|
-
// 2) compute HMAC-SHA256 over this payload
|
|
51
|
-
const hmac = crypto.createHmac('sha256', crypto.createHash('sha256').update(KEY).digest());
|
|
52
|
-
hmac.update(payloadWithWm);
|
|
53
|
-
const hmacDigest = hmac.digest(); // Buffer
|
|
54
|
-
|
|
55
|
-
// 3) write back payload (replace resources.bin) and hmac file
|
|
56
|
-
fs.writeFileSync(RES_BIN, payloadWithWm);
|
|
57
|
-
fs.writeFileSync(OUT_HMAC, hmacDigest);
|
|
58
|
-
|
|
59
|
-
console.log('Security addons: watermark injected and HMAC written ->', OUT_HMAC);
|
|
60
|
-
console.log('Watermark meta:', WATERMARK_META);
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const { execFileSync, execSync } = require('child_process');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
const BUILD_TOOLS = path.resolve(__dirname);
|
|
6
|
-
const vendorSigntool = path.join(BUILD_TOOLS, 'vendor', 'signtool', process.platform === 'win32' ? 'signtool.exe' : 'signtool');
|
|
7
|
-
const certsDir = path.join(BUILD_TOOLS, 'certs');
|
|
8
|
-
|
|
9
|
-
function die(msg){ console.error(msg); process.exit(2); }
|
|
10
|
-
|
|
11
|
-
if (!fs.existsSync(vendorSigntool)) die('Vendor signtool not found: ' + vendorSigntool);
|
|
12
|
-
|
|
13
|
-
const pfx = fs.readdirSync(certsDir).find(f => f.endsWith('.pfx'));
|
|
14
|
-
if (!pfx) die('No .pfx found in ' + certsDir);
|
|
15
|
-
const pfxPath = path.join(certsDir, pfx);
|
|
16
|
-
|
|
17
|
-
// Get password by running decrypt script
|
|
18
|
-
let pwd;
|
|
19
|
-
try{
|
|
20
|
-
pwd = execSync(`node "${path.join(BUILD_TOOLS, 'decrypt_pfx_password.js')}"`, {encoding:'utf8'}).trim();
|
|
21
|
-
} catch(e){ die('Failed to decrypt pfx password: ' + e.message); }
|
|
22
|
-
|
|
23
|
-
const target = path.resolve(path.join(__dirname, '..', 'dist', 'MonApp-Setup-1.0.0.exe'));
|
|
24
|
-
if (!fs.existsSync(target)) die('Target not found: ' + target);
|
|
25
|
-
|
|
26
|
-
const args = ['sign', '/f', pfxPath, '/p', pwd, '/tr', 'http://timestamp.digicert.com', '/td', 'sha256', '/fd', 'sha256', target];
|
|
27
|
-
|
|
28
|
-
console.log('Running:', vendorSigntool, args.join(' '));
|
|
29
|
-
try{
|
|
30
|
-
execFileSync(vendorSigntool, args, { stdio: 'inherit' });
|
|
31
|
-
console.log('\nTest sign completed successfully');
|
|
32
|
-
} catch(e){
|
|
33
|
-
console.error('\nTest sign failed:', e.message);
|
|
34
|
-
process.exit(e.status || 1);
|
|
35
|
-
}
|