diff --git a/app/frontend/package-lock.json b/app/frontend/package-lock.json index 96fc6af..1a12fee 100644 --- a/app/frontend/package-lock.json +++ b/app/frontend/package-lock.json @@ -1806,6 +1806,16 @@ "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", "dev": true }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, "cacache": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", @@ -1832,6 +1842,34 @@ "unique-filename": "^1.1.1" } }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, "find-cache-dir": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", @@ -1853,6 +1891,25 @@ "path-exists": "^4.0.0" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "optional": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "optional": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -1917,6 +1974,16 @@ "minipass": "^3.1.1" } }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "optional": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "terser-webpack-plugin": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", @@ -1933,6 +2000,18 @@ "terser": "^4.6.12", "webpack-sources": "^1.4.3" } + }, + "vue-loader-v16": { + "version": "npm:vue-loader@16.1.2", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz", + "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==", + "dev": true, + "optional": true, + "requires": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + } } } }, @@ -4559,6 +4638,24 @@ "domelementtype": "1" } }, + "dot-object": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/dot-object/-/dot-object-2.1.4.tgz", + "integrity": "sha512-7FXnyyCLFawNYJ+NhkqyP9Wd2yzuo+7n9pGiYpkmXCTYa8Ci2U0eUNDVg5OuO5Pm6aFXI2SWN8/N/w7SJWu1WA==", + "dev": true, + "requires": { + "commander": "^4.0.0", + "glob": "^7.1.5" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + } + } + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -6798,6 +6895,12 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -11236,6 +11339,32 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", "dev": true }, + "vue-i18n": { + "version": "8.22.4", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.22.4.tgz", + "integrity": "sha512-XLI5s0AdqMP2Lf4I4CmdmOq8kjb5DDFGR77wAuxCfpEuYSfhTRyyx6MetgZMiL6Lxa0DasjBOiOcciU3NkL3/Q==" + }, + "vue-i18n-extract": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/vue-i18n-extract/-/vue-i18n-extract-1.1.10.tgz", + "integrity": "sha512-DYqcjrAm4L95Ftz8AVIzUyrHCBQV326rbOru6B3W2vXHIzUUuJwwFgyVPE+d7YTeHD189eoOkRu0aL6EzeMWZQ==", + "dev": true, + "requires": { + "commander": "^6.1.0", + "dot-object": "^2.1.4", + "glob": "^7.1.6", + "is-valid-glob": "^1.0.0", + "js-yaml": "^3.14.0" + }, + "dependencies": { + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + } + } + }, "vue-loader": { "version": "15.9.3", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.3.tgz", @@ -11257,87 +11386,6 @@ } } }, - "vue-loader-v16": { - "version": "npm:vue-loader@16.1.2", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz", - "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==", - "dev": true, - "optional": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "optional": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "optional": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "optional": true - }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dev": true, - "optional": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "vue-router": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.3.tgz", diff --git a/app/frontend/package.json b/app/frontend/package.json index 073ee82..5655dd9 100644 --- a/app/frontend/package.json +++ b/app/frontend/package.json @@ -5,7 +5,8 @@ "scripts": { "serve": "vue-cli-service serve --copy --port=4202", "build": "vue-cli-service build", - "lint": "vue-cli-service lint" + "lint": "vue-cli-service lint", + "vue-i18n-extract": "vue-i18n-extract report -a -v './src/**/*.?(js|vue)' -l './src/locales/*.?(json|yaml|yml)'" }, "dependencies": { "@fnando/sparkline": "^0.3.10", @@ -15,6 +16,7 @@ "sass-loader": "^10.0.4", "simple-keyboard": "^2.30.25", "vue": "^2.6.12", + "vue-i18n": "^8.22.4", "vue-router": "^3.4.3" }, "devDependencies": { @@ -24,6 +26,7 @@ "babel-eslint": "^10.1.0", "eslint": "^7.9.0", "eslint-plugin-vue": "^6.2.2", + "vue-i18n-extract": "1.1.10", "vue-template-compiler": "^2.6.12" }, "eslintConfig": { diff --git a/app/frontend/src/App.vue b/app/frontend/src/App.vue index 32c8dea..cca5c1d 100644 --- a/app/frontend/src/App.vue +++ b/app/frontend/src/App.vue @@ -29,24 +29,37 @@ diff --git a/app/frontend/src/locales/en.json b/app/frontend/src/locales/en.json new file mode 100644 index 0000000..e7786bf --- /dev/null +++ b/app/frontend/src/locales/en.json @@ -0,0 +1,81 @@ +{ + "home": { + "welcome_msg": "Welcome to TinyCheck.", + "help_msg": "We are going to help you to check your device.", + "start_btn": "Let's start!" + }, + "analysis": { + "question": "Do you want to analyze the captured communications?", + "no_btn": "No, just save them", + "yes_btn": "Yes, let's do it", + "please_wait_msg": "Please wait during the analysis...", + "some_time_msg": "Yes, it can take some time..." + }, + "capture": { + "intercept_coms_msg": "Intercepting the communications of ", + "stop_btn": "Stop the capture" + }, + "generate-ap": { + "network_name": "Network name", + "network_password": "Network password", + "tap_msg": "Tap the white frame to generate a new network.", + "generate_ap_msg": "We generate an ephemeral network for you.", + "error_msg1": "Unfortunately, we got some issues
during the AP creation.", + "error_msg2": "Please verify that you've two WiFi interfaces on your device
and try again by restarting it.", + "restart_btn": "Restart the device" + }, + "report": { + "show_full_report": "Show the full report", + "start_new_capture": "Start a new capture", + "save_capture": "Save the capture", + "numbers": [ + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "ten", + "eleven" + ], + "stalkerware_msg": "Your device is compromised by
a Stalkerware, please check the report.", + "location_msg": "An application is sharing your
current geolocation with a third party.", + "fine_msg": "Everything looks fine, zero alerts.", + "high_msg": "You have {nb} high alert,
your device seems to be compromised.", + "moderate_msg": "You have {nb} moderate alerts,
your device might be compromised.", + "low_msg": "You have only {nb} low alerts,
don't hesitate to check them.", + "save_report": "Save the report", + "report_of": "Report of", + "ip_address": "IP address", + "mac_address": "MAC address", + "high": "high", + "moderate": "moderate", + "low": "low" + }, + "wifi-select": { + "already_connected_question": "You seem to be already connected to a network.
Do you want to use the current connection?", + "no_btn": "No, use another", + "yes_btn": "Yes, use it.", + "wifi_name": "Wi-Fi name", + "refresh_btn": "Refresh networks list", + "not_connected": "You seem to not be connected to Internet.", + "please_config": "Please configure the Wi-Fi connection.", + "lets_do_btn": "Ok, let's do that.", + "wifi_connected": "Wi-Fi connected", + "wifi_not_connected": "Wi-Fi not connected. Please retry.", + "tap_keyboard": "Tap on the virtual keyboard to start", + "wifi_password": "Wi-Fi password", + "connect_to_it": "Connect to it" + }, + "save-capture": { + "please_connect": "Please connect a USB key to save your capture.", + "we_are_saving": "We are saving your capture.", + "tap_msg": "You can tap the USB key to start a new capture.", + "capture_download": "The capture download is going to start...", + "start_capture_btn": "Start another capture" + } +} \ No newline at end of file diff --git a/app/frontend/src/locales/fr.json b/app/frontend/src/locales/fr.json new file mode 100644 index 0000000..4447bd8 --- /dev/null +++ b/app/frontend/src/locales/fr.json @@ -0,0 +1,81 @@ +{ + "home": { + "welcome_msg": "Bienvenue sur TinyCheck.", + "help_msg": "Nous allons vous accompagner pour analyser votre appareil.", + "start_btn": "Allons-y !" + }, + "analysis": { + "question": "Voulez-vous analyser les communications capturées ?", + "no_btn": "Non, enregistrez-les.", + "yes_btn": "Oui, allons-y !", + "please_wait_msg": "Merci d'attendre pendant l'analyse...", + "some_time_msg": "Oui, cela peut prendre du temps..." + }, + "capture": { + "intercept_coms_msg": "Interception des communications de ", + "stop_btn": "Arrêter la capture" + }, + "generate-ap": { + "network_name": "Nom du réseau Wi-Fi", + "network_password": "Mot de passe", + "tap_msg": "Appuyez sur le cadre blanc pour générer un nouveau réseau.", + "generate_ap_msg": "Nous générons un réseau Wi-Fi éphémère.", + "error_msg1": "Malheureusement, nous rencontrons des problèmes
lors de la création du point d'accès.", + "error_msg2": "Veuillez vérifier que vous disposez de
deux interfaces WiFi sur votre appareil.", + "restart_btn": "Restart the device" + }, + "report": { + "show_full_report": "Lire le rapport complet", + "start_new_capture": "Nouvelle capture", + "save_capture": "Sauvegarder", + "numbers": [ + "zéro", + "une", + "deux", + "trois", + "quatre", + "cinq", + "six", + "sept", + "huit", + "neuf", + "dix", + "onze" + ], + "stalkerware_msg": "Votre smartphone est compromis
par un Stalkerware, lisez le rapport.", + "location_msg": "Une application dévoile votre
géo-localisation actelle.", + "fine_msg": "Tout semble OK, vous avez aucue alerte.", + "high_msg": "Vous avez {nb} alerte.s élevée.s,
votre appareil semble être compromis.", + "moderate_msg": "Vous avez {nb} alerte.s moyenne.s,
votre appareil est peut-être compromis.", + "low_msg": "Vous avez uniquement {nb} alerte.s basse.s
n'hésitez pas à les parcourir.", + "save_report": "Sauvegarder le rapport", + "report_of": "Rapport de", + "ip_address": "Adresse IP :", + "mac_address": "Adresse MAC :", + "high": "elevee", + "moderate": "moyenne", + "low": "base" + }, + "wifi-select": { + "already_connected_question": "Vous semblez être connecté à un réseau.
Voulez-vous utiliser cette connexion ?", + "no_btn": "Non, une autre", + "yes_btn": "Oui, utilisez celle-là", + "wifi_name": "Nom du réseau", + "refresh_btn": "Rafraichir la liste des réseaux", + "not_connected": "Vous semblez ne pas être connecté à Internet.", + "please_config": "Configurez la connexion Wi-Fi.", + "lets_do_btn": "Oui, allons-y.", + "wifi_connected": "Wi-Fi connecté", + "wifi_not_connected": "Wi-Fi non connecté. Ressayez.", + "tap_keyboard": "Appuez sur cet espace pour écrire", + "wifi_password": "Mot de passe", + "connect_to_it": "Se connecter" + }, + "save-capture": { + "please_connect": "Connectez une clé USB pour enregistrer votre capture.", + "we_are_saving": "Nous enregistrons votre capture.", + "tap_msg": "Vous pouvez appuyer sur l'animation pour lancer une nouvelle capture.", + "capture_download": "Le téléchargement de la capture va se lancer...", + "start_capture_btn": "Lancer une nouvelle capture" + } +} \ No newline at end of file diff --git a/app/frontend/src/main.js b/app/frontend/src/main.js index 3c99e4e..7b84c01 100644 --- a/app/frontend/src/main.js +++ b/app/frontend/src/main.js @@ -1,10 +1,13 @@ import Vue from 'vue' import App from './App.vue' import router from './router' +import { i18n } from '@/plugins/i18n' + Vue.config.productionTip = true Vue.config.devtools = true new Vue({ router, + i18n, render: h => h(App) }).$mount('#app') \ No newline at end of file diff --git a/app/frontend/src/plugins/i18n.js b/app/frontend/src/plugins/i18n.js new file mode 100644 index 0000000..d48a14b --- /dev/null +++ b/app/frontend/src/plugins/i18n.js @@ -0,0 +1,13 @@ +import Vue from 'vue' +import VueI18n from 'vue-i18n' + +Vue.use(VueI18n) + +export const i18n = new VueI18n({ + locale: 'en', + fallbackLocale: 'en', + messages: { + 'en': require('@/locales/en.json'), + 'fr': require('@/locales/fr.json') + } +}) \ No newline at end of file diff --git a/app/frontend/src/views/analysis.vue b/app/frontend/src/views/analysis.vue index 9ce84ac..c852ed7 100644 --- a/app/frontend/src/views/analysis.vue +++ b/app/frontend/src/views/analysis.vue @@ -1,15 +1,15 @@ @@ -39,7 +39,7 @@ export default { setTimeout(function () { this.long_waiting = true }.bind(this), 15000); axios.get(`/api/analysis/start/${this.capture_token}`, { timeout: 60000 }) .then(response => { - if(response.data.message == "Analysis started") + if(response.data.message == 'Analysis started') this.check_alerts = setInterval(() => { this.get_alerts(); }, 500); }) .catch(error => { @@ -49,13 +49,14 @@ export default { get_alerts: function() { axios.get(`/api/analysis/report/${this.capture_token}`, { timeout: 60000 }) .then(response => { - if(response.data.message != "No report yet"){ + if(response.data.message != 'No report yet'){ clearInterval(this.check_alerts); this.long_waiting = false; this.running = false; - router.replace({ name: 'report', params: { alerts : response.data.alerts, - device : response.data.device, - capture_token : this.capture_token } }); + router.replace({ name: 'report', + params: { alerts : response.data.alerts, + device : response.data.device, + capture_token : this.capture_token } }); } }) .catch(error => { @@ -64,11 +65,9 @@ export default { }, save_capture: function() { var capture_token = this.capture_token - router.replace({ name: 'save-capture', params: { capture_token: capture_token } }); + router.replace({ name: 'save-capture', + params: { capture_token: capture_token } }); } - }, - created: function() { - this.translation = window.translation[this.$route.name] } } diff --git a/app/frontend/src/views/capture.vue b/app/frontend/src/views/capture.vue index 9f01f68..4323d10 100644 --- a/app/frontend/src/views/capture.vue +++ b/app/frontend/src/views/capture.vue @@ -3,10 +3,10 @@
@@ -43,16 +43,16 @@ export default { }, stop_capture: function() { this.loading = true - axios.get(`/api/network/ap/stop`, { timeout: 30000 }) - axios.get(`/api/capture/stop`, { timeout: 30000 }) + axios.get('/api/network/ap/stop', { timeout: 30000 }) + axios.get('/api/capture/stop', { timeout: 30000 }) .then(response => (this.handle_finish(response.data))) }, get_stats: function() { - axios.get(`/api/capture/stats`, { timeout: 30000 }) + axios.get('/api/capture/stats', { timeout: 30000 }) .then(response => (this.handle_stats(response.data))) }, handle_stats: function(data) { - if (data.packets.length) sparkline(document.querySelector("#sparkline"), data.packets); + if (data.packets.length) sparkline(document.querySelector('#sparkline'), data.packets); }, handle_finish: function(data) { clearInterval(this.chrono_interval); @@ -66,32 +66,30 @@ export default { chrono: function() { var time = Date.now() - this.capture_start this.timer_hours = Math.floor(time / (60 * 60 * 1000)); - this.timer_hours = (this.timer_hours < 10) ? "0" + this.timer_hours : this.timer_hours + this.timer_hours = (this.timer_hours < 10) ? '0' + this.timer_hours : this.timer_hours time = time % (60 * 60 * 1000); this.timer_minutes = Math.floor(time / (60 * 1000)); - this.timer_minutes = (this.timer_minutes < 10) ? "0" + this.timer_minutes : this.timer_minutes + this.timer_minutes = (this.timer_minutes < 10) ? '0' + this.timer_minutes : this.timer_minutes time = time % (60 * 1000); this.timer_seconds = Math.floor(time / 1000); - this.timer_seconds = (this.timer_seconds < 10) ? "0" + this.timer_seconds : this.timer_seconds + this.timer_seconds = (this.timer_seconds < 10) ? '0' + this.timer_seconds : this.timer_seconds }, setup_sparklines: function() { - axios.get(`/api/misc/config`, { timeout: 60000 }) + axios.get('/api/misc/config', { timeout: 60000 }) .then(response => { if(response.data.sparklines){ this.sparklines = true - this.sparkwidth = window.screen.width + "px"; - this.sparkheight = Math.trunc(window.screen.height / 5) + "px"; + this.sparkwidth = window.screen.width + 'px'; + this.sparkheight = Math.trunc(window.screen.height / 5) + 'px'; this.stats_interval = setInterval(() => { this.get_stats(); }, 500); } }) .catch(error => { console.log(error) - }); + }); }, }, created: function() { - this.translation = window.translation[this.$route.name] - // Get the config for the sparklines. this.setup_sparklines() diff --git a/app/frontend/src/views/generate-ap.vue b/app/frontend/src/views/generate-ap.vue index 53f5920..663238c 100644 --- a/app/frontend/src/views/generate-ap.vue +++ b/app/frontend/src/views/generate-ap.vue @@ -9,29 +9,30 @@

- {{ translation.network_name }}
+ {{ $t("generate-ap.network_name") }}

{{ ssid_name }}

- {{ translation.network_password }}
+ {{ $t("generate-ap.network_password") }}

{{ ssid_password }}











- {{ translation.tap_msg }} + {{ $t("generate-ap.tap_msg") }}
-

{{ translation.generate_ap_msg }}

+

{{ $t("generate-ap.generate_ap_msg") }}

- +

-

+ +

- +
@@ -62,7 +63,7 @@ export default { generate_ap: function() { clearInterval(this.interval); this.ssid_name = false - axios.get(`/api/network/ap/start`, { timeout: 30000 }) + axios.get('/api/network/ap/start', { timeout: 30000 }) .then(response => (this.show_ap(response.data))) }, show_ap: function(data) { @@ -81,11 +82,11 @@ export default { } }, start_capture: function() { - axios.get(`/api/capture/start`, { timeout: 30000 }) + axios.get('/api/capture/start', { timeout: 30000 }) .then(response => (this.get_capture_token(response.data))) }, reboot: function() { - axios.get(`/api/misc/reboot`, { timeout: 30000 }) + axios.get('/api/misc/reboot', { timeout: 30000 }) .then(response => { console.log(response)}) }, get_capture_token: function(data) { @@ -116,20 +117,9 @@ export default { } }); } - }, - get_config: function() { - axios.get(`/api/misc/config`, { timeout: 60000 }) - .then(response => { - this.reboot_option = response.data.reboot_option - }) - .catch(error => { - console.log(error) - }); - }, + } }, created: function() { - this.translation = window.translation[this.$route.name] - this.get_config(); this.generate_ap(); } } diff --git a/app/frontend/src/views/home.vue b/app/frontend/src/views/home.vue index 2dddea2..6f7b52a 100644 --- a/app/frontend/src/views/home.vue +++ b/app/frontend/src/views/home.vue @@ -1,8 +1,8 @@ @@ -11,7 +11,7 @@ import router from '../router' export default { name: 'home', - props: { saved_ssid: String, iface_out: String, list_ssids: Array, internet: Boolean }, + props: { saved_ssid: String, list_ssids: Array, internet: Boolean }, data() { return { translation: {}, @@ -22,18 +22,15 @@ export default { var saved_ssid = this.saved_ssid var list_ssids = this.list_ssids var internet = this.internet - if (this.iface_out.charAt(0) == "e"){ + if (window.config.iface_out.charAt(0) == "e"){ router.push({ name: 'generate-ap' }); } else { router.push({ name: 'wifi-select', params: { saved_ssid: saved_ssid, list_ssids: list_ssids, - internet:internet } }); + internet: internet } }); } } - }, - created: function() { - this.translation = window.translation[this.$route.name] } } diff --git a/app/frontend/src/views/report.vue b/app/frontend/src/views/report.vue index 51a1ba5..131b2ae 100644 --- a/app/frontend/src/views/report.vue +++ b/app/frontend/src/views/report.vue @@ -3,69 +3,69 @@
-

