diff options
| author | Oskar <oskar@mullvad.net> | 2024-11-05 07:57:08 +0100 |
|---|---|---|
| committer | Oskar <oskar@mullvad.net> | 2024-11-14 16:43:18 +0100 |
| commit | 84f14d79c4f0dde73337820ec94ba8ff928a3797 (patch) | |
| tree | ce468658e5ba7b0a74950c7ad1b09b3a4d00520b /gui/scripts | |
| parent | e3ce0eb5cd0610dbff6ec98cb8cb388415c74bf6 (diff) | |
| download | mullvadvpn-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.md | 41 | ||||
| -rwxr-xr-x | gui/scripts/build-logo-icons.sh | 97 | ||||
| -rwxr-xr-x | gui/scripts/build-proto.sh | 48 | ||||
| -rwxr-xr-x | gui/scripts/build-test-executable.sh | 80 | ||||
| -rw-r--r-- | gui/scripts/extract-translations.js | 52 | ||||
| -rwxr-xr-x | gui/scripts/fetch-relay-locations.py | 125 | ||||
| -rwxr-xr-x | gui/scripts/generate-menubar-icons.sh | 224 | ||||
| -rw-r--r-- | gui/scripts/integrate-relay-locations.py | 76 | ||||
| -rw-r--r-- | gui/scripts/osv-scanner.toml | 43 | ||||
| -rw-r--r-- | gui/scripts/pylintrc | 15 | ||||
| -rw-r--r-- | gui/scripts/requirements.txt | 55 | ||||
| -rw-r--r-- | gui/scripts/verify-translations-format.ts | 147 |
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); -} |
