summaryrefslogtreecommitdiffhomepage
path: root/gui/scripts
diff options
context:
space:
mode:
authorOskar <oskar@mullvad.net>2024-11-05 07:57:08 +0100
committerOskar <oskar@mullvad.net>2024-11-14 16:43:18 +0100
commit84f14d79c4f0dde73337820ec94ba8ff928a3797 (patch)
treece468658e5ba7b0a74950c7ad1b09b3a4d00520b /gui/scripts
parente3ce0eb5cd0610dbff6ec98cb8cb388415c74bf6 (diff)
downloadmullvadvpn-84f14d79c4f0dde73337820ec94ba8ff928a3797.tar.xz
mullvadvpn-84f14d79c4f0dde73337820ec94ba8ff928a3797.zip
Move gui directory to desktop/packages/mullvad-vpn
Diffstat (limited to 'gui/scripts')
-rw-r--r--gui/scripts/README.md41
-rwxr-xr-xgui/scripts/build-logo-icons.sh97
-rwxr-xr-xgui/scripts/build-proto.sh48
-rwxr-xr-xgui/scripts/build-test-executable.sh80
-rw-r--r--gui/scripts/extract-translations.js52
-rwxr-xr-xgui/scripts/fetch-relay-locations.py125
-rwxr-xr-xgui/scripts/generate-menubar-icons.sh224
-rw-r--r--gui/scripts/integrate-relay-locations.py76
-rw-r--r--gui/scripts/osv-scanner.toml43
-rw-r--r--gui/scripts/pylintrc15
-rw-r--r--gui/scripts/requirements.txt55
-rw-r--r--gui/scripts/verify-translations-format.ts147
12 files changed, 0 insertions, 1003 deletions
diff --git a/gui/scripts/README.md b/gui/scripts/README.md
deleted file mode 100644
index 8556bb85fb..0000000000
--- a/gui/scripts/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-This is a folder with the supporting scripts written in Python 3, node, bash.
-
-
-## Maps and location translations
-
-### Dependency installation notes
-
-1. Run the following command in terminal to install python dependencies:
- `pip3 install -r requirements.txt`
-
-2. Make sure you have gettext utilities installed.
- https://www.gnu.org/software/gettext/
-
-
-### Update translations
-
-See [locales/README.md](../locales/README.md) for information about how to handle translations.
-
-The `<repo>/scripts/localization` script is, among other things, calling into `fetch-relay-locations.py`
-and `integrate-relay-locations.py` in this directory.
-
-* `fetch-relay-locations.py` fetches the relay list and extracts all country and city names.
-* `intregrate-relay-locations.py` integrates the fetched relay locations into
-`<repo>/gui/locales/relay-locations.pot`.
-
-### Locking Python dependencies
-
-1. Freeze dependencies:
-
-```
-pip3 freeze -r requirements.txt
-```
-
-and save the output into `requirements.txt`.
-
-
-2. Hash them with `hashin` tool:
-
-```
-hashin --python 3.7 --verbose --update-all
-```
diff --git a/gui/scripts/build-logo-icons.sh b/gui/scripts/build-logo-icons.sh
deleted file mode 100755
index e35f713e77..0000000000
--- a/gui/scripts/build-logo-icons.sh
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env bash
-
-# This script creates the macOS .icns from the icons in /graphics/macOS/ which need to be updated
-# first if the source SVGs have been updated. More info about how to update them can be found in
-# the readme.
-#
-# Icon guidelines for macOS:
-# https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/app-icon/
-#
-# Icon templates for macOS:
-# https://developer.apple.com/design/resources/
-#
-# Icon guidelines for Windows:
-# https://docs.microsoft.com/en-us/windows/uwp/design/style/app-icons-and-logos#target-size-app-icon-assets
-# https://docs.microsoft.com/en-us/windows/win32/uxguide/vis-icons
-
-echo "Press enter to continue if you've followed the instructions in graphics/README.md"
-read -r
-
-set -eu
-
-if ! command -v convert > /dev/null; then
- echo >&2 "convert (imagemagick) is required to run this script"
- exit 1
-fi
-
-if ! command -v rsvg-convert > /dev/null; then
- echo >&2 "rsvg-convert (librsvg) is required to run this script"
- exit 1
-fi
-
-if ! command -v iconutil > /dev/null; then
- echo >&2 "iconutil is required to run this script"
- exit 1
-fi
-
-
-
-SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cd "$SCRIPT_DIR"
-
-GRAPHICS_DIR="../../graphics"
-DIST_ASSETS_DIR="../../dist-assets"
-SVG_SOURCE_PATH="$GRAPHICS_DIR/icon.svg"
-TMP_DIR=$(mktemp -d)
-TMP_ICO_DIR="$TMP_DIR/ico"
-TMP_ICONSET_DIR="$TMP_DIR/icon.iconset"
-
-mkdir "$TMP_ICONSET_DIR"
-mkdir "$TMP_ICO_DIR"
-
-COMPRESSION_OPTIONS="-define png:compression-filter=5 -define png:compression-level=9 \
- -define png:compression-strategy=1 -define png:exclude-chunk=all -strip"
-
-# macOS .icns icon
-for icon in "$GRAPHICS_DIR/macOS"/*; do
- cp "$icon" "$TMP_ICONSET_DIR"/
-done
-
-iconutil --convert icns --output "$DIST_ASSETS_DIR/icon-macos.icns" "$TMP_ICONSET_DIR"
-rm "$TMP_ICONSET_DIR"/*
-
-# Linux .icns icon
-for size in 16 32 128 256 512; do
- double_size="$((size * 2))"
- rsvg-convert -o "$TMP_ICONSET_DIR"/icon-$size.png -w $size -h $size $SVG_SOURCE_PATH
- rsvg-convert -o "$TMP_ICONSET_DIR"/icon-$size@2x.png -w "$double_size" -h "$double_size" \
- $SVG_SOURCE_PATH
-done
-iconutil --convert icns --output $DIST_ASSETS_DIR/icon.icns "$TMP_ICONSET_DIR"
-rm -rf "$TMP_ICONSET_DIR"
-
-# Windows .ico icon
-for size in 16 20 24 30 32 36 40 48 60 64 72 80 96 256 512; do
- rsvg-convert -o "$TMP_ICO_DIR"/$size.png -w $size -h $size $SVG_SOURCE_PATH
-done
-convert "$TMP_ICO_DIR"/* "$COMPRESSION_OPTIONS" $DIST_ASSETS_DIR/icon.ico
-rm -rf "$TMP_ICO_DIR"
-
-# Windows installer sidebar
-# "bmp3" specifies the Windows 3.x format which is required for the image to be displayed
-sidebar_path="$TMP_DIR/sidebar.png"
-sidebar_logo_size=234
-rsvg-convert -o "$sidebar_path" -w $sidebar_logo_size -h $sidebar_logo_size $SVG_SOURCE_PATH
-convert -background "#294D73" "$sidebar_path" \
- -gravity center -extent ${sidebar_logo_size}x314 \
- -gravity west -crop 164x314+10+0 bmp3:$DIST_ASSETS_DIR/windows/installersidebar.bmp
-rm "$sidebar_path"
-
-# GUI notification icon
-rsvg-convert -o ../assets/images/icon-notification.png -w 128 -h 128 $SVG_SOURCE_PATH
-
-# GUI in app icon
-cp "$SVG_SOURCE_PATH" ../assets/images/logo-icon.svg
-
-rmdir "$TMP_DIR"
-
diff --git a/gui/scripts/build-proto.sh b/gui/scripts/build-proto.sh
deleted file mode 100755
index 8861eb5730..0000000000
--- a/gui/scripts/build-proto.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env bash
-
-set -eu
-
-SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cd "$SCRIPT_DIR"
-
-ARCH="$(uname -m)"
-PLATFORM="$(uname -s)"
-MANAGEMENT_INTERFACE_PROTO_BUILD_DIR=${MANAGEMENT_INTERFACE_PROTO_BUILD_DIR:-}
-NODE_MODULES_DIR="$(cd ../node_modules/.bin && pwd)"
-PROTO_DIR="../../mullvad-management-interface/proto"
-PROTO_FILENAME="management_interface.proto"
-DESTINATION_DIR="../build/src/main/management_interface"
-TYPES_DESTINATION_DIR="../src/main/management_interface"
-
-TS_PROTOC_PLUGIN="$NODE_MODULES_DIR/protoc-gen-ts"
-if [[ "$(uname -s)" == "MINGW"* ]]; then
- TS_PROTOC_PLUGIN="$TS_PROTOC_PLUGIN.cmd"
-fi
-
-mkdir -p $DESTINATION_DIR
-mkdir -p $TYPES_DESTINATION_DIR
-
-if [[ "$PLATFORM" == "Linux" && ("${ARCH,,}" == "arm64" || "${ARCH,,}" == "aarch64") ]]; then
- if [[ -n "${MANAGEMENT_INTERFACE_PROTO_BUILD_DIR}" ]]; then
- cp "$MANAGEMENT_INTERFACE_PROTO_BUILD_DIR"/*.js $DESTINATION_DIR
- cp "$MANAGEMENT_INTERFACE_PROTO_BUILD_DIR"/*.ts $TYPES_DESTINATION_DIR
- else
- >&2 echo "Building management interface proto files on aarch64 is not supported"
- >&2 echo "(see https://github.com/grpc/grpc-node/issues/1497)."
- >&2 echo "Please build the proto files on another platform using build-proto.sh script,"
- >&2 echo "and set MANAGEMENT_INTERFACE_PROTO_BUILD_DIR environment variable to the directory of the build."
- exit 1
- fi
-else
- "$NODE_MODULES_DIR/grpc_tools_node_protoc" \
- --js_out=import_style=commonjs,binary:$DESTINATION_DIR \
- --grpc_out=grpc_js:$DESTINATION_DIR \
- --proto_path=$PROTO_DIR \
- $PROTO_DIR/$PROTO_FILENAME
-
- "$NODE_MODULES_DIR/grpc_tools_node_protoc" \
- --plugin=protoc-gen-ts="$TS_PROTOC_PLUGIN" \
- --ts_out=grpc_js:$TYPES_DESTINATION_DIR \
- --proto_path=$PROTO_DIR \
- $PROTO_DIR/$PROTO_FILENAME
-fi
diff --git a/gui/scripts/build-test-executable.sh b/gui/scripts/build-test-executable.sh
deleted file mode 100755
index dd2758ebc3..0000000000
--- a/gui/scripts/build-test-executable.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env bash
-
-set -eu
-
-SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cd "$SCRIPT_DIR/.."
-
-TARGET=${1:-$(rustc -vV | sed -n 's|host: ||p')}
-PRODUCT_VERSION=$(cargo run -q --bin mullvad-version)
-
-ASSETS=(
- "build/src/config.json"
- "build/src/renderer/lib/routes.js"
- "build/test/e2e/utils.js"
- "build/test/e2e/shared/*.js"
- "build/test/e2e/installed/*.js"
- "build/test/e2e/installed/**/*.js"
- "node_modules/.bin/playwright"
- "node_modules/playwright"
- "node_modules/playwright-core"
- "node_modules/@playwright/test"
-)
-
-function build_test_executable {
- local pkg_target=$1
- local bin_suffix=${2:-""}
- local temp_dir
- temp_dir="$(mktemp -d)"
- local temp_executable="$temp_dir/temp-test-executable$bin_suffix"
- local output="../dist/app-e2e-tests-$PRODUCT_VERSION-$TARGET$bin_suffix"
- local node_copy_path="$temp_dir/node$bin_suffix"
- local node_path
- node_path="$(volta which node || which node)"
-
- # pack assets
- cp "$node_path" "$node_copy_path"
- # shellcheck disable=SC2068
- tar -czf ./build/test/assets.tar.gz ${ASSETS[@]}
-
- cp "$node_copy_path" "$temp_executable"
- node --experimental-sea-config standalone-tests.sea.json
-
- # Inject SEA blob
- case $pkg_target in
- macos-*)
- codesign --remove-signature "$temp_executable"
- npx postject "$temp_executable" NODE_SEA_BLOB \
- standalone-tests.sea.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \
- --macho-segment-name NODE_SEA
- codesign --sign - "$temp_executable"
- ;;
- *)
- npx postject "$temp_executable" NODE_SEA_BLOB \
- standalone-tests.sea.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
- ;;
- esac
-
- mkdir -p "$(dirname "$output")"
- mv "$temp_executable" "$output"
-
- rm -rf "$temp_dir"
-}
-
-case "$TARGET" in
- "aarch64-unknown-linux-gnu")
- build_test_executable linux-arm64
- ;;
- "x86_64-unknown-linux-gnu")
- build_test_executable linux-x64
- ;;
- "aarch64-apple-darwin")
- build_test_executable macos-arm64
- ;;
- "x86_64-apple-darwin")
- build_test_executable macos-x64
- ;;
- "x86_64-pc-windows-msvc")
- build_test_executable win-x64 .exe
- ;;
-esac
diff --git a/gui/scripts/extract-translations.js b/gui/scripts/extract-translations.js
deleted file mode 100644
index e101ca03a5..0000000000
--- a/gui/scripts/extract-translations.js
+++ /dev/null
@@ -1,52 +0,0 @@
-const { GettextExtractor, JsExtractors } = require('gettext-extractor');
-const path = require('path');
-
-const extractor = new GettextExtractor();
-const outputPotFile = path.resolve(__dirname, '../locales/messages.pot');
-const comments = {
- otherLineLeading: true,
- sameLineLeading: true,
- regex: /^TRANSLATORS:\s*(.*)$/,
-};
-
-extractor
- .createJsParser([
- JsExtractors.callExpression('messages.gettext', {
- arguments: {
- text: 0,
- },
- comments,
- }),
- JsExtractors.callExpression('messages.pgettext', {
- arguments: {
- context: 0,
- text: 1,
- },
- comments,
- }),
- JsExtractors.callExpression('messages.ngettext', {
- arguments: {
- text: 0,
- textPlural: 1,
- },
- comments,
- }),
- JsExtractors.callExpression('messages.npgettext', {
- arguments: {
- context: 0,
- text: 1,
- textPlural: 2,
- },
- comments,
- }),
- ])
- .parseFilesGlob('./src/**/*.@(ts|tsx)', {
- cwd: path.resolve(__dirname, '..'),
- });
-
-// clean file references
-extractor.getMessages().forEach((msg) => {
- msg.references = [];
-});
-extractor.savePotFile(outputPotFile);
-extractor.printStats();
diff --git a/gui/scripts/fetch-relay-locations.py b/gui/scripts/fetch-relay-locations.py
deleted file mode 100755
index 374ec98601..0000000000
--- a/gui/scripts/fetch-relay-locations.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env python3
-"""
-This module adds relay location city and country names to relay-locations.pot
-"""
-
-import os
-from os import path
-import json
-import urllib.request
-from polib import POFile, POEntry
-import colorful as c
-
-SCRIPT_DIR = path.dirname(path.realpath(__file__))
-
-# The output directory for the generated content
-OUT_DIR = path.join(SCRIPT_DIR, "out")
-
-# the directory with the generated localizations content
-LOCALE_OUT_DIR = path.join(OUT_DIR, "locales")
-
-# Relay locations gettext catalogue template filename (.pot)
-RELAY_LOCATIONS_POT_FILENAME = "relay-locations.pot"
-
-
-def extract_relay_translations():
- try:
- response = request_relays()
- except Exception as e:
- print(c.red("Failed to fetch the relays list: {}".format(e)))
- raise
-
- locations = response.get("locations")
- countries = structure_locations(locations)
-
- extract_relay_locations_pot(countries)
-
-
-def structure_locations(locations):
- countries = {}
-
- for location_key in locations:
- location = locations.get(location_key)
- country_name = location.get("country")
- city_name = location.get("city")
-
- if not "-" in location_key:
- print("Location key incorrectly formatted: {}".format(location_key))
- continue
-
- country_code, city_code = location_key.split("-")
-
- if country_name is None:
- print("Country name missing for {}".format(location_key))
- continue
-
- if city_name is None:
- print("City name missing for {}".format(location_key))
- continue
-
- if country_code not in countries:
- countries[country_code] = {"name": country_name, "cities": {}}
-
- country = countries[country_code]
- cities = country["cities"]
- if city_code not in cities:
- cities[city_code] = city_name
- else:
- print("There are multiple entries for {} in {}".format(city_name, country_name))
-
- return countries
-
-
-def extract_relay_locations_pot(countries):
- pot = POFile(encoding='utf-8', check_for_duplicates=True)
- pot.metadata = {"Content-Type": "text/plain; charset=utf-8"}
- output_path = path.join(LOCALE_OUT_DIR, RELAY_LOCATIONS_POT_FILENAME)
-
- print("Generating {}".format(output_path))
-
- for country_code in countries:
- country = countries[country_code]
- entry = POEntry(
- msgid=country["name"],
- msgstr="",
- comment=country_code.upper()
- )
- pot.append(entry)
-
- cities = country["cities"]
- for city_code in cities:
- entry = POEntry(
- msgid=cities[city_code],
- msgstr="",
- comment="{} {}".format(country_code.upper(), city_code.upper())
- )
-
- try:
- pot.append(entry)
- except ValueError as err:
- print(c.orange("Cannot add an entry: {}".format(err)))
-
- pot.save(output_path)
-
-
-def request_relays():
- request = urllib.request.Request("https://api.mullvad.net/app/v1/relays")
- with urllib.request.urlopen(request) as connection:
- return json.load(connection)
-
-
-# Program main()
-
-def main():
- # ensure output path exists
- if not path.exists(OUT_DIR):
- os.makedirs(OUT_DIR)
-
- # ensure locales output path exists
- if not path.exists(LOCALE_OUT_DIR):
- os.makedirs(LOCALE_OUT_DIR)
-
- # extract translations
- extract_relay_translations()
-
-main()
diff --git a/gui/scripts/generate-menubar-icons.sh b/gui/scripts/generate-menubar-icons.sh
deleted file mode 100755
index 8bd4310ace..0000000000
--- a/gui/scripts/generate-menubar-icons.sh
+++ /dev/null
@@ -1,224 +0,0 @@
-#!/usr/bin/env bash
-
-# This script generates the PNG/ICO menubar icons from the SVG files in `/menubar-icons/svg/`.
-# Please see /menubar-icons/README.md for more information.
-
-set -eu
-
-if ! command -v convert > /dev/null; then
- echo >&2 "convert (imagemagick) is required to run this script"
- exit 1
-fi
-
-if ! command -v rsvg-convert > /dev/null; then
- echo >&2 "rsvg-convert (librsvg) is required to run this script"
- exit 1
-fi
-
-SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cd "$SCRIPT_DIR"
-
-MENUBAR_ICONS_DIR="../assets/images/menubar-icons"
-
-SVG_DIR="$MENUBAR_ICONS_DIR/svg"
-MACOS_DIR="$MENUBAR_ICONS_DIR/darwin"
-WINDOWS_DIR="$MENUBAR_ICONS_DIR/win32"
-LINUX_DIR="$MENUBAR_ICONS_DIR/linux"
-TMP_DIR=$(mktemp -d)
-
-COMPRESSION_OPTIONS=(
- -define png:compression-filter=5
- -define png:compression-level=9
- -define png:compression-strategy=1
- -define png:exclude-chunk=all
- -strip
-)
-
-function main() {
- mkdir -p "$MACOS_DIR" "$WINDOWS_DIR" "$LINUX_DIR"
-
- for frame in {1..9}; do
- generate "lock-$frame" "lock-$frame"
- done
- # The monochrome source svg differs from the colored one. The red circle is a hole in the monochrome
- # one. "lock-10_mono.svg" is the same icon but with a hole instead of a circle.
- generate lock-10 lock-10_mono
-
- rmdir "$TMP_DIR"
-}
-
-# Genares the ico icons for the Windows tray icon. The ico consists of 3 different resolutions with
-# 3 different bit depths each. Each icon is also available with and without notification dot.
-function generate_ico() {
- local svg_source_path="$1"
- local ico_target_path="$2"
-
- local tmp_file_paths=()
- local notification_icon_tmp_file_paths=()
- for size in 16 32 48; do
- local padding=$((size / 16))
- local notification_icon_size=$((size / 2))
- local png_tmp_path="$TMP_DIR/$size"
-
- generate_square "$svg_source_path" "$png_tmp_path.png" \
- "${png_tmp_path}_notification.png" "$size" "$padding" "$notification_icon_size"
-
- # 4- and 8-bit versions for RDP
- convert -colors 256 +dither "$png_tmp_path.png" png8:"$png_tmp_path-8.png"
- convert -colors 16 +dither "$png_tmp_path-8.png" "$png_tmp_path-4.png"
-
- convert -colors 256 +dither "${png_tmp_path}_notification.png" \
- png8:"${png_tmp_path}_notification-8.png"
- convert -colors 16 +dither "${png_tmp_path}_notification-8.png" \
- "${png_tmp_path}_notification-4.png"
-
- tmp_file_paths+=("$png_tmp_path.png" "$png_tmp_path-8.png" "$png_tmp_path-4.png")
- notification_icon_tmp_file_paths+=(
- "${png_tmp_path}_notification.png"
- "${png_tmp_path}_notification-8.png"
- "${png_tmp_path}_notification-4.png"
- )
- done
-
- convert "${tmp_file_paths[@]}" "${COMPRESSION_OPTIONS[@]}" "$ico_target_path.ico"
- convert "${notification_icon_tmp_file_paths[@]}" "${COMPRESSION_OPTIONS[@]}" \
- "${ico_target_path}_notification.ico"
-
- rm "${tmp_file_paths[@]}"
- rm "${notification_icon_tmp_file_paths[@]}"
-}
-
-# Generates pngs both for regular icon and icon with notification symbol next to the icon, ending
-# up with a rectangular icon.
-function generate_rectangle() {
- local svg_source_path="$1"
- local png_target_path="$2"
- local png_notification_target_path="$3"
- local target_size=$4
- local target_padding=$5
- local notification_width=$6
- local target_size_no_padding=$((target_size - target_padding * 2))
- local png_tmp_path="$TMP_DIR/tmp.png"
-
- generate_lock_png "$svg_source_path" "$png_target_path" "$target_size" "$target_padding"
- append_notification_icon "$png_target_path" "$png_notification_target_path" \
- "$notification_width"
-
- rm "$png_tmp_path"
-}
-
-# Generates pngs both for regular icon and icon with notification symbol, ending up with a square
-# icon since the notification dot is overlapping the lock.
-function generate_square() {
- local svg_source_path="$1"
- local png_target_path="$2"
- local png_notification_target_path="$3"
- local target_size=$4
- local target_padding=$5
- local notification_width=$6
- local target_size_no_padding=$((target_size - target_padding * 2))
- local png_tmp_path="$TMP_DIR/tmp.png"
-
- generate_lock_png "$svg_source_path" "$png_target_path" "$target_size" "$target_padding"
- overlay_notification_icon "$png_target_path" "$png_notification_target_path" \
- "$notification_width"
-
- rm "$png_tmp_path"
-}
-
-# Generates the lock png
-function generate_lock_png() {
- local svg_source_path="$1"
- local png_target_path="$2"
- local target_size=$3
- local target_padding=$4
- local target_size_no_padding=$((target_size - target_padding * 2))
- local png_tmp_path="$TMP_DIR/tmp.png"
-
- rsvg-convert -o "$png_tmp_path" -w $target_size_no_padding -h $target_size_no_padding \
- "$svg_source_path"
- convert -background transparent "$png_tmp_path" -gravity center \
- -extent "${target_size}x$target_size" "${COMPRESSION_OPTIONS[@]}" "$png_target_path"
-}
-
-# Creates a copy of the icon at $source_path and appends the notification symbol to it
-function append_notification_icon() {
- local source_path="$1"
- local target_path="$2"
- local width="$3"
- local padding="${4:-0}"
- local size=$((width + 2))
- local notification_icon_tmp_path="$TMP_DIR/notification.png"
-
- rsvg-convert -o "$notification_icon_tmp_path" -w $size -h $size \
- --left "$padding" --page-width $((size + padding)) --page-height $size \
- "$SVG_DIR/notification.svg"
- convert -strip -background transparent -colorspace sRGB -gravity center \
- +append "$source_path" "$notification_icon_tmp_path" "$target_path"
-
- rm "$notification_icon_tmp_path"
-}
-
-# Creates a copy of the icon at $source_path and puts the notification symbol on top of it in the
-# bottom right corner.
-function overlay_notification_icon() {
- local source_path="$1"
- local target_path="$2"
- local size="$3"
- local notification_icon_tmp_path="$TMP_DIR/notification.png"
-
- rsvg-convert -o "$notification_icon_tmp_path" -w "$size" -h "$size" "$SVG_DIR/notification.svg"
- convert -strip -background transparent -composite -colorspace sRGB -gravity SouthEast \
- "$source_path" "$notification_icon_tmp_path" "$target_path"
-
- rm "$notification_icon_tmp_path"
-}
-
-# Generates all icon versions for a specific frame.
-function generate() {
- local icon_name="$1"
- local svg_source_path="$SVG_DIR/$icon_name.svg"
- local monochrome_svg_source_path="$SVG_DIR/$2.svg"
-
- local black_svg_source_path="$TMP_DIR/black.svg"
- local white_svg_source_path="$TMP_DIR/white.svg"
-
- local macos_target_base_path="$MACOS_DIR/$icon_name"
- local linux_target_base_path="$LINUX_DIR/$icon_name"
- local windows_target_base_path="$WINDOWS_DIR/$icon_name"
-
- sed -E 's/#[0-9a-fA-f]{6}/#000000/g' "$monochrome_svg_source_path" > "$black_svg_source_path"
- sed -E 's/#[0-9a-fA-f]{6}/#FFFFFF/g' "$monochrome_svg_source_path" > "$white_svg_source_path"
-
- # MacOS colored
- generate_rectangle "$svg_source_path" "$macos_target_base_path.png" \
- "${macos_target_base_path}_notification.png" 22 3 4
- generate_rectangle "$svg_source_path" "$macos_target_base_path@2x.png" \
- "${macos_target_base_path}_notification@2x.png" 44 6 8
-
- # MacOS monochrome
- generate_rectangle "$black_svg_source_path" "${macos_target_base_path}Template.png" \
- "${macos_target_base_path}_notificationTemplate.png" 22 3 4
- generate_rectangle "$black_svg_source_path" "${macos_target_base_path}Template@2x.png" \
- "${macos_target_base_path}_notificationTemplate@2x.png" 44 6 8
-
- # Linux colored
- generate_square "$svg_source_path" "$linux_target_base_path.png" \
- "${linux_target_base_path}_notification.png" 48 4 24
-
- # Linux white
- generate_square "$white_svg_source_path" "${linux_target_base_path}_white.png" \
- "${linux_target_base_path}_white_notification.png" 48 4 24
-
- # Windows colored
- generate_ico "$svg_source_path" "$windows_target_base_path"
-
- # Windows monochrome
- generate_ico "$white_svg_source_path" "${windows_target_base_path}_white"
- generate_ico "$black_svg_source_path" "${windows_target_base_path}_black"
-
- rm "$black_svg_source_path" "$white_svg_source_path"
-}
-
-main
-
diff --git a/gui/scripts/integrate-relay-locations.py b/gui/scripts/integrate-relay-locations.py
deleted file mode 100644
index e99b6a211e..0000000000
--- a/gui/scripts/integrate-relay-locations.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-A helper script to integrate the generated geo data into the app.
-"""
-
-import os
-from os import path
-from subprocess import Popen, PIPE
-import shutil
-import colorful as c
-
-SCRIPT_DIR = path.dirname(path.realpath(__file__))
-
-# The name of the relay locations gettext catalogue template file
-RELAY_LOCATIONS_POT_FILENAME = "relay-locations.pot"
-
-# The directory with the generated content
-GENERATED_CONTENT_OUTPUT_PATH = path.join(SCRIPT_DIR, "out")
-
-# The directory with the generated localizations content
-GENERATED_TRANSLATIONS_PATH = path.join(GENERATED_CONTENT_OUTPUT_PATH, "locales")
-
-# The directory with the existing app localizations
-APP_TRANSLATIONS_PATH = path.realpath(path.join(SCRIPT_DIR, "../locales"))
-
-def merge_relay_locations_catalogue_template():
- existing_pot_file = path.join(APP_TRANSLATIONS_PATH, RELAY_LOCATIONS_POT_FILENAME)
- generated_pot_file = path.join(GENERATED_TRANSLATIONS_PATH, RELAY_LOCATIONS_POT_FILENAME)
-
- merge_gettext_catalogues(existing_pot_file, generated_pot_file)
-
-
-def merge_gettext_catalogues(existing_catalogue_file, generated_catalogue_file):
- if path.exists(existing_catalogue_file):
- args = (
- existing_catalogue_file, generated_catalogue_file,
-
- "--output-file", existing_catalogue_file,
-
- # ensure that the first occurrence takes precedence in merge conflict
- "--use-first",
-
- # sort by msgid
- "--sort-output",
-
- # disable wrapping long strings because crowdin does not do that
- "--no-wrap"
- )
-
- (exit_code, errors) = run_program("msgcat", *args)
-
- if exit_code == 0:
- print(c.green("Merged {} into {}.".format(generated_catalogue_file, existing_catalogue_file)))
- else:
- print(c.red("msgcat exited with {}: {}".format(exit_code, errors.decode().strip())))
- else:
- print(c.orange("The existing catalogue does not exist. Copying {} to {}")
- .format(generated_catalogue_file, existing_catalogue_file))
- shutil.copyfile(generated_catalogue_file, existing_catalogue_file)
-
-
-def run_program(*args):
- with Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) as subproc:
- print("Run: {}".format(' '.join(args)))
-
- errors = subproc.communicate()[1]
- return (subproc.returncode, errors)
-
-
-# Program main()
-
-def main():
- merge_relay_locations_catalogue_template()
-
-main()
diff --git a/gui/scripts/osv-scanner.toml b/gui/scripts/osv-scanner.toml
deleted file mode 100644
index c415d89235..0000000000
--- a/gui/scripts/osv-scanner.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-# See repository root `osv-scanner.toml` for instructions and rules for this file.
-
-# Pillow arbitrary code execution
-[[IgnoredVulns]]
-id = "CVE-2023-50447" # GHSA-3f63-hfp8-52jq
-ignoreUntil = 2024-12-05
-reason = "Only used internally, on trusted input. This tool is also scheduled for removal completely, so not worth trying to upgrade"
-
-# Pillow buffer overflow
-[[IgnoredVulns]]
-id = "CVE-2024-28219" # GHSA-44wm-f244-xhp3
-ignoreUntil = 2024-12-05
-reason = "Only used internally, on trusted input. This tool is also scheduled for removal completely, so not worth trying to upgrade"
-
-# Pillow DoS
-[[IgnoredVulns]]
-id = "CVE-2023-44271" # GHSA-8ghj-p4vj-mr35
-ignoreUntil = 2024-12-05
-reason = "Only used internally, on trusted input. This tool is also scheduled for removal completely, so not worth trying to upgrade"
-
-# libwebp: OOB write in BuildHuffmanTable
-[[IgnoredVulns]]
-id = "CVE-2023-5129" # GHSA-j7hp-h8jx-5ppr
-ignoreUntil = 2024-12-05
-reason = "Only used internally, on trusted input. This tool is also scheduled for removal completely, so not worth trying to upgrade"
-
-# Pillow versions before v10.0.1 bundled libwebp binaries in wheels that are vulnerable to CVE-2023-5129 (previously CVE-2023-4863)
-[[IgnoredVulns]]
-id = "PYSEC-2023-175"
-ignoreUntil = 2024-12-05
-reason = "Only used internally, on trusted input. This tool is also scheduled for removal completely, so not worth trying to upgrade"
-
-# Pillow versions before v10.0.1 bundled libwebp binaries in wheels that are vulnerable to CVE-2023-5129 (previously CVE-2023-4863)
-[[IgnoredVulns]]
-id = "GHSA-56pw-mpj4-fxww"
-ignoreUntil = 2024-12-05
-reason = "Only used internally, on trusted input. This tool is also scheduled for removal completely, so not worth trying to upgrade"
-
-# Pillow vulnerable to Data Amplification attack.
-[[IgnoredVulns]]
-id = "CVE-2022-45198" # GHSA-m2vv-5vj5-2hm7
-ignoreUntil = 2024-12-05
-reason = "Only used internally, on trusted input. This tool is also scheduled for removal completely, so not worth trying to upgrade"
diff --git a/gui/scripts/pylintrc b/gui/scripts/pylintrc
deleted file mode 100644
index 7f79439857..0000000000
--- a/gui/scripts/pylintrc
+++ /dev/null
@@ -1,15 +0,0 @@
-[FORMAT]
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string=' '
-
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=2
-
-[MESSAGES CONTROL]
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifier separated by comma (,) or put this option
-# multiple time (only on the command line, not in the configuration file where
-# it should appear only once).
-disable=invalid-name
diff --git a/gui/scripts/requirements.txt b/gui/scripts/requirements.txt
deleted file mode 100644
index 4a09a5bf34..0000000000
--- a/gui/scripts/requirements.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-polib==1.1.0 \
- --hash=sha256:93b730477c16380c9a96726c54016822ff81acfa553977fdd131f2b90ba858d7 \
- --hash=sha256:fad87d13696127ffb27ea0882d6182f1a9cf8a5e2b37a587751166c51e5a332a
-colorful==0.5.4 \
- --hash=sha256:86848ad4e2eda60cd2519d8698945d22f6f6551e23e95f3f14dfbb60997807ea \
- --hash=sha256:8d264b52a39aae4c0ba3e2a46afbaec81b0559a99be0d2cfe2aba4cf94531348
-## The following requirements were added by pip freeze:
-attrs==19.3.0 \
- --hash=sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c \
- --hash=sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72
-cffi==1.14.0 \
- --hash=sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0 \
- --hash=sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26 \
- --hash=sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6 \
- --hash=sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66 \
- --hash=sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f \
- --hash=sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3
-click==7.1.1 \
- --hash=sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc \
- --hash=sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a
-click-plugins==1.1.1 \
- --hash=sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b \
- --hash=sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8
-cligj==0.5.0 \
- --hash=sha256:20f24ce9abfde3f758aec3399e6811b936b6772f360846c662c19bf5537b4f14 \
- --hash=sha256:6c7d52d529a78712491974f975c33473f430c0f7beb18c0d7a402a743dcb460a
-cssselect2==0.3.0 \
- --hash=sha256:5c2716f06b5de93f701d5755a9666f2ee22cbcd8b4da8adddfc30095ffea3abc \
- --hash=sha256:97d7d4234f846f9996d838964d38e13b45541c18143bc55cf00e4bc1281ace76
-defusedxml==0.6.0 \
- --hash=sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93 \
- --hash=sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5
-munch==2.5.0 \
- --hash=sha256:2d735f6f24d4dba3417fa448cae40c6e896ec1fdab6cdb5e6510999758a4dbd2 \
- --hash=sha256:6f44af89a2ce4ed04ff8de41f70b226b984db10a91dcc7b9ac2efc1c77022fdd
-Pillow==9.0.1 \
- --hash=sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030 \
- --hash=sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e \
- --hash=sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa \
- --hash=sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360 \
- --hash=sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b \
- --hash=sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669 \
- --hash=sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092
-pycparser==2.20 \
- --hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \
- --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705
-six==1.14.0 \
- --hash=sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a \
- --hash=sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c
-tinycss2==1.0.2 \
- --hash=sha256:6427d0e3faa0a5e0e8c9f6437e2de26148a7a197a8b0992789f23d9a802788cf \
- --hash=sha256:9fdacc0e22d344ddd2ca053837c133900fe820ae1222f63b79617490a498507a
-webencodings==0.5.1 \
- --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
- --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923
diff --git a/gui/scripts/verify-translations-format.ts b/gui/scripts/verify-translations-format.ts
deleted file mode 100644
index 05ffb3e504..0000000000
--- a/gui/scripts/verify-translations-format.ts
+++ /dev/null
@@ -1,147 +0,0 @@
-import fs from 'fs';
-import { GetTextTranslation, po } from 'gettext-parser';
-import path from 'path';
-
-const LOCALES_DIR = path.join('..', 'locales');
-
-const ALLOWED_TAGS = ['b', 'br'];
-const ALLOWED_VOID_TAGS = ['br'];
-
-// Make sure to report these strings to crowdin. View this as a temporary escape
-// hatch, not a permanent solution.
-const IGNORED_STRINGS: Set<string> = new Set([
- // German translation. Has been reported to Crowdin.
- 'Daher verwenden wir automatisch Multihop, um %(daita)s mit jedem Server zu aktivieren.',
-]);
-
-function getLocales(): string[] {
- const localesContent = fs.readdirSync(LOCALES_DIR);
- const localeDirectories = localesContent.filter((item) =>
- fs.statSync(path.join(LOCALES_DIR, item)).isDirectory(),
- );
- return localeDirectories;
-}
-
-function parseTranslationsForLocale(locale: string): GetTextTranslation[] {
- const poFileContents = fs.readFileSync(path.join(LOCALES_DIR, locale, 'messages.po'));
- const contexts = po.parse(poFileContents).translations;
-
- const translations = Object.values(contexts)
- .flatMap((context) => Object.values(context))
- .filter((translation) => translation.msgid !== '');
-
- return translations;
-}
-
-function getFormatSpecifiers(text: string): string[] {
- // Matches both %(name)s and %s.
- return text.match(/%(\(.*?\))?[a-z]/g) ?? [];
-}
-
-function formatSpecifiersEquals(source: string[], translation: string[]): boolean {
- const sortedTranslation = translation.sort();
- return (
- source.length === translation.length &&
- source.sort().every((value, index) => value === sortedTranslation[index])
- );
-}
-
-function checkFormatSpecifiersImpl(msgid: string, msgstr: string): boolean {
- const sourceFormatSpecifiers = getFormatSpecifiers(msgid);
- const translationFormatSpecifiers = getFormatSpecifiers(msgstr);
- return formatSpecifiersEquals(sourceFormatSpecifiers, translationFormatSpecifiers);
-}
-
-function checkFormatSpecifiers(translation: GetTextTranslation): boolean {
- return translation.msgstr
- .map((msgstr) => {
- // Make sure that the translation matches either the singular or plural.
- const equal =
- checkFormatSpecifiersImpl(translation.msgid, msgstr) ||
- (translation.msgid_plural && checkFormatSpecifiersImpl(translation.msgid_plural, msgstr));
-
- if (!equal) {
- console.error(`Error in "${translation.msgid}", "${msgstr}"`);
- }
-
- return equal;
- })
- .every((result) => result);
-}
-
-function checkHtmlTagsImpl(value: string): { correct: boolean; amount: number } {
- const tagsRegexp = new RegExp('<.*?>', 'g');
- const tags = value.match(tagsRegexp) ?? [];
- const tagTypes = tags.map((tag) => tag.slice(1, -1));
-
- // Make sure tags match by pushing start-tags to a stack and matching closing tags with the last
- // item.
- const tagStack: string[] = [];
- for (let tag of tagTypes) {
- const selfClosing = tag.endsWith('/');
- const endTag = tag.startsWith('/');
- tag = endTag ? tag.slice(1) : selfClosing ? tag.slice(0, -1).trim() : tag;
-
- if (!ALLOWED_TAGS.includes(tag)) {
- console.error(`Tag "<${tag}>" not allowed: "${value}"`);
- return { correct: false, amount: NaN };
- }
-
- if (!ALLOWED_VOID_TAGS.includes(tag)) {
- if (endTag) {
- // End tags require a matching start tag.
- if (tag !== tagStack.pop()) {
- console.error(`Closing non-existent start-tag (</${tag}>) in "${value}"`);
- return { correct: false, amount: NaN };
- }
- } else {
- tagStack.push(tag);
- }
- }
- }
-
- if (tagStack.length > 0) {
- console.error(`Missing closing-tags (${tagStack}) in "${value}"`);
- return { correct: false, amount: NaN };
- }
-
- return { correct: true, amount: tags.length / 2 };
-}
-
-function checkHtmlTags(translation: GetTextTranslation): boolean {
- const { correct, amount: sourceAmount } = checkHtmlTagsImpl(translation.msgid);
-
- const translationsCorrect = translation.msgstr.every((value) => {
- const { correct, amount } = checkHtmlTagsImpl(value);
- // The amount doesn't make sense if the string isn't correctly formatted.
- if (correct && amount !== sourceAmount) {
- console.error(
- `Incorrect amount of tags in translation for "${translation.msgid}": "${value}"`,
- );
- }
- return correct && amount === sourceAmount;
- });
-
- return correct && translationsCorrect;
-}
-
-function checkTranslation(translation: GetTextTranslation): boolean {
- // Ignore some strings
- if (translation.msgstr.every((str) => IGNORED_STRINGS.has(str))) {
- return true;
- }
- return checkFormatSpecifiers(translation) && checkHtmlTags(translation);
-}
-
-const isCorrect = getLocales()
- .map(parseTranslationsForLocale)
- // Map first to output all errors
- .map((translations) => translations.every(checkTranslation))
- .every((result) => result);
-
-if (isCorrect) {
- console.log('Looks good!');
-} else {
- console.error('See above errors');
- process.exit(1);
-}