#!/bin/sh
# Copyright (C) 2021 Wojtek Kosior
# Redistribution terms are gathered in the `copyright' file.
. ./shell_utils.sh
handle_export_line() {
if [ "x$1" = "xEXPORTS_START" ]; then
if [ "$STATE" = "before_block" ]; then
STATE="in_block"
fi
elif [ "x$1" = "xEXPORT" ]; then
if [ "$STATE" != "in_block" ]; then
return
fi
EXPORTCODE="${EXPORTCODE}window.killtheweb.$2 = $2;$ENDL"
PREVIOUS_FILE="$(map_get EXPORTS $2)"
if [ "x$PREVIOUS_FILE" != "x" ]; then
errcho "export $2 present in both $PREVIOUS_FILE and $FILE"
return 1
fi
map_set_instr EXPORTS $2 "$FILE"
elif [ "x$1" = "xEXPORTS_END" ]; then
if [ "$STATE" = "in_block" ]; then
STATE="after_block"
fi
fi
}
translate_exports() {
STATE="before_block"
EXPORTCODE=''
while read EXPORT_LINE; do
handle_export_line $EXPORT_LINE || return 1
done
map_set_instr EXPORTCODES $FILEKEY "$EXPORTCODE"
}
add_exports() {
FILE="$1"
FILEKEY="$(sanitize "$FILE")"
eval "$(grep -o 'EXPORT.\+' "$1" | translate_exports || exit 1)"
}
handle_import_line() {
if [ "x$1" = "xIMPORTS_START" ]; then
if [ "$STATE" = "before_block" ]; then
STATE="in_block"
fi
elif [ "x$1" = "xIMPORT" ]; then
if [ "$STATE" != "in_block" ]; then
return
fi
IMPORTCODE="${IMPORTCODE}const $2 = window.killtheweb.$2;$ENDL"
IMPORTS="$IMPORTS $2"
elif [ "x$1" = "xIMPORTS_END" ]; then
if [ "$STATE" = "in_block" ]; then
STATE="after_block"
fi
fi
}
translate_imports() {
STATE="before_block"
IMPORTCODE=''
IMPORTS=''
while read IMPORT_LINE; do
handle_import_line $IMPORT_LINE || return 1
done
map_set_instr IMPORTCODES $FILEKEY "$IMPORTCODE"
map_set_instr IMPORTS $FILEKEY "$IMPORTS"
}
add_imports() {
FILE="$1"
FILEKEY="$(sanitize "$FILE")"
eval "$(grep -o 'IMPORT.\+' "$1" | translate_imports || exit 1)"
}
compute_scripts_list_rec() {
local FILE="$1"
local FILEKEY=$(sanitize "$1")
local FILESTATE="$(map_get FILESTATES $FILEKEY)"
if [ "xprocessed" = "x$FILESTATE" ]; then
return
fi
if [ "xprocessing" = "x$FILESTATE" ]; then
errcho "import loop on $FILE"
return 1
fi
USED="$USED $FILEKEY"
map_set FILESTATES $FILEKEY "processing"
local IMPORT
for IMPORT in $(map_get IMPORTS $FILEKEY); do
NEXT_FILE="$(map_get EXPORTS $IMPORT)"
if [ "x" = "x$NEXT_FILE" ]; then
errcho "nothing exports $IMPORT, required by $FILE"
return 1
fi
if ! compute_scripts_list_rec "$NEXT_FILE"; then
errcho "when satisfying $IMPORT for $FILE"
return 1
fi
done
[ "x$FILE" = "xexports_init.js" ] || echo $FILE # exports_init.js is hardcoded to load first; the entire export system depends on it
map_set FILESTATES $FILEKEY "processed"
}
compute_scripts_list() {
USED=''
echo COMPUTED_SCRIPTS=\"exports_init.js
compute_scripts_list_rec "$1"
echo \"
for FILEKEY in $USED; do
map_set_instr USED $FILEKEY yes
done
}
as_json_list() {
while true; do
if [ "x" = "x$2" ]; then
echo -n '\\n'"\t\t\"$1\""'\\n\t'
return
fi
echo -n '\\n'"\t\t\"$1\","
shift
done
}
as_html_list() {
while [ "x" != "x$1" ]; do
echo -n '\\n'" "
shift
done
}
set_browser() {
if [ "x$1" = "xmozilla" -o "x$1" = "xchromium" ]; then
BROWSER="$1"
else
errcho "usage: $0 mozilla|chromium"
exit 1
fi
}
main() {
set_browser "$1"
# placate importers of these, as they are exported by the yet-to-be-created exports_init.js
EXPORTS__browser=exports_init.js
EXPORTS__is_chrome=exports_init.js
EXPORTS__is_mozilla=exports_init.js
SCRIPTDIRS='background html common content'
SCRIPTS=$(find $SCRIPTDIRS -name '[^.#]*.js')
for SCRIPT in $SCRIPTS; do
add_exports $SCRIPT
add_imports $SCRIPT
done
eval "$(compute_scripts_list background/main.js || exit 1)"
BGSCRIPTS="$(as_json_list $COMPUTED_SCRIPTS)"
eval "$(compute_scripts_list content/main.js || exit 1)"
CONTENTSCRIPTS="$(as_json_list $COMPUTED_SCRIPTS)"
eval "$(compute_scripts_list html/display-panel.js || exit 1)"
POPUPSCRIPTS="$(as_html_list $COMPUTED_SCRIPTS)"
eval "$(compute_scripts_list html/options_main.js || exit 1)"
OPTIONSSCRIPTS="$(as_html_list $COMPUTED_SCRIPTS)"
BUILDDIR=build_$BROWSER
rm -rf $BUILDDIR
mkdir $BUILDDIR
for DIR in $(find $SCRIPTDIRS -type d); do
mkdir -p $BUILDDIR/$DIR
done
CHROMIUM_KEY=''
GECKO_APPLICATIONS=''
if [ "$BROWSER" = "chromium" ]; then
CHROMIUM_KEY="\n\
\n\
// WARNING!!!\n\
// EACH USER SHOULD REPLACE \"key\" WITH A UNIQUE VALUE!!!\n\
// OTHERWISE, SECURITY CAN BE TRIVIALLY COMPROMISED!\n\
//\n\
// A unique key can be generated with:\n\
// $ ssh-keygen -f /path/to/new/key.pem -t rsa -b 1024\n\
//\n\
// Only relevant to users of chrome-based browsers.\n\
// Users of Firefox forks are safe.\n\
\n\
\"key\": \"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcnNhAAAAAwEAAQAAAIEA+0GT5WNmRRo8e5tL9+BmNtY6aBPwLIgbPnLShYBMSR40iYwLTsccrkwBXb3bs1o4p6q5WJugI8Lsia+GXZc/XHGFkq7D1aWiTxlJLs8z0JC2TQ2/yatYmBMchogYGeeUfP7aI7JJZwpATts+VhIvgga/4FYj+DijMIEpwdckqFEAAAII4Dh7HOA4exwAAAAHc3NoLXJzYQAAAIEA+0GT5WNmRRo8e5tL9+BmNtY6aBPwLIgbPnLShYBMSR40iYwLTsccrkwBXb3bs1o4p6q5WJugI8Lsia+GXZc/XHGFkq7D1aWiTxlJLs8z0JC2TQ2/yatYmBMchogYGeeUfP7aI7JJZwpATts+VhIvgga/4FYj+DijMIEpwdckqFEAAAADAQABAAAAgEHB5/MhEKMFOs8e1cMJ97ZiWubiUPlWpcqyQmauLUj1nspg3JTBh8AWJEVkaxuFgU5gYCHQmRjC6yUdywyziOEkFA4r/WpX4WmbIe+GQHRHhitLN0dgF8N6/fVNOoa5StTdfZqyl23pVXyepoDNjrJFKyupqPMmpwfH5lGr9RwBAAAAQG76HflB/5j8P2YgIYX6dQT4Ei0SqiIjNVy7jFJUQDKSJg/PYkedE02JZJBJPcMYxEJUxXtMgq+upamNILfkmY0AAABBAP4v0O5dqjy16xDDFzb4DPNAcw5Za9KJaXKVkUuKXMNZOKTR0RC/upjNTmttY980RKdIx5zA25dO8cx563bSDIsAAABBAP0MaOpBiai/eRmLqhlthHODa+Mur6W3uc9PyhWhgDBjLNMR/doaYeyfVKxtIiN3a+HkN++G+vbokRweQv++bhMAAAANdXJ6QGxvY2FsaG9zdAECAwQFBg==\","
else
GECKO_APPLICATIONS="\n\
\"applications\": {\n\
\"gecko\": {\n\
\"id\": \"{6fe13369-88e9-440f-b837-5012fb3bedec}\",\n\
\"strict_min_version\": \"60.0\"\n\
}\n\
},"
fi
sed "\
s^_GECKO_APPLICATIONS_^$GECKO_APPLICATIONS^
s^_CHROMIUM_KEY_^$CHROMIUM_KEY^
s^_BGSCRIPTS_^$BGSCRIPTS^
s^_CONTENTSCRIPTS_^$CONTENTSCRIPTS^" \
< manifest.json > $BUILDDIR/manifest.json
./process_html_file.sh html/display-panel.html |
sed "s^_POPUPSCRIPTS_^$POPUPSCRIPTS^" \
> $BUILDDIR/html/display-panel.html
./process_html_file.sh html/options.html |
sed "s^_OPTIONSSCRIPTS_^$OPTIONSSCRIPTS^" \
> $BUILDDIR/html/options.html
for FILE in $SCRIPTS; do
FILEKEY=$(sanitize "$FILE")
if [ "xyes" != "x$(map_get USED $FILEKEY)" ]; then
errcho "WARNING! $FILE not used"
else
(echo "\
\"use strict\";
({fun: (function() {
$(map_get IMPORTCODES $FILEKEY)
";
# A hack to insert the contents of default_settings.json at the appropriate location in background/main.js
if [ "$FILE" = "background/main.js" ]; then
# Uses an internal sed expression to escape and indent the JSON file for use in the external sed expression
sed 's/^ `DEFAULT SETTINGS`$/'"$(sed -E 's/([\\\&\/])/\\\1/g; s/^/ /; s/$/\\/' < default_settings.json) "/g < "$FILE"
else
cat $FILE
fi
echo "
$(map_get EXPORTCODES $FILEKEY)
})}).fun();") > $BUILDDIR/$FILE
fi
done
if [ "$BROWSER" = "chromium" ]; then
cat > $BUILDDIR/exports_init.js < $BUILDDIR/exports_init.js < "$MOZILLA_FILE"
done
fi
if [ "$BROWSER" = "mozilla" ]; then
for CHROMIUM_FILE in $(find $BUILDDIR -name "CHROMIUM_*"); do
echo > "$CHROMIUM_FILE"
done
fi
}
main "$@"