Project

General

Profile

Download (8.21 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / build.sh @ 263d03d5

1
#!/bin/sh
2

    
3
# This file is part of Haketilo
4
#
5
# Copyright (C) 2021, Wojtek Kosior
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the CC0 1.0 Universal License as published by
9
# the Creative Commons Corporation.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# CC0 1.0 Universal License for more details.
15

    
16
handle_export_line() {
17
    if [ "x$1" = "xEXPORTS_START" ]; then
18
	if [ "$STATE" = "before_block" ]; then
19
	    STATE="in_block"
20
	fi
21
    elif [ "x$1" = "xEXPORT" ]; then
22
	if [ "$STATE" != "in_block" ]; then
23
	    return
24
	fi
25

    
26
	EXPORTCODE="${EXPORTCODE}window.killtheweb.$2 = $2;$ENDL"
27

    
28
	PREVIOUS_FILE="$(map_get EXPORTS $2)"
29
	if [ "x$PREVIOUS_FILE" != "x" ]; then
30
	    errcho "export $2 present in both $PREVIOUS_FILE and $FILE"
31
	    return 1
32
	fi
33

    
34
	map_set_instr EXPORTS $2 "$FILE"
35

    
36
    elif [ "x$1" = "xEXPORTS_END" ]; then
37
	if [ "$STATE" = "in_block" ]; then
38
	    STATE="after_block"
39
	fi
40
    fi
41
}
42

    
43
translate_exports() {
44
    STATE="before_block"
45
    EXPORTCODE=''
46

    
47
    while read EXPORT_LINE; do
48
	handle_export_line $EXPORT_LINE || return 1
49
    done
50

    
51
    map_set_instr EXPORTCODES $FILEKEY "$EXPORTCODE"
52
}
53

    
54
add_exports() {
55
    FILE="$1"
56
    FILEKEY="$(sanitize "$FILE")"
57

    
58
    eval "$(grep -o 'EXPORT.\+' "$1" | translate_exports || exit 1)"
59
}
60

    
61
handle_import_line() {
62
    if [ "x$1" = "xIMPORTS_START" ]; then
63
	if [ "$STATE" = "before_block" ]; then
64
	    STATE="in_block"
65
	fi
66
    elif [ "x$1" = "xIMPORT" ]; then
67
	if [ "$STATE" != "in_block" ]; then
68
	    return
69
	fi
70

    
71
	IMPORTCODE="${IMPORTCODE}const $2 = window.killtheweb.$2;$ENDL"
72

    
73
	IMPORTS="$IMPORTS $2"
74

    
75
    elif [ "x$1" = "xIMPORTS_END" ]; then
76
	if [ "$STATE" = "in_block" ]; then
77
	    STATE="after_block"
78
	fi
79
    fi
80
}
81

    
82
translate_imports() {
83
    STATE="before_block"
84
    IMPORTCODE=''
85
    IMPORTS=''
86

    
87
    while read IMPORT_LINE; do
88
	handle_import_line $IMPORT_LINE || return 1
89
    done
90

    
91
    map_set_instr IMPORTCODES $FILEKEY "$IMPORTCODE"
92
    map_set_instr IMPORTS $FILEKEY "$IMPORTS"
93
}
94

    
95
add_imports() {
96
    FILE="$1"
97
    FILEKEY="$(sanitize "$FILE")"
98

    
99
    eval "$(grep -o 'IMPORT.\+' "$1" | translate_imports || exit 1)"
100
}
101

    
102
compute_scripts_list_rec() {
103
    local FILE="$1"
104
    local FILEKEY=$(sanitize "$1")
105

    
106
    local FILESTATE="$(map_get FILESTATES $FILEKEY)"
107
    if [ "xprocessed" = "x$FILESTATE" ]; then
108
	return
109
    fi
110
    if [ "xprocessing" = "x$FILESTATE" ]; then
111
	errcho "import loop on $FILE"
112
	return 1
113
    fi
114

    
115
    USED="$USED $FILEKEY"
116

    
117
    map_set FILESTATES $FILEKEY "processing"
118

    
119
    local IMPORT
120
    for IMPORT in $(map_get IMPORTS $FILEKEY); do
121
	NEXT_FILE="$(map_get EXPORTS $IMPORT)"
122
	if [ "x" = "x$NEXT_FILE" ]; then
123
	    errcho "nothing exports $IMPORT, required by $FILE"
124
	    return 1
125
	fi
126
	if ! compute_scripts_list_rec "$NEXT_FILE"; then
127
	    errcho "when satisfying $IMPORT for $FILE"
128
	    return 1
129
	fi
130
    done
131

    
132
    [ "x$FILE" = "xexports_init.js" ] || echo $FILE # exports_init.js is hardcoded to load first; the entire export system depends on it
133
    map_set FILESTATES $FILEKEY "processed"
134
}
135

    
136
compute_scripts_list() {
137
    USED=''
138
    echo COMPUTED_SCRIPTS=\"exports_init.js
139
    compute_scripts_list_rec "$1"
140
    echo \"
141

    
142
    for FILEKEY in $USED; do
143
	map_set_instr USED $FILEKEY yes
144
    done
145
}
146

    
147
as_json_list() {
148
    while true; do
149
	if [ "x" = "x$2" ]; then
150
	    echo -n '\\n'"\t\t\"$1\""'\\n\t'
151
	    return
152
	fi
153
	echo -n '\\n'"\t\t\"$1\","
154
	shift
155
    done
156
}
157

    
158
as_html_list() {
159
    while [ "x" != "x$1" ]; do
160
	echo -n '\\n'"    <script src=\"/$1\"></script>"
161
	shift
162
    done
163
}
164

    
165
build_main() {
166
    # placate importers of these, as they are exported by the yet-to-be-created exports_init.js
167
    EXPORTS__browser=exports_init.js
168
    EXPORTS__is_chrome=exports_init.js
169
    EXPORTS__is_mozilla=exports_init.js
170

    
171
    SCRIPTDIRS='background html common content'
172

    
173
    SCRIPTS=$(find $SCRIPTDIRS -name '[^.#]*.js')
174

    
175
    for SCRIPT in $SCRIPTS; do
176
	add_exports $SCRIPT
177
	add_imports $SCRIPT
178
    done
179

    
180
    eval "$(compute_scripts_list background/main.js || exit 1)"
181
    BGSCRIPTS="$(as_json_list $COMPUTED_SCRIPTS)"
182
    eval "$(compute_scripts_list content/main.js || exit 1)"
183
    CONTENTSCRIPTS="$(as_json_list $COMPUTED_SCRIPTS)"
184
    eval "$(compute_scripts_list html/display-panel.js || exit 1)"
185
    POPUPSCRIPTS="$(as_html_list $COMPUTED_SCRIPTS)"
186
    eval "$(compute_scripts_list html/options_main.js || exit 1)"
187
    OPTIONSSCRIPTS="$(as_html_list $COMPUTED_SCRIPTS)"
188

    
189
    for DIR in $(find $SCRIPTDIRS -type d); do
190
	mkdir -p "$BUILDDIR"/$DIR
191
    done
192

    
193
    CHROMIUM_KEY=''
194
    CHROMIUM_UPDATE_URL=''
195
    GECKO_APPLICATIONS=''
196

    
197
    if [ "x$UPDATE_URL" != x ]; then
198
	UPDATE_URL=",\n    \"update_url\": \"$UPDATE_URL\""
199
    fi
200

    
201
    if [ "$BROWSER" = "chromium" ]; then
202
	CHROMIUM_KEY="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64)"
203
	CHROMIUM_KEY=$(echo chromium-key-dummy-file-$CHROMIUM_KEY | tr / -)
204
	touch "$BUILDDIR"/$CHROMIUM_KEY
205

    
206
	CHROMIUM_UPDATE_URL="$UPDATE_URL"
207

    
208
	CHROMIUM_KEY="\n\
209
	// WARNING!!!\n\
210
	// EACH USER SHOULD REPLACE DUMMY FILE's VALUE WITH A UNIQUE ONE!!!\n\
211
	// OTHERWISE, SECURITY CAN BE TRIVIALLY COMPROMISED!\n\
212
	// Only relevant to users of chrome-based browsers.\n\
213
	// Users of Firefox forks are safe.\n\
214
	\"$CHROMIUM_KEY\"\
215
"
216
    else
217
	GECKO_APPLICATIONS="\n\
218
    \"applications\": {\n\
219
	\"gecko\": {\n\
220
	    \"id\": \"{6fe13369-88e9-440f-b837-5012fb3bedec}\",\n\
221
	    \"strict_min_version\": \"60.0\"$UPDATE_URL\n\
222
	}\n\
223
    },"