- - +

+ +
-

- - +

+ +
-

- - +

+ +
-

- - +

+ +
-

- - +

+ +
-

- - +

{{ $t("report.fine_msg") }}

+ +
-

{{ translation.report_of }} {{ device.name }}

- {{ translation.ip_address }} {{device.ip_address}}
{{ translation.mac_address }} {{device.mac_address}} +

{{ $t("report.report_of") }} {{device.name}}

+ {{ $t("report.ip_address") }} {{device.ip_address}}
{{ $t("report.mac_address") }} {{device.mac_address}}
- +
- +
@@ -116,15 +116,6 @@ export default { new_capture: function() { router.push({ name: 'generate-ap' }) }, - nb_translate: function(x) { - var nbs = this.translation["numbers"] - try { - return nbs[x]; - } catch (error) - { - return x; - } - }, grep_keyword: function(kw, level){ try { if(this.alerts[level].length){ @@ -143,12 +134,6 @@ export default { return false; } } - }, - created: function() { - this.translation = window.translation[this.$route.name] - this.translation["high_msg"] = this.translation["high_msg"].replace("{nb}", this.nb_translate(this.alerts.high.length)) - this.translation["moderate_msg"] = this.translation["moderate_msg"].replace("{nb}", this.nb_translate(this.alerts.moderate.length)) - this.translation["low_msg"] = this.translation["low_msg"].replace("{nb}", this.nb_translate(this.alerts.low.length)) } } diff --git a/app/frontend/src/views/save-capture.vue b/app/frontend/src/views/save-capture.vue index 26cb79a..d94013d 100644 --- a/app/frontend/src/views/save-capture.vue +++ b/app/frontend/src/views/save-capture.vue @@ -6,14 +6,14 @@
-


{{ translation.please_connect }}

-


{{ translation.we_are_saving }}

-


{{ translation.tap_msg }}

+


{{ $t("save-capture.please_connect") }}

+


{{ $t("save-capture.we_are_saving") }}

+


{{ $t("save-capture.tap_msg") }}

-

{{ translation.catpure_download }}


- +

{{ $t("save-capture.capture_download") }}


+
@@ -175,28 +175,18 @@ export default { new_capture: function() { clearTimeout(this.timeout); router.push({ name: 'generate-ap' }) - }, - load_config: function() { - axios.get(`/api/misc/config`, { timeout: 60000 }) - .then(response => { - if(response.data.download_links){ - this.init = true - this.save_usb = false - this.download_url = `/api/save/save-capture/${this.capture_token}/url` - } else { - this.init = true - this.save_usb = true - this.interval = setInterval(() => { this.check_usb() }, 500); - } - }) - .catch(error => { - console.log(error) - }); } }, created: function() { - this.translation = window.translation[this.$route.name] - this.load_config() + if(window.config.download_links){ + this.init = true + this.save_usb = false + this.download_url = `/api/save/save-capture/${this.capture_token}/url` + } else { + this.init = true + this.save_usb = true + this.interval = setInterval(() => { this.check_usb() }, 500); + } } } \ No newline at end of file diff --git a/app/frontend/src/views/splash-screen.vue b/app/frontend/src/views/splash-screen.vue index a915982..bc76224 100644 --- a/app/frontend/src/views/splash-screen.vue +++ b/app/frontend/src/views/splash-screen.vue @@ -15,58 +15,34 @@ data() { return { list_ssids: [], - internet: false, - iface_out:"" + internet: false } }, methods: { - // Check if the device is connected to internet. internet_check: function() { - axios.get(`/api/network/status`, { timeout: 10000 }) + axios.get('/api/network/status', { timeout: 10000 }) .then(response => { - if (response.data.internet){ - this.internet = true - } - this.load_config() + if (response.data.internet) this.internet = true + if (window.config.iface_out.charAt(0) == 'e') { + setTimeout(function () { this.goto_home(); }.bind(this), 1000); + } else { + this.get_wifi_networks(); + } }) .catch(err => (console.log(err))) }, - // Get the WiFi networks around the box. get_wifi_networks: function() { - axios.get(`/api/network/wifi/list`, { timeout: 10000 }) + axios.get('/api/network/wifi/list', { timeout: 10000 }) .then(response => { this.list_ssids = response.data.networks this.goto_home(); }) .catch(err => (console.log(err))) }, - // Forward the view to home, with some props - // such as (SSIDs, internet & interface) goto_home: function() { var list_ssids = this.list_ssids var internet = this.internet - var iface_out = this.iface_out - router.replace({ name: 'home', params: { list_ssids: list_ssids, internet: internet, iface_out : iface_out } }); - }, - // Get the network_out from the config - // to determine the next steps. - load_config: function() { - axios.get(`/api/misc/config`, { timeout: 60000 }) - .then(response => { - if(response.data.iface_out){ - this.iface_out = response.data.iface_out - // If ethernet, just goto the homepage. - // Else, get wifi networks and then go to home. - if(this.iface_out.charAt(0) == "e"){ - setTimeout(function () { this.goto_home(); }.bind(this), 1000); - } else { - this.get_wifi_networks(); - } - } - }) - .catch(error => { - console.log(error) - }); + router.replace({ name: 'home', params: { list_ssids: list_ssids, internet: internet } }); } }, created: function() { diff --git a/app/frontend/src/views/wifi-select.vue b/app/frontend/src/views/wifi-select.vue index cc16eee..ce3fc1b 100644 --- a/app/frontend/src/views/wifi-select.vue +++ b/app/frontend/src/views/wifi-select.vue @@ -2,41 +2,42 @@
-

+

- +   +
-

{{ translation.not_connected }}
{{ translation.please_config }}

+

{{ $t("wifi-select.not_connected") }}
{{ $t("wifi-select.please_config") }}

- +
- +
@@ -63,7 +64,7 @@ export default { connecting: false, error: false, success: false, - btnval: "", + btnval: this.$t("wifi-select.connect_to_it"), ssid: "", selected_ssid: false, password: "", @@ -72,7 +73,6 @@ export default { ssids: [], have_internet: false, enter_creds: false, - virtual_keyboard: false, refreshing: false, translation: {} } @@ -84,15 +84,15 @@ export default { }, methods: { wifi_connect: function() { - axios.get(`/api/network/wifi/connect`, { timeout: 60000 }) + axios.get('/api/network/wifi/connect', { timeout: 60000 }) .then(response => { if (response.data.status) { this.success = true this.connecting = false - this.btnval = this.translation.wifi_connected + this.btnval = this.$t('wifi-select.wifi_connected') setTimeout(() => router.push('generate-ap'), 1000); } else { - this.btnval = this.translation["wifi_not_connected"] + this.btnval = this.$t('wifi-select.wifi_not_connected') this.connecting = false } }) @@ -102,7 +102,7 @@ export default { }, wifi_setup: function() { if (this.ssid.length && this.password.length >= 8 ){ - axios.post(`/api/network/wifi/setup`, { ssid: this.ssid, password: this.password }, { timeout: 60000 }) + axios.post('/api/network/wifi/setup', { ssid: this.ssid, password: this.password }, { timeout: 60000 }) .then(response => { if(response.data.status) { this.connecting = true @@ -116,15 +116,6 @@ export default { }); } }, - get_config: function() { - axios.get(`/api/misc/config`, { timeout: 60000 }) - .then(response => { - this.virtual_keyboard = response.data.virtual_keyboard - }) - .catch(error => { - console.log(error) - }); - }, onChange(input) { this.input = input this.password = this.input; @@ -141,25 +132,22 @@ export default { }, refresh_wifi_list: function(){ this.refreshing = true - axios.get(`/api/network/wifi/list`, { timeout: 10000 }) - .then(response => { - this.refreshing = false - this.append_ssids(response.data.networks) - }).catch(error => { - this.refreshing = false - console.log(error) + axios.get('/api/network/wifi/list', { timeout: 10000 }) + .then(response => { + this.refreshing = false + this.append_ssids(response.data.networks) + }).catch(error => { + this.refreshing = false + console.log(error) }); } }, created: function() { - this.translation = window.translation[this.$route.name] - this.btnval = this.translation.connect_to_it - this.get_config() this.have_internet = (this.internet) ? true : false this.keyboard = false - if (typeof this.list_ssids == "object" && this.list_ssids.length != 0){ + if (typeof this.list_ssids == 'object' && this.list_ssids.length != 0){ this.ssids = this.list_ssids } else { this.refresh_wifi_list() diff --git a/server/frontend/app/assets/lang/en.json b/server/frontend/app/assets/lang/en.json deleted file mode 100644 index 239008d..0000000 --- a/server/frontend/app/assets/lang/en.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "home": { - "welcome_msg": "Welcome to TinyCheck.", - "help_msg": "We are going to help you to check your device.", - "start_btn": "Let's start!" - }, - "analysis": { - "question": "Do you want to analyze the captured communications?", - "no_btn": "No, just save them", - "yes_btn": "Yes, let's do it", - "please_wait_msg": "Please wait during the analysis...", - "some_time_msg": "Yes, it can take some time..." - }, - "capture": { - "intercept_coms_msg": "Intercepting the communications of ", - "stop_btn": "Stop the capture" - }, - "generate-ap": { - "network_name": "Network name", - "network_password": "Network password", - "tap_msg": "Tap the white frame to generate a new network.", - "generate_ap_msg": "We generate an ephemeral network for you.", - "error_msg1": "Unfortunately, we got some issues
during the AP creation.", - "error_msg2": "Please verify that you've two WiFi interfaces on your device
and try again by restarting it.", - "restart_btn": "Restart the device" - }, - "report": { - "show_full_report": "Show the full report", - "start_new_capture": "Start a new capture", - "save_capture": "Save the capture", - "numbers": [ - "zero", - "one", - "two", - "three", - "four", - "five", - "six", - "seven", - "eight", - "nine", - "ten", - "eleven" - ], - "stalkerware_msg": "Your device is compromised by
a Stalkerware, please check the report.", - "location_msg": "An application is sharing your
current geolocation with a third party.", - "fine_msg": "Everything looks fine, zero alerts.", - "high_msg": "You have {nb} high alert,
your device seems to be compromised.", - "moderate_msg": "You have {nb} moderate alerts,
your device might be compromised.", - "low_msg": "You have only {nb} low alerts,
don't hesitate to check them.", - "save_report": "Save the report", - "report_of": "Report of", - "ip_address": "IP address", - "mac_address": "MAC address", - "high": "high", - "moderate": "moderate", - "low": "low" - }, - "wifi-select": { - "already_connected_question": "You seem to be already connected to a network.
Do you want to use the current connection?", - "no_btn": "No, use another", - "yes_btn": "Yes, use it.", - "wifi_name": "Wi-Fi name", - "refresh_btn": "Refresh networks list", - "not_connected": "You seem to not be connected to Internet.", - "please_config": "Please configure the Wi-Fi connection.", - "lets_do_btn": "Ok, let's do that.", - "wifi_connected": "Wi-Fi connected", - "wifi_not_connected": "Wi-Fi not connected. Please retry.", - "tap_keyboard": "Tap on the virtual keyboard to start", - "wifi_password": "Wi-Fi password", - "connect_to_it": "Connect to it" - }, - "save-capture": { - "please_connect": "Please connect a USB key to save your capture.", - "we_are_saving": "We are saving your capture.", - "tap_msg": "You can tap the USB key to start a new capture.", - "capture_download": "The capture download is going to start...", - "start_capture_btn": "Start another capture" - } -} \ No newline at end of file diff --git a/server/frontend/app/assets/lang/fr.json b/server/frontend/app/assets/lang/fr.json deleted file mode 100644 index cb03a14..0000000 --- a/server/frontend/app/assets/lang/fr.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "home": { - "welcome_msg": "Bienvenue sur TinyCheck.", - "help_msg": "Nous allons vous accompagner pour analyser votre appareil.", - "start_btn": "Allons-y !" - }, - "analysis": { - "question": "Voulez-vous analyser les communications capturées ?", - "no_btn": "Non, enregistrez-les.", - "yes_btn": "Oui, allons-y !", - "please_wait_msg": "Merci d'attendre pendant l'analyse...", - "some_time_msg": "Oui, cela peut prendre du temps..." - }, - "capture": { - "intercept_coms_msg": "Interception des communications de ", - "stop_btn": "Arrêter la capture" - }, - "generate-ap": { - "network_name": "Nom du réseau", - "network_password": "Mot de passe du réseau", - "tap_msg": "Appuyez sur le cadre blanc pour générer un nouveau réseau.", - "generate_ap_msg": "Nous générons un réseau Wi-Fi éphémère.", - "error_msg1": "Malheureusement, nous rencontrons des problèmes
lors de la création du point d'accès.", - "error_msg2": "Veuillez vérifier que vous disposez de
deux interfaces WiFi sur votre appareil.", - "restart_btn": "Restart the device" - }, - "report": { - "show_full_report": "Lire le rapport complet", - "start_new_capture": "Nouvelle capture", - "save_capture": "Sauvegarder", - "numbers": [ - "zéro", - "une", - "deux", - "trois", - "quatre", - "cinq", - "six", - "sept", - "huit", - "neuf", - "dix", - "onze" - ], - "stalkerware_msg": "Votre smartphone est compromis
par un Stalkerware, lisez le rapport.", - "location_msg": "Une application dévoile votre
géo-localisation actelle.", - "fine_msg": "Tout semble OK, vous avez aucue alerte.", - "high_msg": "Vous avez {nb} alerte(s) élevée(s),
votre appareil semble être compromis.", - "moderate_msg": "Vous avez {nb} alerte(s) moyenne(s),
votre appareil est peut-être compromis.", - "low_msg": "Vous avez uniquement {nb} alerte(s) basse(s)
n'hésitez pas à les lire.", - "save_report": "Sauvegarder le rapport", - "report_of": "Rapport de", - "ip_address": "Adresse IP :", - "mac_address": "Adresse MAC :", - "high": "elevee", - "moderate": "moyenne", - "low": "base" - }, - "wifi-select": { - "already_connected_question": "Vous semblez être connecté à un réseau.
Voulez-vous utiliser cette connexion ?", - "no_btn": "Non, une autre", - "yes_btn": "Oui, utilisez celle-là", - "wifi_name": "Nom du réseau", - "refresh_btn": "Rafraichir la liste des réseaux", - "not_connected": "Vous semblez ne pas être connecté à Internet.", - "please_config": "Configurez la connexion Wi-Fi.", - "lets_do_btn": "Oui, allons-y.", - "wifi_connected": "Wi-Fi connecté", - "wifi_not_connected": "Wi-Fi non connecté. Ressayez.", - "tap_keyboard": "Appuez sur cet espace pour écrire", - "wifi_password": "Mot de passe", - "connect_to_it": "Se connecter" - }, - "save-capture": { - "please_connect": "Connectez une clé USB pour enregistrer votre capture.", - "we_are_saving": "Nous enregistrons votre capture.", - "tap_msg": "Vous pouvez appuyer sur l'animation pour lancer une nouvelle capture.", - "capture_download": "Le téléchargement de la capture va se lancer...", - "start_capture_btn": "Lancer une nouvelle capture" - } -} \ No newline at end of file diff --git a/server/frontend/app/blueprints/misc.py b/server/frontend/app/blueprints/misc.py index 95c5c18..c9bbeed 100644 --- a/server/frontend/app/blueprints/misc.py +++ b/server/frontend/app/blueprints/misc.py @@ -13,8 +13,8 @@ misc_bp = Blueprint("misc", __name__) @misc_bp.route("/reboot", methods=["GET"]) def api_reboot(): - """ - Reboot the device + """ + Reboot the device """ if read_config(("frontend", "reboot_option")): sp.Popen("shutdown -r now", shell=True) @@ -25,8 +25,8 @@ def api_reboot(): @misc_bp.route("/quit", methods=["GET"]) def api_quit(): - """ - Quit the interface (Chromium browser) + """ + Quit the interface (Chromium browser) """ if read_config(("frontend", "quit_option")): sp.Popen('pkill -INT -f "chromium-browser"', shell=True) @@ -37,8 +37,8 @@ def api_quit(): @misc_bp.route("/shutdown", methods=["GET"]) def api_shutdown(): - """ - Reboot the device + """ + Reboot the device """ if read_config(("frontend", "shutdown_option")): sp.Popen("shutdown -h now", shell=True) @@ -49,8 +49,8 @@ def api_shutdown(): @misc_bp.route("/config", methods=["GET"]) def get_config(): - """ - Get configuration keys relative to the GUI + """ + Get configuration keys relative to the GUI """ return jsonify({ "virtual_keyboard": read_config(("frontend", "virtual_keyboard")), @@ -60,20 +60,6 @@ def get_config(): "quit_option": read_config(("frontend", "quit_option")), "shutdown_option": read_config(("frontend", "shutdown_option")), "reboot_option": read_config(("frontend", "reboot_option")), - "iface_out": read_config(("network", "out")) + "iface_out": read_config(("network", "out")), + "user_lang": read_config(("frontend", "user_lang")) }) - - -@misc_bp.route("/get-lang", methods=["GET"]) -def get_lang(): - """ - Get the user lang defined in the config.yaml - and retrieve the interface translation. - """ - lang = read_config(("frontend", "user_lang")) - if re.match("^[a-z]{2,3}$", lang): - with open(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "app/assets/lang/{}.json".format(lang)), "r") as f: - return(f.read()) - else: - with open(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "app/assets/lang/en.json"), "r") as f: - return(f.read())