forked from sindresorhus/create-dmg
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsla.js
More file actions
145 lines (124 loc) · 3.22 KB
/
sla.js
File metadata and controls
145 lines (124 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import {Buffer} from 'node:buffer';
import process from 'node:process';
import fs from 'node:fs';
import path from 'node:path';
import {execa} from 'execa';
import {temporaryFile} from 'tempy';
import plist from 'plist';
// LPic resource: default language 0, count 1, language entry (0, 0, 0)
const LPIC_DATA = Buffer.from([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
// STR# resource: button labels for English
// Format: count (2 bytes) + pascal strings (length byte + string)
const STR_DATA = Buffer.from([
0x00,
0x06, // 6 strings
0x07,
...Buffer.from('English'),
0x05,
...Buffer.from('Agree'),
0x08,
...Buffer.from('Disagree'),
0x05,
...Buffer.from('Print'),
0x07,
...Buffer.from('Save...'),
0x7B,
...Buffer.from('If you agree with the terms of this license, press "Agree" to install the software. If you do not agree, press "Disagree".'),
]);
// Styl resource: basic style info
const STYL_DATA = Buffer.from([
0x00,
0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0E,
0x00,
0x11,
0x00,
0x15,
0x00,
0x00,
0x00,
0x0C,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
]);
function createRtfFromText(text) {
let escaped = '';
for (const char of text) {
switch (char) {
case '\\':
case '{':
case '}': {
escaped += `\\${char}`;
break;
}
case '\n': {
escaped += '\\par\n';
break;
}
case '\r': {
// ignore
break;
}
default: { escaped += char.codePointAt(0) <= 0x7F ? char : `\\u${char.codePointAt(0)}?`;
}
}
}
return `{\\rtf1\\ansi\\ansicpg1252\\cocoartf1504\\cocoasubrtf830
{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;}
{\\colortbl;\\red255\\green255\\blue255;}
{\\*\\expandedcolortbl;;}
\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\txal\\partightenfactor0
\\f0\\fs24 \\cf0 ${escaped}}`;
}
function createResource(id, name, data) {
return {
Attributes: '0x0000',
Data: data,
ID: String(id),
Name: name,
};
}
export default async function sla(dmgPath) {
const rtfSlaFile = path.join(process.cwd(), 'license.rtf');
const txtSlaFile = path.join(process.cwd(), 'license.txt');
const hasRtf = fs.existsSync(rtfSlaFile);
const hasTxt = fs.existsSync(txtSlaFile);
if (!hasRtf && !hasTxt) {
return;
}
let rtfData;
let textData;
if (hasRtf) {
rtfData = fs.readFileSync(rtfSlaFile);
const {stdout} = await execa('/usr/bin/textutil', ['-convert', 'txt', '-stdout', rtfSlaFile]);
textData = Buffer.from(stdout, 'utf8');
} else {
const plainText = fs.readFileSync(txtSlaFile, 'utf8');
textData = Buffer.from(plainText, 'utf8');
rtfData = Buffer.from(createRtfFromText(plainText));
}
const resources = {
LPic: [createResource(5000, 'English', LPIC_DATA)],
'RTF ': [createResource(5000, 'English SLA', rtfData)],
'STR#': [createResource(5000, 'English', STR_DATA)],
TEXT: [createResource(5000, 'English SLA', textData)],
styl: [createResource(5000, 'English', STYL_DATA)],
};
const plistContent = plist.build(resources);
const temporaryPlistPath = temporaryFile({extension: 'plist'});
fs.writeFileSync(temporaryPlistPath, plistContent);
try {
await execa('/usr/bin/hdiutil', ['udifrez', dmgPath, '-xml', temporaryPlistPath]);
} finally {
fs.rmSync(temporaryPlistPath, {force: true});
}
}