224
    fi
225

    
226
    sed "\
227
s^_GECKO_APPLICATIONS_^$GECKO_APPLICATIONS^
228
s^_CHROMIUM_KEY_^$CHROMIUM_KEY^
229
s^_CHROMIUM_UPDATE_URL_^$CHROMIUM_UPDATE_URL^
230
s^_BGSCRIPTS_^$BGSCRIPTS^
231
s^_CONTENTSCRIPTS_^$CONTENTSCRIPTS^" \
232
	< manifest.json > "$BUILDDIR"/manifest.json
233

    
234
    ./process_html_file.sh html/display-panel.html |
235
	sed "s^_POPUPSCRIPTS_^$POPUPSCRIPTS^" \
236
	    > "$BUILDDIR"/html/display-panel.html
237

    
238
    ./process_html_file.sh html/options.html |
239
	sed "s^_OPTIONSSCRIPTS_^$OPTIONSSCRIPTS^" \
240
	    > "$BUILDDIR"/html/options.html
241

    
242
    for FILE in $SCRIPTS; do
243
	FILEKEY=$(sanitize "$FILE")
244
	if [ "xyes" != "x$(map_get USED $FILEKEY)" ]; then
245
	    errcho "WARNING! $FILE not used"
246
	else
247
	    (echo "\
248
\"use strict\";
249

    
250
({fun: (function() {
251
$(map_get IMPORTCODES $FILEKEY)
252

    
253
";
254

    
255
# A hack to insert the contents of default_settings.json at the appropriate location in background/main.js
256
if [ "$FILE" = "background/main.js" ]; then
257
    # Uses an internal sed expression to escape and indent the JSON file for use in the external sed expression
258
    sed 's/^        `DEFAULT SETTINGS`$/'"$(sed -E 's/([\\\&\/])/\\\1/g; s/^/        /; s/$/\\/' < default_settings.json) "/g < "$FILE"
259
else
260
    cat $FILE
261
fi
262

    
263
echo "
264

    
265
$(map_get EXPORTCODES $FILEKEY)
266
})}).fun();") > "$BUILDDIR"/$FILE
267
	fi
268
    done
269

    
270
    if [ "$BROWSER" = "chromium" ]; then
271
	cat > "$BUILDDIR"/exports_init.js <<EOF
272
window.killtheweb={is_chrome: true, browser: window.chrome};
273
EOF
274
    else
275
	cat > "$BUILDDIR"/exports_init.js <<EOF
276
/* Polyfill for IceCat 60. */
277
String.prototype.matchAll = String.prototype.matchAll || function(regex) {
278
    if (regex.flags.search("g") === -1)
279
        throw new TypeError("String.prototype.matchAll called with a non-global RegExp argument");
280

    
281
    for (const matches = [];;) {
282
        if (matches[matches.push(regex.exec(this)) - 1] === null)
283
	    return matches.splice(0, matches.length - 1);
284
    }
285
}
286

    
287
window.killtheweb={is_mozilla: true, browser: this.browser};
288
EOF
289
    fi
290

    
291
    cp -r copyright licenses/ "$BUILDDIR"
292
    cp html/*.css "$BUILDDIR"/html
293
    mkdir "$BUILDDIR"/icons
294
    cp icons/*.png "$BUILDDIR"/icons
295

    
296
    if [ "$BROWSER" = "chromium" ]; then
297
	for MOZILLA_FILE in $(find "$BUILDDIR" -name "MOZILLA_*"); do
298
	    echo > "$MOZILLA_FILE"
299
	done
300
    fi
301
    if [ "$BROWSER" = "mozilla" ]; then
302
	for CHROMIUM_FILE in $(find "$BUILDDIR" -name "CHROMIUM_*"); do
303
	    echo > "$CHROMIUM_FILE"
304
	done
305
    fi
306
}
307

    
308
main() {
309
    if [ "x$1" = "xmozilla" -o "x$1" = "xchromium" ]; then
310
	BROWSER=$1
311
    else
312
	errcho "usage:  $0 mozilla|chromium [source directory] [update url]"
313
	exit 1
314
    fi
315

    
316
    SRCDIR="${2:-.}"
317
    if [ -d "$SRCDIR" ]; then
318
	BUILDDIR="$(realpath $BROWSER-unpacked)"
319
	rm -rf "$BUILDDIR"
320
	mkdir "$BUILDDIR"
321
	cd "$SRCDIR"
322
    else
323
	errcho "usage:  $0 mozilla|chromium [source directory] [update url]"
324
	exit 2
325
    fi
326

    
327
    UPDATE_URL="$3"
328

    
329
    . ./shell_utils.sh
330
    build_main
331
}
332

    
333
main "$@"
(3-3/12)