summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsegfault <segfault@riseup.net>2019-09-30 23:14:53 +0200
committersegfault <segfault@riseup.net>2019-10-01 23:40:20 +0200
commitde5b80128f30eda27529bc880dc9ba19d8648c92 (patch)
tree710723ded81229f32b9aab0590d242df39822c02
parent99e5d9b31832ea8ca7f940cecb02dda3f1d1b32c (diff)
More refactoring (refs: #17098)wip/feature/17098-refactor-greeter
-rwxr-xr-xbin/delete-merged-git-branches2
-rwxr-xr-xconfig/chroot_local-includes/etc/gdm3/PostLogin/Default1
-rw-r--r--config/chroot_local-includes/etc/whisperback/debugging-info.json3
-rw-r--r--config/chroot_local-includes/lib/systemd/system/tails-unblock-network.service13
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/config.py13
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/greeter.py138
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/admin.py34
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/formats.py114
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/keyboard.py80
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/language.py123
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization.py53
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization_settings.py87
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/macspoof.py19
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/network.py23
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/physicalsecurity.py69
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/rootaccess.py62
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/translatable_window.py24
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py45
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/main_window.py8
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py12
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/settings_collection.py4
-rw-r--r--config/chroot_local-includes/usr/lib/python3/dist-packages/tailslib/additionalsoftware.py2
-rwxr-xr-xconfig/chroot_local-includes/usr/local/lib/onion-grater4
-rwxr-xr-xconfig/chroot_local-includes/usr/local/lib/tails-additional-software-notify6
-rwxr-xr-xconfig/chroot_local-includes/usr/local/lib/tails-autotest-remote-shell4
-rw-r--r--config/chroot_local-includes/usr/local/lib/tails-shell-library/tails-greeter.sh13
-rwxr-xr-xconfig/chroot_local-includes/usr/local/lib/tails-unblock-network2
-rwxr-xr-xconfig/chroot_local-includes/usr/local/sbin/tails-additional-software4
-rwxr-xr-xconfig/chroot_local-includes/usr/local/sbin/tails-debugging-info4
-rw-r--r--config/chroot_local-includes/usr/share/tails/greeter/locales (renamed from config/chroot_local-includes/usr/share/tails/greeter/language_codes)0
-rwxr-xr-xconfig/chroot_local-includes/usr/share/tails/greeter/tails-greeter.py140
31 files changed, 520 insertions, 586 deletions
diff --git a/bin/delete-merged-git-branches b/bin/delete-merged-git-branches
index 03ea380..d2e2036 100755
--- a/bin/delete-merged-git-branches
+++ b/bin/delete-merged-git-branches
@@ -15,7 +15,7 @@ def yes_no_input(prompt, default=True):
options = 'Y/n'
else:
options = 'N/y'
- sys.stdout.write('%s [%s] ' % (prompt, options))
+ sys.stdout.apply_to_upcoming_session('%s [%s] ' % (prompt, options))
while True:
answer = input().lower()
if len(answer) == 0:
diff --git a/config/chroot_local-includes/etc/gdm3/PostLogin/Default b/config/chroot_local-includes/etc/gdm3/PostLogin/Default
index 0722b7e..a3fe997 100755
--- a/config/chroot_local-includes/etc/gdm3/PostLogin/Default
+++ b/config/chroot_local-includes/etc/gdm3/PostLogin/Default
@@ -10,7 +10,6 @@
# * /var/lib/gdm3/tails.locale : $TAILS_LOCALE_NAME, $TAILS_XKBMODEL,
# $TAILS_XKBLAYOUT, $TAILS_XKBVARIANT, $TAILS_XKBOPTIONS, $CODESET
# * /var/lib/gdm3/tails.password : $TAILS_USER_PASSWORD
-# * /var/lib/gdm3/tails.physical_security : $TAILS_MACSPOOF_ENABLED
# For whatever reason, /usr/sbin (needed by at least chpasswd)
# is not in our PATH
diff --git a/config/chroot_local-includes/etc/whisperback/debugging-info.json b/config/chroot_local-includes/etc/whisperback/debugging-info.json
index 35903bc..b9c451a 100644
--- a/config/chroot_local-includes/etc/whisperback/debugging-info.json
+++ b/config/chroot_local-includes/etc/whisperback/debugging-info.json
@@ -16,7 +16,8 @@
["file", {"user": "Debian-gdm", "path": "/var/log/gdm3/tails-greeter.errors"}],
["file", {"user": "root", "path": "/var/log/live/boot.log"}],
["file", {"user": "root", "path": "/var/log/live/config.log"}],
-["file", {"user": "root", "path": "/var/lib/live/config/tails.physical_security"}],
+["file", {"user": "root", "path": "/var/lib/live/config/tails.macspoof"}],
+["file", {"user": "root", "path": "/var/lib/live/config/tails.network"}],
["file", {"user": "root", "path": "/var/lib/live/config/tails.persistence"}],
["file", {"user": "tails-persistence-setup", "path": "/live/persistence/TailsData_unlocked/persistence.conf"}],
["file", {"user": "tails-persistence-setup", "path": "/live/persistence/TailsData_unlocked/live-additional-software.conf"}],
diff --git a/config/chroot_local-includes/lib/systemd/system/tails-unblock-network.service b/config/chroot_local-includes/lib/systemd/system/tails-unblock-network.service
index e8feaca..eab9902 100644
--- a/config/chroot_local-includes/lib/systemd/system/tails-unblock-network.service
+++ b/config/chroot_local-includes/lib/systemd/system/tails-unblock-network.service
@@ -5,15 +5,18 @@ Documentation=https://tails.boum.org/contribute/design/MAC_address/
[Service]
Type=oneshot
RemainAfterExit=yes
-EnvironmentFile=/var/lib/gdm3/tails.physical_security
+EnvironmentFile=/var/lib/gdm3/tails.network
-# It's important we "export" the settings from tails.physical_security
-# before unblocking the network; doing so will make the user-set MAC spoofing
+# It's important we "export" the settings from tails.macspoof before
+# unblocking the network; doing so will make the user-set MAC spoofing
# option apply (via the custom udev rule) when loading the modules for the
# previously blocked network devices.
ExecStartPre=/usr/bin/install -m 0640 -o root -g root \
- /var/lib/gdm3/tails.physical_security \
- /var/lib/live/config/tails.physical_security
+ /var/lib/gdm3/tails.macspoof \
+ /var/lib/live/config/tails.macspoof && \
+ /usr/bin/install -m 0640 -o root -g root \
+ /var/lib/gdm3/tails.network \
+ /var/lib/live/config/tails.network
ExecStartPre=/bin/sync
ExecStartPre=/bin/sh -c \
'if [ "${TAILS_NETCONF}" = "obstacle" ] ; then \
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/config.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/config.py
index 8c7fe3b..3e63b1d 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/config.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/config.py
@@ -27,19 +27,22 @@ LUSER = 'amnesia'
data_path = '/usr/share/tails/greeter/'
# File containing the language codes that are supported by the greeter
-language_codes_path = os.path.join(data_path, 'language_codes')
+locales_path = os.path.join(data_path, 'locales')
# Locales path
-locales_path = '/usr/share/locale/'
+system_locale_dir = '/usr/share/locale/'
# File where session locale settings are stored
locale_output_path = '/var/lib/gdm3/tails.locale'
# File where the session sudo password is stored
-rootpassword_output_path = '/var/lib/gdm3/tails.password'
+admin_password_output_path = '/var/lib/gdm3/tails.password'
# World-readable file where Tails persistence status is stored
persistence_state_file = '/var/lib/live/config/tails.persistence'
-# File where settings related to physical security are stored
-physical_security_settings = '/var/lib/gdm3/tails.physical_security'
+# File where the network setting is stored
+network_setting = '/var/lib/gdm3/tails.network'
+
+# File where the MAC address spoofing setting is stored
+macspoof_setting = '/var/lib/gdm3/tails.macspoof'
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/greeter.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/greeter.py
new file mode 100644
index 0000000..a09ccc7
--- /dev/null
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/greeter.py
@@ -0,0 +1,138 @@
+#!/usr/bin/python3
+#
+# Copyright 2012-2019 Tails developers <tails@boum.org>
+# Copyright 2011 Max <govnototalitarizm@gmail.com>
+# Copyright 2011 Martin Owens
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>
+#
+
+import gi
+import logging
+
+from tailsgreeter.gdmclient import GdmClient
+from tailsgreeter.settings import localization
+from tailsgreeter.settings.admin import AdminSetting
+from tailsgreeter.settings.localization_settings import LocalisationSettings
+from tailsgreeter.settings.macspoof import MacSpoofSetting
+from tailsgreeter.settings.network import NetworkSetting
+from tailsgreeter.settings.persistence import PersistenceSettings
+from tailsgreeter.translatable_window import TranslatableWindow
+from tailsgreeter.ui.additional_settings import AdminSettingUI, MACSpoofSettingUI, NetworkSettingUI
+from tailsgreeter.ui.main_window import GreeterMainWindow
+from tailsgreeter.ui.region_settings import LanguageSettingUI, KeyboardSettingUI, FormatsSettingUI
+from tailsgreeter.ui.settings_collection import GreeterSettingsCollection
+
+gi.require_version('Gio', '2.0')
+from gi.repository import Gio
+
+
+class GreeterApplication():
+ """Tails greeter main controller
+
+ This class is the greeter dbus service"""
+
+ def __init__(self):
+ self.session = None
+ self.forced = False
+ self.postponed = False
+ self.postponed_text = None
+ self.ready = False
+ self.translated = False
+
+ self._sessionmanager = Gio.DBusProxy.new_for_bus_sync(
+ Gio.BusType.SESSION,
+ Gio.DBusProxyFlags.NONE,
+ None,
+ "org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ "org.gnome.SessionManager")
+
+ # Load models
+ self.gdmclient = GdmClient(session_opened_cb=self.close_app)
+
+ persistence = PersistenceSettings()
+ self.localisationsettings = LocalisationSettings(
+ usermanager_loaded_cb=self.usermanager_loaded,
+ locale_selected_cb=self.on_language_changed
+ )
+ self.admin_setting = AdminSetting()
+ self.network_setting = NetworkSetting()
+ self.macspoof_setting = MacSpoofSetting()
+
+ # Initialize the settings
+ settings = GreeterSettingsCollection(
+ LanguageSettingUI(self.localisationsettings.language),
+ KeyboardSettingUI(self.localisationsettings.keyboard),
+ FormatsSettingUI(self.localisationsettings.formats),
+ AdminSettingUI(self.admin_setting),
+ MACSpoofSettingUI(self.macspoof_setting),
+ NetworkSettingUI(self.network_setting),
+ )
+
+ # Initialize main window
+ self.mainwindow = GreeterMainWindow(self, persistence, settings)
+
+ # Inhibit the session being marked as idle
+ self.inhibit_idle()
+
+ def translate_to(self, lang):
+ """Translate all windows to target language"""
+ TranslatableWindow.translate_all(lang)
+
+ def login(self):
+ """Login GDM to the server"""
+ logging.debug("login called")
+
+ # Apply settings
+ self.localisationsettings.apply_to_upcoming_session()
+ self.admin_setting.apply_to_upcoming_session()
+ self.macspoof_setting.apply_to_upcoming_session()
+ self.network_setting.apply_to_upcoming_session()
+
+ self.mainwindow.hide()
+ self.gdmclient.do_login()
+
+ def usermanager_loaded(self):
+ """UserManager is ready"""
+ logging.debug("Entering usermanager_loaded")
+ self.ready = True
+ logging.info("tails-greeter is ready.")
+ self.mainwindow.show()
+
+ def on_language_changed(self, locale_code: str):
+ """Translate to the given locale"""
+ self.localisationsettings.formats.on_language_changed(locale_code) # XXX: notify
+ self.localisationsettings.keyboard.on_language_changed(locale_code) # XXX: notify
+ self.translate_to(locale_code)
+ self.mainwindow.current_language = localization.language_from_locale(locale_code)
+
+ def close_app(self):
+ """We're done, quit gtk app"""
+ logging.info("Finished.")
+ Gtk.main_quit()
+
+ def shutdown(self):
+ """Shuts down the computer using GNOME Session Manager"""
+ logging.info("Shutdown")
+ self._sessionmanager.Shutdown()
+
+ def inhibit_idle(self):
+ cookie = self._sessionmanager.Inhibit(
+ "(susu)",
+ "org.boum.tails.Greeter",
+ 0,
+ "Greeter session shouldn't idle",
+ 8) # Inhibit the session being marked as idle
+ logging.debug("inhibitor cookie=%i", cookie)
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/admin.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/admin.py
new file mode 100644
index 0000000..ae85d34
--- /dev/null
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/admin.py
@@ -0,0 +1,34 @@
+
+import os
+import os.path
+import logging
+import pipes
+
+import tailsgreeter.config
+
+
+class AdminSetting(object):
+ """Setting controlling the sudo password"""
+
+ def __init__(self):
+ self.password = None
+
+ def apply_to_upcoming_session(self):
+ setting_file = tailsgreeter.config.admin_password_output_path
+
+ if self.password:
+ with open(setting_file, 'w') as f:
+ os.chmod(setting_file, 0o600)
+ f.write('TAILS_USER_PASSWORD=%s\n' % pipes.quote(self.password))
+ logging.debug('password written to %s', setting_file)
+ return
+
+ # Try to remove the password file
+ try:
+ os.unlink(setting_file)
+ logging.debug('removed %s', setting_file)
+ except OSError:
+ # It's bad if the file exists and couldn't be removed, so we
+ # we raise the exception in that case (which prevents the login)
+ if os.path.exists(setting_file):
+ raise
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/formats.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/formats.py
index 02f03f6..b7d3e7a 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/formats.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/formats.py
@@ -1,65 +1,50 @@
import logging
-from typing import TYPE_CHECKING
import gi
-from tailsgreeter.settings.localization import LocalizationSetting, language_from_locale, country_from_locale, \
- countries_from_locales
+from tailsgreeter.settings.localization import LocalizationSetting, language_from_locale, country_from_locale
gi.require_version('GObject', '2.0')
gi.require_version('GnomeDesktop', '3.0')
gi.require_version('Gtk', '3.0')
from gi.repository import GObject, GnomeDesktop, Gtk
-if TYPE_CHECKING:
- from tailsgreeter.settings.localization_settings import LocalisationSettings
-
class FormatsSetting(LocalizationSetting):
- def __init__(self, settings_object: "LocalisationSettings"):
- super().__init__(settings_object)
- super().set_value('en_US', is_default=True)
+ def __init__(self, language_codes: [str]):
+ super().__init__()
+ self.value = 'en_US'
+ self.locales_per_country = self._make_locales_per_country_dict(language_codes)
- def get_tree(self):
+ def get_tree(self) -> Gtk.TreeStore:
treestore = Gtk.TreeStore(GObject.TYPE_STRING, # id
GObject.TYPE_STRING) # name
- format_codes = countries_from_locales(
- self._settings.system_locales_list)
- format_codes.sort(key=lambda x: self._country_name(x).lower())
- logging.debug("format_codes=%s", format_codes)
- for format_code in format_codes:
- format_name = self._country_name(format_code)
- if not format_name:
+ country_codes = list(self.locales_per_country.keys())
+ country_codes.sort(key=lambda x: self._country_name(x).lower())
+ logging.debug("format_codes=%s", country_codes)
+ for country_code in country_codes:
+ country_name = self._country_name(country_code)
+ if not country_name:
# Don't display languages without a name
continue
+
treeiter_format = treestore.append(parent=None)
- treestore.set(treeiter_format,
- 0, self.get_default_locale(format_code))
- treestore.set(treeiter_format, 1, format_name)
- locale_codes = sorted(
- self.get_default_locales(format_code),
- key=lambda x: self._locale_name(x).lower())
- if len(locale_codes) > 1:
- for locale_code in locale_codes:
- treeiter_locale = treestore.append(
- parent=treeiter_format)
- treestore.set(treeiter_locale, 0, locale_code)
- treestore.set(treeiter_locale, 1,
- self._locale_name(locale_code))
+ treestore.set(treeiter_format, 0, self.get_default_locale(country_code))
+ treestore.set(treeiter_format, 1, country_name)
+ locales = sorted(self.locales_per_country[country_code],
+ key=lambda x: self._locale_name(x).lower())
+ if len(locales) > 1:
+ for locale in locales:
+ treeiter_locale = treestore.append(parent=treeiter_format)
+ treestore.set(treeiter_locale, 0, locale)
+ treestore.set(treeiter_locale, 1, self._locale_name(locale))
return treestore
- def get_name(self):
+ def get_name(self) -> str:
return self._locale_name(self.get_value())
- def get_default_locales(self, country_code):
- """Return available locales for given country
-
- """
- if country_code in self._settings.system_formats_dict:
- return self._settings.system_formats_dict[country_code]
-
- def get_default_locale(self, country_code=None):
+ def get_default_locale(self, country_code=None) -> str:
"""Return default locale for given country
Returns the 1st locale among:
@@ -67,17 +52,18 @@ class FormatsSetting(LocalizationSetting):
- the 1st locale for the language
- en_US
"""
- default_locales = self.get_default_locales(country_code)
- if default_locales:
- for locale_code in default_locales:
- if (country_from_locale(locale_code).lower() ==
- language_from_locale(locale_code)):
- return locale_code
- return default_locales[0]
- else:
+ locales = self.locales_per_country[country_code]
+ if not locales:
return 'en_US'
- def _country_name(self, country_code):
+ # Get the default locale for the country
+ for locale_code in locales:
+ if country_from_locale(locale_code).lower() == language_from_locale(locale_code):
+ return locale_code
+
+ return locales[0]
+
+ def _country_name(self, country_code) -> str:
default_locale = 'C'
local_locale = self.get_default_locale(country_code)
native_name = GnomeDesktop.get_country_from_code(
@@ -93,7 +79,7 @@ class FormatsSetting(LocalizationSetting):
native=native_name, localized=localized_name)
@staticmethod
- def _locale_name(locale_code):
+ def _locale_name(locale_code) -> str:
lang_code = language_from_locale(locale_code)
country_code = country_from_locale(locale_code)
language_name_locale = GnomeDesktop.get_language_from_code(lang_code)
@@ -118,11 +104,25 @@ class FormatsSetting(LocalizationSetting):
except AttributeError:
return locale_code
- def set_default(self):
- """Set default format for current language
-
- Select the same locale for formats that the language
- """
- default_format = self._settings.language.get_value()
- logging.debug("setting default formats to %s", default_format)
- self.set_value(default_format, is_default=True)
+ @staticmethod
+ def _make_locales_per_country_dict(language_codes: [str]) -> {str: [str]}:
+ """assemble dictionary of country codes to corresponding locales list
+
+ example {FR: [fr_FR, en_FR], ...}"""
+ res = {}
+ for language_code in language_codes:
+ country_code = country_from_locale(language_code)
+ if country_code not in res:
+ res[country_code] = []
+ if language_code not in res[country_code]:
+ res[country_code].append(language_code)
+ return res
+
+ def on_language_changed(self, language_code: str):
+ """Set the formats according to the new language"""
+ # Don't overwrite user chosen values
+ if self.value_changed_by_user:
+ return
+
+ logging.debug("setting formats to %s", language_code)
+ self.set_value(language_code)
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/keyboard.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/keyboard.py
index 65de965..5118f00 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/keyboard.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/keyboard.py
@@ -14,10 +14,10 @@ from gi.repository import Gio, GLib, GnomeDesktop, GObject, Gtk
class KeyboardSetting(LocalizationSetting):
- def __init__(self, settings_object):
- super().__init__(settings_object)
+ def __init__(self):
+ super().__init__()
self.xkbinfo = GnomeDesktop.XkbInfo()
- super().set_value('us', is_default=True)
+ self.value = 'us'
def get_tree(self, layout_codes=None):
if not layout_codes:
@@ -27,9 +27,8 @@ class KeyboardSetting(LocalizationSetting):
GObject.TYPE_STRING) # name
layouts = self._layouts_split_names(layout_codes)
for group_name in sorted(layouts.keys()):
- layout_codes = sorted(
- layouts[group_name],
- key=lambda x: self._layout_name(x).lower())
+ layout_codes = sorted(layouts[group_name],
+ key=lambda x: self._layout_name(x).lower())
treeiter_group = treestore.append(parent=None)
# we fill the title with the 1st layout of the group
treestore.set(treeiter_group, 0, layout_codes[0])
@@ -38,8 +37,7 @@ class KeyboardSetting(LocalizationSetting):
for layout_code in layout_codes:
treeiter_layout = treestore.append(parent=treeiter_group)
treestore.set(treeiter_layout, 0, layout_code)
- treestore.set(treeiter_layout, 1,
- self._layout_name(layout_code))
+ treestore.set(treeiter_layout, 1, self._layout_name(layout_code))
return treestore
def get_name(self):
@@ -51,21 +49,9 @@ class KeyboardSetting(LocalizationSetting):
"""
return self.xkbinfo.get_all_layouts()
- def get_defaults(self):
- """Return list of supported keyboard layouts for current language
-
- """
- lang_code = language_from_locale(self._settings.language.get_value())
- layouts = self._layouts_for_language(lang_code)
- if not layouts:
- country_code = country_from_locale(self._settings.language.get_value())
- layouts = self._layouts_for_country(country_code)
- if not layouts:
- layouts = ['us']
- return layouts
-
- def set_value(self, layout, is_default=False):
- super().set_value(layout, is_default)
+ def set_value(self, layout, chosen_by_user=False):
+ super().set_value(layout)
+ self.value_changed_by_user = chosen_by_user
self._apply_layout_to_current_screen()
def _layout_name(self, layout_code):
@@ -86,8 +72,8 @@ class KeyboardSetting(LocalizationSetting):
layouts_names[country_name].add(layout_code)
return layouts_names
- def _layouts_for_language(self, lang_code):
- """Return the list of available layouts for given language
+ def _layouts_for_language(self, lang_code) -> {str}:
+ """Return the set of available layouts for given language
"""
try:
t_code = ln_iso639_tri(lang_code)
@@ -111,10 +97,10 @@ class KeyboardSetting(LocalizationSetting):
layouts = self.xkbinfo.get_layouts_for_language(b_code)
logging.debug('got %d layouts for %s', len(layouts), lang_code)
- return layouts
+ return set(layouts)
- def _layouts_for_country(self, country):
- """Return the list of available layouts for given country
+ def _layouts_for_country(self, country) -> {str}:
+ """Return the set of available layouts for given country
"""
# XXX: it would be logical to use:
# self.__xklinfo.get_layouts_for_language(country)
@@ -122,8 +108,7 @@ class KeyboardSetting(LocalizationSetting):
# country.
def country_filter(layout):
cc = country.lower()
- return ((layout == cc)
- or ('+' in layout) and (layout.split('+')[0] == cc))
+ return (layout == cc) or ('+' in layout) and (layout.split('+')[0] == cc)
layouts = list(filter(country_filter, self.get_all()))
@@ -168,35 +153,34 @@ class KeyboardSetting(LocalizationSetting):
layouts = filtered_layouts
return layouts
- def set_default(self):
- """Sets the best default layout for the current locale
- """
- language = language_from_locale(self._settings.language.get_value())
- country = country_from_locale(self._settings.language.get_value())
+ def on_language_changed(self, locale: str):
+ """Set the keyboard layout according to the new language"""
+
+ # Don't overwrite a user chosen value
+ if self.value_changed_by_user:
+ return
+
+ language = language_from_locale(locale)
+ country = country_from_locale(locale)
# First, build a list of layouts to consider for the language
language_layouts = self._layouts_for_language(language)
logging.debug("Language %s layouts: %s", language, language_layouts)
country_layouts = self._layouts_for_country(country)
logging.debug("Country %s layouts: %s", country, country_layouts)
- layouts = set(language_layouts).intersection(country_layouts)
+ layouts = language_layouts.intersection(country_layouts)
logging.debug("Intersection of language %s and country %s: %s",
language, country, layouts)
- if not len(layouts) > 0:
- def country_filter(layout):
- layout_name, layout_variant = self._split_variant(layout)
- return layout_name == country.lower()
- layouts = list(filter(country_filter, language_layouts))
+
+ if not layouts:
+ layouts = set(l for l in language_layouts if self._split_variant(l)[0] == country.lower)
logging.debug("Empty intersection of language and country, filter "
"by country %s only: %s", country, layouts)
- if not len(layouts) > 0:
- def language_filter(layout):
- layout_name, layout_variant = self._split_variant(layout)
- return layout_name == language
- layouts = list(filter(language_filter, language_layouts))
+ if not layouts:
+ layouts = set(l for l in language_layouts if self._split_variant(l)[0] == language)
logging.debug("List still empty, filter by language %s only: %s",
language, layouts)
- if not len(layouts) > 0:
+ if not layouts:
layouts = language_layouts
logging.debug("List still empty, use all language %s layouts: %s",
language, layouts)
@@ -220,7 +204,7 @@ class KeyboardSetting(LocalizationSetting):
else:
default_layout = 'us'
logging.debug("Using us as fallback default layout")
- self.set_value(default_layout, is_default=True)
+ self.set_value(default_layout)
def _apply_layout_to_current_screen(self):
layout = self.get_value()
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/language.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/language.py
index f2f9409..ca57785 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/language.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/language.py
@@ -20,6 +20,7 @@
import gi
import logging
import locale
+from typing import Callable
from tailsgreeter.settings.localization import LocalizationSetting, \
language_from_locale, languages_from_locales, country_from_locale
@@ -33,16 +34,19 @@ from gi.repository import GLib, GObject, GnomeDesktop, Gtk
class LanguageSetting(LocalizationSetting):
- def __init__(self, settings_object):
- super().__init__(settings_object)
- super().set_value('en_US', is_default=True)
+ def __init__(self, locales: [str], language_changed_cb: Callable):
+ super().__init__()
+ self.value = 'en_US'
+ self.locales = locales
+ self.language_changed_cb = language_changed_cb
+ self._user_account = None
+ self.locales_per_language = self._make_language_to_locale_dict(locales)
- def get_tree(self):
+ def get_tree(self) -> Gtk.TreeStore:
treestore = Gtk.TreeStore(GObject.TYPE_STRING, # id
GObject.TYPE_STRING) # name
- lang_codes = languages_from_locales(
- self._settings.system_locales_list)
+ lang_codes = languages_from_locales(self.locales)
lang_codes.sort(key=lambda x: self._language_name(x).lower())
for lang_code in lang_codes:
language_name = self._language_name(lang_code)
@@ -50,58 +54,46 @@ class LanguageSetting(LocalizationSetting):
# Don't display languages without a name
continue
treeiter_language = treestore.append(parent=None)
- treestore.set(treeiter_language,
- 0, self.get_default_locale(lang_code))
+ treestore.set(treeiter_language, 0, self.get_default_locale(lang_code))
treestore.set(treeiter_language, 1, language_name)
- locale_codes = sorted(
- self.get_default_locales(lang_code),
- key=lambda x: self._locale_name(x).lower())
- if len(locale_codes) > 1:
- for locale_code in locale_codes:
- treeiter_locale = treestore.append(
- parent=treeiter_language)
+ locales = sorted(self.locales_per_language[lang_code],
+ key=lambda x: self._locale_name(x).lower())
+ if len(locales) > 1:
+ for locale_code in locales:
+ treeiter_locale = treestore.append(parent=treeiter_language)
treestore.set(treeiter_locale, 0, locale_code)
- treestore.set(treeiter_locale, 1,
- self._locale_name(locale_code))
+ treestore.set(treeiter_locale, 1, self._locale_name(locale_code))
return treestore
- def get_name(self):
+ def get_name(self) -> str:
return self._locale_name(self.get_value())
- def get_default_locales(self, lang_code):
- """Return available locales for given language
-
- """
- if lang_code in self._settings._system_languages_dict:
- return self._settings._system_languages_dict[lang_code]
-
- def get_default_locale(self, lang_code=None):
- """Return default locale for given language
-
- Returns the 1st locale among:
- - the locale whose country name matches language name
- - the 1st locale for the language
- - en_US
- """
- default_locales = self.get_default_locales(lang_code)
- if default_locales:
- for locale_code in default_locales:
- if (country_from_locale(locale_code).lower() ==
- language_from_locale(locale_code)):
- return locale_code
- return default_locales[0]
- else:
+ def get_default_locale(self, lang_code=None) -> str:
+ """Try to find a default locale for the given language"""
+ locales = self.locales_per_language[lang_code]
+ if not locales:
return 'en_US'
- def set_value(self, locale, is_default=False):
- super().set_value(locale, is_default)
- self.__apply_locale()
- self._settings.formats.set_default_if_needed() # XXX: notify
- self._settings.keyboard.set_default_if_needed() # XXX: notify
- if self._settings._locale_selected_cb:
- self._settings._locale_selected_cb(locale)
+ # Try using the default locale for the language as chosen by locale.normalize
+ default_locale = locale.normalize(lang_code).split('.')[0]
+ if default_locale in locales:
+ return default_locale
+
+ # Try using the locale with the same country code as the language code
+ for locale_code in locales:
+ if (country_from_locale(locale_code).lower() ==
+ language_from_locale(locale_code)):
+ return locale_code
+
+ # None above worked, so just return the first locale in our list
+ return locales[0]
- def _language_name(self, lang_code):
+ def set_value(self, locale_code: str, chosen_by_user=False):
+ super().set_value(locale_code, chosen_by_user)
+ self._apply_language(locale_code)
+ self.language_changed_cb(locale_code)
+
+ def _language_name(self, lang_code) -> str:
default_locale = 'C'
local_locale = self.get_default_locale(lang_code)
try:
@@ -117,7 +109,8 @@ class LanguageSetting(LocalizationSetting):
return "{native} ({localized})".format(
native=native_name, localized=localized_name)
- def _locale_name(self, locale_code):
+ @staticmethod
+ def _locale_name(locale_code) -> str:
lang_code = language_from_locale(locale_code)
country_code = country_from_locale(locale_code)
language_name_locale = GnomeDesktop.get_language_from_code(lang_code)
@@ -142,12 +135,28 @@ class LanguageSetting(LocalizationSetting):
except AttributeError:
return locale_code
- def __apply_locale(self):
- locale_code = locale.normalize(
- self.get_value() + '.' + locale.getpreferredencoding())
- logging.debug("Setting session language to %s", locale_code)
- if self._settings._act_user:
- GLib.idle_add(
- lambda: self._settings._act_user.set_language(locale_code))
+ def _apply_language(self, language_code):
+ normalized_code = locale.normalize(language_code + '.' + locale.getpreferredencoding())
+ logging.debug("Setting session language to %s", normalized_code)
+ if self._user_account:
+ # For some reason, this produces the following warning, but
+ # the language is actually applied.
+ # AccountsService-WARNING **: 19:29:39.181: SetLanguage for language de_DE.UTF-8 failed:
+ # GDBus.Error:org.freedesktop.Accounts.Error.PermissionDenied: Not authorized
+ GLib.idle_add(lambda: self._user_account.set_language(normalized_code))
else:
logging.warning("AccountsManager not ready")
+
+ @staticmethod
+ def _make_language_to_locale_dict(locale_codes):
+ """assemble dictionary of language codes to corresponding locales list
+
+ example {en: [en_US, en_GB], ...}"""
+ languages_dict = {}
+ for locale_code in locale_codes:
+ lang_code = language_from_locale(locale_code)
+ if lang_code not in languages_dict:
+ languages_dict[lang_code] = []
+ if locale_code not in languages_dict[lang_code]:
+ languages_dict[lang_code].append(locale_code)
+ return languages_dict
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization.py
index 665d551..b8d6313 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization.py
@@ -19,48 +19,31 @@
import gi
import pycountry
-from typing import TYPE_CHECKING
gi.require_version('GObject', '2.0')
from gi.repository import GObject
-if TYPE_CHECKING:
- from tailsgreeter.settings.localization_settings import LocalisationSettings
+class LocalizationSetting(GObject.Object, object):
-class LocalizationSetting(GObject.Object):
+ def __init__(self):
+ GObject.Object.__init__(self)
+ self.value = ""
+ self.value_changed_by_user = False
- value = GObject.property(type=str)
- is_default = GObject.property(type=bool, default=True)
-
- def __init__(self, settings_object: "LocalisationSettings"):
- super().__init__()
- self._settings = settings_object
-
- def get_value(self):
+ def get_value(self) -> str:
return self.value
- # is_default will be used by subclasses to register default value
- def set_value(self, value, is_default=False):
+ def set_value(self, value, chosen_by_user=False):
self.value = value
- if not is_default:
- self.is_default = False
- self._settings.apply_settings_to_upcoming_session()
+ self.value_changed_by_user = chosen_by_user
- def get_name(self):
+ def get_name(self) -> str:
raise NotImplementedError
- def get_tree(self):
+ def get_tree(self) -> str:
raise NotImplementedError
- def set_default(self):
- raise NotImplementedError
-
- def set_default_if_needed(self):
- """Update default value if it was not user choosen"""
- if self.is_default:
- self.set_default()
-
def ln_iso639_tri(ln_CC):
"""get iso639 3-letter code from a language code
@@ -87,12 +70,7 @@ def languages_from_locales(locales):
"""Obtain a language code list from a locale code list
example: [fr_FR, en_GB] -> [fr, en]"""
- language_codes = []
- for l in locales:
- language_code = language_from_locale(l)
- if language_code not in language_codes:
- language_codes.append(language_code)
- return language_codes
+ return list({language_from_locale(l) for l in locales})
def country_from_locale(locale):
@@ -102,13 +80,8 @@ def country_from_locale(locale):
return locale.split('_')[1]
-def countries_from_locales(locales):
+def countries_from_locales(locales) -> [str]:
"""Obtain a country code list from a locale code list
example: [fr_FR, en_GB] -> [FR, GB]"""
- country_codes = []
- for l in locales:
- country_code = country_from_locale(l)
- if country_code not in country_codes:
- country_codes.append(country_code)
- return country_codes
+ return list({country_from_locale(l) for l in locales})
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization_settings.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization_settings.py
index 0f15c20..9f47318 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization_settings.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/localization_settings.py
@@ -1,9 +1,9 @@
import gi
import logging
import os
+from typing import Callable
import tailsgreeter.config
-from tailsgreeter.settings.localization import language_from_locale, country_from_locale
from tailsgreeter.settings.formats import FormatsSetting
from tailsgreeter.settings.keyboard import KeyboardSetting
from tailsgreeter.settings.language import LanguageSetting
@@ -16,88 +16,55 @@ class LocalisationSettings(object):
"""Controller for localisation settings
"""
- def __init__(self, usermanager_loaded_cb=None, locale_selected_cb=None):
+ def __init__(self, usermanager_loaded_cb: Callable, locale_selected_cb: Callable):
self._usermanager_loaded_cb = usermanager_loaded_cb
- self._locale_selected_cb = locale_selected_cb
- self._act_user = None
+ self._user_account = None
self._actusermanager_loadedid = None
- self.system_locales_list = self.__get_langcodes()
- self._system_languages_dict = self.__fill_languages_dict(
- self.system_locales_list)
- self.system_formats_dict = self.__fill_formats_dict(
- self.system_locales_list)
+ locales = self._get_locales()
self._actusermanager = AccountsService.UserManager.get_default()
self._actusermanager_loadedid = self._actusermanager.connect(
"notify::is-loaded", self.__on_usermanager_loaded)
- self.language = LanguageSetting(self)
- self.keyboard = KeyboardSetting(self)
- self.formats = FormatsSetting(self)
+ self.language = LanguageSetting(locales, locale_selected_cb)
+ self.keyboard = KeyboardSetting()
+ self.formats = FormatsSetting(locales)
def __del__(self):
if self._actusermanager_loadedid:
self._actusermanager.disconnect(self._actusermanager_loadedid)
@staticmethod
- def __get_langcodes():
- with open(tailsgreeter.config.language_codes_path, 'r') as f:
+ def _get_locales() -> [str]:
+ with open(tailsgreeter.config.locales_path, 'r') as f:
return [line.rstrip('\n') for line in f.readlines()]
def __on_usermanager_loaded(self, manager, pspec, data=None):
logging.debug("Received AccountsManager signal is-loaded")
- act_user = manager.get_user(tailsgreeter.config.LUSER)
- if not act_user.is_loaded():
+ user_account = manager.get_user(tailsgreeter.config.LUSER)
+ if not user_account.is_loaded():
raise RuntimeError("User manager for %s not loaded"
% tailsgreeter.config.LUSER)
- self._act_user = act_user
+ self.language._user_account = user_account
+
if self._usermanager_loaded_cb:
self._usermanager_loaded_cb()
- @staticmethod
- def __fill_languages_dict(locale_codes):
- """assemble dictionary of language codes to corresponding locales list
-
- example {en: [en_US, en_GB], ...}"""
- languages_dict = {}
- for locale_code in locale_codes:
- lang_code = language_from_locale(locale_code)
- if lang_code not in languages_dict:
- languages_dict[lang_code] = []
- if locale_code not in languages_dict[lang_code]:
- languages_dict[lang_code].append(locale_code)
- return languages_dict
-
- @staticmethod
- def __fill_formats_dict(locale_codes):
- """assemble dictionary of country codes to corresponding locales list
-
- example {FR: [fr_FR, en_FR], ...}"""
- formats_dict = {}
- for locale_code in locale_codes:
- country_code = country_from_locale(locale_code)
- if country_code not in formats_dict:
- formats_dict[country_code] = []
- if locale_code not in formats_dict[country_code]:
- formats_dict[country_code].append(locale_code)
- return formats_dict
-
- def apply_settings_to_upcoming_session(self):
+ def apply_to_upcoming_session(self):
with open(tailsgreeter.config.locale_output_path, 'w') as f:
os.chmod(tailsgreeter.config.locale_output_path, 0o600)
- if hasattr(self, "text"):
- f.write('TAILS_LOCALE_NAME=%s\n' % self.language.get_value())
- if hasattr(self, "formats"):
- f.write('TAILS_FORMATS=%s\n' % self.formats.get_value())
- if hasattr(self, "layout"):
- try:
- layout, variant = self.keyboard.get_value().split('+')
- except ValueError:
- layout = self.keyboard.get_value()
- variant = ''
- # XXX: use default value from /etc/default/keyboard
- f.write('TAILS_XKBMODEL=%s\n' % 'pc105')
- f.write('TAILS_XKBLAYOUT=%s\n' % layout)
- f.write('TAILS_XKBVARIANT=%s\n' % variant)
+
+ f.write('TAILS_LOCALE_NAME=%s\n' % self.language.get_value())
+ f.write('TAILS_FORMATS=%s\n' % self.formats.get_value())
+
+ try:
+ layout, variant = self.keyboard.get_value().split('+')
+ except ValueError:
+ layout = self.keyboard.get_value()
+ variant = ''
+ # XXX: use default value from /etc/default/keyboard
+ f.write('TAILS_XKBMODEL=%s\n' % 'pc105')
+ f.write('TAILS_XKBLAYOUT=%s\n' % layout)
+ f.write('TAILS_XKBVARIANT=%s\n' % variant)
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/macspoof.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/macspoof.py
new file mode 100644
index 0000000..4132e39
--- /dev/null
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/macspoof.py
@@ -0,0 +1,19 @@
+import os
+import logging
+import pipes
+
+import tailsgreeter.config
+
+
+class MacSpoofSetting(object):
+ """Setting controlling whether the MAC address is spoofed or not"""
+
+ def __init__(self):
+ self.value = True
+
+ def apply_to_upcoming_session(self):
+ setting_file = tailsgreeter.config.macspoof_setting
+ with open(setting_file, 'w') as f:
+ os.chmod(setting_file, 0o600)
+ f.write("TAILS_MACSPOOF_ENABLED=%s\n" % pipes.quote(str(self.value)).lower())
+ logging.debug('macspoof setting written to %s', setting_file)
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/network.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/network.py
new file mode 100644
index 0000000..ba257d3
--- /dev/null
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/network.py
@@ -0,0 +1,23 @@
+import os
+import logging
+import pipes
+
+import tailsgreeter.config
+
+
+class NetworkSetting(object):
+ """Setting controlling how Tails connects to Tor"""
+
+ NETCONF_DIRECT = "direct"
+ NETCONF_OBSTACLE = "obstacle"
+ NETCONF_DISABLED = "disabled"
+
+ def __init__(self):
+ self.value = self.NETCONF_DIRECT
+
+ def apply_to_upcoming_session(self):
+ setting_file = tailsgreeter.config.network_setting
+ with open(setting_file, 'w') as f:
+ os.chmod(setting_file, 0o600)
+ f.write("TAILS_NETCONF=%s\n" % pipes.quote(self.value))
+ logging.debug('network setting written to %s', setting_file)
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/physicalsecurity.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/physicalsecurity.py
deleted file mode 100644
index 75b744b..0000000
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/physicalsecurity.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 2013-2016 Tails developers <tails@boum.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>
-#
-"""Physical security settings
-
-"""
-import os
-import logging
-import pipes
-
-import tailsgreeter.config
-
-
-class PhysicalSecuritySettings(object):
- """Model storing settings related to physical security
-
- """
-
- NETCONF_DIRECT = "direct"
- NETCONF_OBSTACLE = "obstacle"
- NETCONF_DISABLED = "disabled"
-
- def __init__(self):
- # Whether to run macspoof
- self._netconf = self.NETCONF_DIRECT
- self._macspoof = True
- self.write_settings()
-
- def write_settings(self):
- physical_security_settings_file = \
- tailsgreeter.config.physical_security_settings
- with open(physical_security_settings_file, 'w') as f:
- os.chmod(physical_security_settings_file, 0o600)
- f.write('TAILS_NETCONF={0}\n'.format(
- pipes.quote(self.netconf)))
- f.write('TAILS_MACSPOOF_ENABLED={0}\n'.format(
- pipes.quote(str(self.macspoof).lower())))
- logging.debug('physical security settings written to %s',
- physical_security_settings_file)
-
- @property
- def netconf(self):
- return self._netconf
-
- @property
- def macspoof(self):
- return self._macspoof
-
- @netconf.setter
- def netconf(self, new_state):
- self._netconf = new_state
- self.write_settings()
-
- @macspoof.setter
- def macspoof(self, new_state):
- self._macspoof = new_state
- self.write_settings()
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/rootaccess.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/rootaccess.py
deleted file mode 100644
index 057f8be..0000000
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/settings/rootaccess.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2012-2016 Tails developers <tails@boum.org>
-# Copyright 2011 Max <govnototalitarizm@gmail.com>
-# Copyright 2011 Martin Owens
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>
-#
-"""Root access handling
-
-"""
-import os
-import os.path
-import logging
-import pipes
-
-import tailsgreeter.config
-
-
-class RootAccessSettings(object):
- """Model storing settings related to root access
-
- """
- def __init__(self):
- # Root password
- self.password = None
- # XXX: this should read the content of the setting file
-
- @property
- def password(self):
- return self._password
-
- @password.setter
- def password(self, password):
- self._password = password
- if password:
- with open(tailsgreeter.config.rootpassword_output_path, 'w') as f:
- os.chmod(tailsgreeter.config.rootpassword_output_path, 0o600)
- f.write('TAILS_USER_PASSWORD=%s\n'
- % pipes.quote(self.password))
- logging.debug('password written to %s',
- tailsgreeter.config.rootpassword_output_path)
- else:
- try:
- os.unlink(tailsgreeter.config.rootpassword_output_path)
- logging.debug('removed %s',
- tailsgreeter.config.rootpassword_output_path)
- except OSError:
- if not os.path.exists(
- tailsgreeter.config.rootpassword_output_path):
- pass
- else:
- raise
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/translatable_window.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/translatable_window.py
index 39c0988..a9577c3 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/translatable_window.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/translatable_window.py
@@ -1,3 +1,23 @@
+#!/usr/bin/python3
+#
+# Copyright 2012-2019 Tails developers <tails@boum.org>
+# Copyright 2011 Max <govnototalitarizm@gmail.com>
+# Copyright 2011 Martin Owens
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>
+#
+
import gettext
import logging
@@ -17,7 +37,7 @@ class TranslatableWindow(object):
self.window_ = window
self.translation = gettext.translation(
TRANSLATION_DOMAIN,
- tailsgreeter.config.locales_path,
+ tailsgreeter.config.system_locale_dir,
fallback=True
)
@@ -108,7 +128,7 @@ class TranslatableWindow(object):
try:
self.translation = gettext.translation(
TRANSLATION_DOMAIN,
- tailsgreeter.config.locales_path, [str(lang)])
+ tailsgreeter.config.system_locale_dir, [str(lang)])
except IOError:
self.translation = None
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py
index c7c471c..6a2883f 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/additional_settings.py
@@ -13,8 +13,9 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gdk, Gtk
if TYPE_CHECKING:
- from tailsgreeter.settings.rootaccess import RootAccessSettings
- from tailsgreeter.settings.physicalsecurity import PhysicalSecuritySettings
+ from tailsgreeter.settings.admin import AdminSetting
+ from tailsgreeter.settings.macspoof import MacSpoofSetting
+ from tailsgreeter.settings.network import NetworkSetting
ADDITIONAL_SETTINGS_UI_FILE = "additional_settings.ui"
@@ -45,7 +46,7 @@ class AdditionalSetting(GreeterSetting):
pass
-class AdminSetting(AdditionalSetting):
+class AdminSettingUI(AdditionalSetting):
@property
def id(self) -> str:
return "admin"
@@ -78,8 +79,8 @@ class AdminSetting(AdditionalSetting):
self.dialog.button_add.set_sensitive(self.passwords_match())
self.password_entry.grab_focus()
- def __init__(self, root_access_setting: "RootAccessSettings"):
- self._root_access_setting = root_access_setting
+ def __init__(self, admin_setting: "AdminSetting"):
+ self._admin_setting = admin_setting
self.password = None
super().__init__()
self.accel_key = Gdk.KEY_a
@@ -116,7 +117,7 @@ class AdminSetting(AdditionalSetting):
def apply(self):
# This writes the password to a file from which it will be set
# as the amnesia password when the greeter is closed.
- self._root_access_setting.password = self.password
+ self._admin_setting.password = self.password
def cb_entry_admin_changed(self, editable, user_data=None):
self.update_check_icon()
@@ -145,7 +146,7 @@ class AdminSetting(AdditionalSetting):
self.popover.close(Gtk.ResponseType.YES)
-class MACSpoofSetting(AdditionalSetting):
+class MACSpoofSettingUI(AdditionalSetting):
@property
def id(self) -> str:
return "macspoof"
@@ -162,8 +163,8 @@ class MACSpoofSetting(AdditionalSetting):
def value_for_display(self) -> str:
return get_on_off_string(self.spoofing_enabled, default=True)
- def __init__(self, physical_security_settings: "PhysicalSecuritySettings"):
- self._physical_security_settings = physical_security_settings
+ def __init__(self, macspoof_setting: "MacSpoofSetting"):
+ self._macspoof_setting = macspoof_setting
self.spoofing_enabled = True
super().__init__()
self.accel_key = Gdk.KEY_m
@@ -177,7 +178,7 @@ class MACSpoofSetting(AdditionalSetting):
self.listboxrow_macspoof_off = self.builder.get_object('listboxrow_macspoof_off')
def apply(self):
- self._physical_security_settings.macspoof = self.spoofing_enabled
+ self._macspoof_setting.value = self.spoofing_enabled
def cb_listbox_macspoof_row_activated(self, listbox, row, user_data=None):
self.spoofing_enabled = row == self.listboxrow_macspoof_on
@@ -195,7 +196,7 @@ class MACSpoofSetting(AdditionalSetting):
return False
-class NetworkSetting(AdditionalSetting):
+class NetworkSettingUI(AdditionalSetting):
@property
def id(self) -> str:
return "network"
@@ -210,16 +211,16 @@ class NetworkSetting(AdditionalSetting):
@property
def value_for_display(self) -> str:
- if self.netconf == self._physical_security_settings.NETCONF_DIRECT:
+ if self.value == self._network_setting.NETCONF_DIRECT:
return _("Direct (default)")
- if self.netconf == self._physical_security_settings.NETCONF_OBSTACLE:
+ if self.value == self._network_setting.NETCONF_OBSTACLE:
return _("Bridge & Proxy")
- if self.netconf == self._physical_security_settings.NETCONF_DISABLED:
+ if self.value == self._network_setting.NETCONF_DISABLED:
return _("Offline")
- def __init__(self, physical_security_settings: "PhysicalSecuritySettings"):
- self._physical_security_settings = physical_security_settings
- self.netconf = self._physical_security_settings.NETCONF_DIRECT
+ def __init__(self, network_setting: "NetworkSetting"):
+ self._network_setting = network_setting
+ self.value = self._network_setting.NETCONF_DIRECT
super().__init__()
self.accel_key = Gdk.KEY_n
self.icon_network_clear_chosen = self.builder.get_object('image_network_clear')
@@ -233,8 +234,8 @@ class NetworkSetting(AdditionalSetting):
self.listboxrow_network_off = self.builder.get_object('listboxrow_network_off')
def apply(self):
- self._physical_security_settings.netconf = self.netconf
- is_bridge = self.netconf == self._physical_security_settings.NETCONF_OBSTACLE
+ self._network_setting.value = self.value
+ is_bridge = self.value == self._network_setting.NETCONF_OBSTACLE
self.main_window.set_bridge_infobar_visibility(is_bridge)
def cb_listbox_network_button_press(self, widget, event, user_data=None):
@@ -249,13 +250,13 @@ class NetworkSetting(AdditionalSetting):
self.icon_network_off_chosen.set_visible(False)
if row == self.listboxrow_network_clear:
- self.netconf = self._physical_security_settings.NETCONF_DIRECT
+ self.value = self._network_setting.NETCONF_DIRECT
self.icon_network_clear_chosen.set_visible(True)
elif row == self.listboxrow_network_specific:
- self.netconf = self._physical_security_settings.NETCONF_OBSTACLE
+ self.value = self._network_setting.NETCONF_OBSTACLE
self.icon_network_specific_chosen.set_visible(True)
elif row == self.listboxrow_network_off:
- self.netconf = self._physical_security_settings.NETCONF_DISABLED
+ self.value = self._network_setting.NETCONF_DISABLED
self.icon_network_off_chosen.set_visible(True)
if self.has_popover() and self.popover.is_open():
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/main_window.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/main_window.py
index 96fefe1..1bc3338 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/main_window.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/main_window.py
@@ -30,7 +30,7 @@ from tailsgreeter.ui import _
from tailsgreeter.ui.add_settings_dialog import AddSettingsDialog
from tailsgreeter.ui.additional_settings import AdditionalSetting
from tailsgreeter.ui.help_window import GreeterHelpWindow
-from tailsgreeter.ui.region_settings import RegionSetting, TextSetting
+from tailsgreeter.ui.region_settings import LocalizationSettingUI, LanguageSettingUI
from tailsgreeter import TRANSLATION_DOMAIN
from tailsgreeter.ui.persistent_storage import PersistentStorage
@@ -50,7 +50,7 @@ ICON_DIR = 'icons/'
PREFERRED_WIDTH = 620
PREFERRED_HEIGHT = 470
-locale.bindtextdomain(TRANSLATION_DOMAIN, tailsgreeter.config.locales_path)
+locale.bindtextdomain(TRANSLATION_DOMAIN, tailsgreeter.config.system_locale_dir)
class GreeterMainWindow(Gtk.Window, TranslatableWindow):
@@ -366,7 +366,7 @@ class GreeterMainWindow(Gtk.Window, TranslatableWindow):
setting.popover.open(self.on_region_setting_popover_closed, setting)
return False
- def on_region_setting_popover_closed(self, popover: Popover, setting: RegionSetting):
+ def on_region_setting_popover_closed(self, popover: Popover, setting: LocalizationSettingUI):
# Unselect the listbox row
self.listbox_region.unselect_all()
@@ -378,7 +378,7 @@ class GreeterMainWindow(Gtk.Window, TranslatableWindow):
# If the language is changed, the values of the other region settings
# are changed as well, so we have to update the value labels for all
# region settings in that case.
- if isinstance(setting, TextSetting):
+ if isinstance(setting, LanguageSettingUI):
for s in self.settings.region_settings:
s.update_value_label()
else:
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py
index 16fd73b..ce28eef 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/region_settings.py
@@ -18,7 +18,7 @@ if TYPE_CHECKING:
REGION_SETTINGS_UI_FILE = "region_settings.ui"
-class RegionSetting(GreeterSetting):
+class LocalizationSettingUI(GreeterSetting):
def __init__(self, localization_setting: "LocalizationSetting"):
self._localization_setting = localization_setting
super().__init__()
@@ -53,7 +53,7 @@ class RegionSetting(GreeterSetting):
self.treeview.set_model(self.treestore_filtered)
def apply(self):
- self._localization_setting.set_value(self.selected_code)
+ self._localization_setting.set_value(self.selected_code, chosen_by_user=True)
def cb_searchentry_activate(self, searchentry, user_data=None):
"""Selects the topmost item in the treeview when pressing Enter"""
@@ -125,10 +125,10 @@ class RegionSetting(GreeterSetting):
return False
-class TextSetting(RegionSetting):
+class LanguageSettingUI(LocalizationSettingUI):
@property
def id(self) -> str:
- return "text"
+ return "language"
@property
def title(self) -> str:
@@ -143,7 +143,7 @@ class TextSetting(RegionSetting):
return self._localization_setting.get_name()
-class KeyboardSetting(RegionSetting):
+class KeyboardSettingUI(LocalizationSettingUI):
@property
def id(self) -> str:
return "keyboard"
@@ -161,7 +161,7 @@ class KeyboardSetting(RegionSetting):
return self._localization_setting.get_name()
-class FormatsSetting(RegionSetting):
+class FormatsSettingUI(LocalizationSettingUI):
@property
def id(self) -> str:
return "formats"
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/settings_collection.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/settings_collection.py
index bc2619a..03bb463 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/settings_collection.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailsgreeter/ui/settings_collection.py
@@ -1,7 +1,7 @@
import gi
from tailsgreeter.ui.setting import GreeterSetting
-from tailsgreeter.ui.region_settings import RegionSetting
+from tailsgreeter.ui.region_settings import LocalizationSettingUI
from tailsgreeter.ui.additional_settings import AdditionalSetting
gi.require_version('Gtk', '3.0')
@@ -16,7 +16,7 @@ class GreeterSettingsCollection(object):
return
self.region_settings = GreeterSettingsCollection(
- *(s for s in self.settings.values() if isinstance(s, RegionSetting)),
+ *(s for s in self.settings.values() if isinstance(s, LocalizationSettingUI)),
no_subclassification = True,
)
self.additional_settings = GreeterSettingsCollection(
diff --git a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailslib/additionalsoftware.py b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailslib/additionalsoftware.py
index ab6eaf1..89e4ca6 100644
--- a/config/chroot_local-includes/usr/lib/python3/dist-packages/tailslib/additionalsoftware.py
+++ b/config/chroot_local-includes/usr/lib/python3/dist-packages/tailslib/additionalsoftware.py
@@ -36,7 +36,7 @@ def _write_config(packages, search_new_persistence=False):
with atomicwrites.atomic_write(packages_list_path,
overwrite=True) as f:
for package in sorted(packages):
- f.write(package + '\n')
+ f.apply_to_upcoming_session(package + '\n')
os.chmod(packages_list_path, 0o0644)
finally:
os.seteuid(0)
diff --git a/config/chroot_local-includes/usr/local/lib/onion-grater b/config/chroot_local-includes/usr/local/lib/onion-grater
index b8369b9..5910302 100755
--- a/config/chroot_local-includes/usr/local/lib/onion-grater
+++ b/config/chroot_local-includes/usr/local/lib/onion-grater
@@ -245,9 +245,9 @@ class FilteredControlPortProxySession:
if line.isspace():
return
self.debug_log_send(line)
- self.wfile.write(bytes(line, 'ascii'))
+ self.wfile.apply_to_upcoming_session(bytes(line, 'ascii'))
if not raw:
- self.wfile.write(bytes("\r\n", 'ascii'))
+ self.wfile.apply_to_upcoming_session(bytes("\r\n", 'ascii'))
self.wfile.flush()
def get_rule(self, cmd, arg_str):
diff --git a/config/chroot_local-includes/usr/local/lib/tails-additional-software-notify b/config/chroot_local-includes/usr/local/lib/tails-additional-software-notify
index e31e020..6893b63 100755
--- a/config/chroot_local-includes/usr/local/lib/tails-additional-software-notify
+++ b/config/chroot_local-includes/usr/local/lib/tails-additional-software-notify
@@ -45,7 +45,7 @@ class ASPNotifier(object):
self.cb_notification_clicked, None)
self.notification.connect("closed", self.cb_notification_closed)
self.notification.show()
- sys.stdout.write("id=%i" % self.notification.props.id)
+ sys.stdout.apply_to_upcoming_session("id=%i" % self.notification.props.id)
if not (accept_label or deny_label or documentation_target):
sys.exit(2)
@@ -70,10 +70,10 @@ def print_help():
"""The subcommand which displays help
"""
program_name = os.path.basename(sys.argv[0])
- sys.stderr.write(
+ sys.stderr.apply_to_upcoming_session(
"Usage: %s <summary> <body> [<accept_label> [<deny_label> "
"[documentation_target [<urgent>]]]]\n" % program_name)
- sys.stderr.write(
+ sys.stderr.apply_to_upcoming_session(
"Shows a notification with <summary>, <body> and optional "
"buttons.\n"
"\n"
diff --git a/config/chroot_local-includes/usr/local/lib/tails-autotest-remote-shell b/config/chroot_local-includes/usr/local/lib/tails-autotest-remote-shell
index 96ae7db..ee2d1a5 100755
--- a/config/chroot_local-includes/usr/local/lib/tails-autotest-remote-shell
+++ b/config/chroot_local-includes/usr/local/lib/tails-autotest-remote-shell
@@ -172,7 +172,7 @@ def main():
else:
raise ValueError("unknown command type")
response = (ret + "\n").encode('utf-8')
- port.write(response)
+ port.apply_to_upcoming_session(response)
port.flush()
except Exception as e:
print("Error caught while processing line:", file=sys.stderr)
@@ -182,7 +182,7 @@ def main():
print("-----", file=sys.stderr)
sys.stderr.flush()
exc_str = '{}: {}'.format(type(e).__name__, str(e))
- port.write(json.dumps([id, 'error', exc_str]).encode('utf-8') + b"\n")
+ port.apply_to_upcoming_session(json.dumps([id, 'error', exc_str]).encode('utf-8') + b"\n")
port.flush()
continue
diff --git a/config/chroot_local-includes/usr/local/lib/tails-shell-library/tails-greeter.sh b/config/chroot_local-includes/usr/local/lib/tails-shell-library/tails-greeter.sh
index dc6cc26..ca0c4db 100644
--- a/config/chroot_local-includes/usr/local/lib/tails-shell-library/tails-greeter.sh
+++ b/config/chroot_local-includes/usr/local/lib/tails-shell-library/tails-greeter.sh
@@ -1,7 +1,8 @@
#!/bin/sh
-PERSISTENCE_STATE='/var/lib/live/config/tails.persistence'
-PHYSICAL_SECURITY_SETTINGS='/var/lib/live/config/tails.physical_security'
+PERSISTENCE_SETTING='/var/lib/live/config/tails.persistence'
+MACSPOOF_SETTING='/var/lib/live/config/tails.macspoof'
+NETWORK_SETTING='/var/lib/live/config/tails.network'
_get_tg_setting() {
if [ -r "${1}" ]; then
@@ -11,7 +12,7 @@ _get_tg_setting() {
}
persistence_is_enabled() {
- [ "$(_get_tg_setting "${PERSISTENCE_STATE}" TAILS_PERSISTENCE_ENABLED)" = true ]
+ [ "$(_get_tg_setting "${PERSISTENCE_SETTING}" TAILS_PERSISTENCE_ENABLED)" = true ]
}
persistence_is_enabled_for() {
@@ -20,15 +21,15 @@ persistence_is_enabled_for() {
persistence_is_enabled_read_write() {
persistence_is_enabled && \
- [ "$(_get_tg_setting "${PERSISTENCE_STATE}" TAILS_PERSISTENCE_READONLY)" != true ]
+ [ "$(_get_tg_setting "${PERSISTENCE_SETTING}" TAILS_PERSISTENCE_READONLY)" != true ]
}
mac_spoof_is_enabled() {
# Only return false when explicitly told so to increase failure
# safety.
- [ "$(_get_tg_setting "${PHYSICAL_SECURITY_SETTINGS}" TAILS_MACSPOOF_ENABLED)" != false ]
+ [ "$(_get_tg_setting "${MACSPOOF_SETTING}" TAILS_MACSPOOF_ENABLED)" != false ]
}
tails_netconf() {
- _get_tg_setting "${PHYSICAL_SECURITY_SETTINGS}" TAILS_NETCONF
+ _get_tg_setting "${NETWORK_SETTING}" TAILS_NETCONF
}
diff --git a/config/chroot_local-includes/usr/local/lib/tails-unblock-network b/config/chroot_local-includes/usr/local/lib/tails-unblock-network
index 5f8e1b5..3e33d08 100755
--- a/config/chroot_local-includes/usr/local/lib/tails-unblock-network
+++ b/config/chroot_local-includes/usr/local/lib/tails-unblock-network
@@ -4,7 +4,7 @@ set -e
set -u
set -x
-CONFIG_FILE=/var/lib/gdm3/tails.physical_security
+CONFIG_FILE=/var/lib/gdm3/tails.network
NET_MODULES_BLACKLIST=/etc/modprobe.d/all-net-blacklist.conf
# Import the TAILS_NETCONF variable
diff --git a/config/chroot_local-includes/usr/local/sbin/tails-additional-software b/config/chroot_local-includes/usr/local/sbin/tails-additional-software
index a2fbc9b..9d8783a 100755
--- a/config/chroot_local-includes/usr/local/sbin/tails-additional-software
+++ b/config/chroot_local-includes/usr/local/sbin/tails-additional-software
@@ -627,8 +627,8 @@ def upgrade_additional_packages():
def print_help():
"""Subcommand which displays help."""
- sys.stderr.write("Usage: %s <subcommand>\n" % program_name)
- sys.stderr.write("""Subcommands:
+ sys.stderr.apply_to_upcoming_session("Usage: %s <subcommand>\n" % program_name)
+ sys.stderr.apply_to_upcoming_session("""Subcommands:
install: install additional software
upgrade: upgrade additional software\n""")
diff --git a/config/chroot_local-includes/usr/local/sbin/tails-debugging-info b/config/chroot_local-includes/usr/local/sbin/tails-debugging-info
index a0babde..9f5af7e 100755
--- a/config/chroot_local-includes/usr/local/sbin/tails-debugging-info
+++ b/config/chroot_local-includes/usr/local/sbin/tails-debugging-info
@@ -92,7 +92,7 @@ def debug_file(user, filename):
>>> import tempfile, getpass
>>> with tempfile.NamedTemporaryFile('w') as f:
- ... _ = f.write("foo\\nbar")
+ ... _ = f.apply_to_upcoming_session("foo\\nbar")
... _ = f.seek(0)
... debug_file(getpass.getuser(), f.name)
{...'content': ['foo', 'bar']...}
@@ -122,7 +122,7 @@ def debug_directory(user, dir_name):
>>> tmpdir = '/tmp/mytempdir'
>>> os.makedirs(tmpdir)
>>> with open(os.path.join(tmpdir, 'foo'), 'w') as f:
- ... _ = f.write("foobar\\nbar")
+ ... _ = f.apply_to_upcoming_session("foobar\\nbar")
... _ = f.seek(0)
... result = debug_directory(getpass.getuser(), tmpdir)
>>> os.remove(os.path.join(tmpdir, 'foo'))
diff --git a/config/chroot_local-includes/usr/share/tails/greeter/language_codes b/config/chroot_local-includes/usr/share/tails/greeter/locales
index 0b161b7..0b161b7 100644
--- a/config/chroot_local-includes/usr/share/tails/greeter/language_codes
+++ b/config/chroot_local-includes/usr/share/tails/greeter/locales
diff --git a/config/chroot_local-includes/usr/share/tails/greeter/tails-greeter.py b/config/chroot_local-includes/usr/share/tails/greeter/tails-greeter.py
index 29cf327..a953808 100755
--- a/config/chroot_local-includes/usr/share/tails/greeter/tails-greeter.py
+++ b/config/chroot_local-includes/usr/share/tails/greeter/tails-greeter.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
#
-# Copyright 2012-2016 Tails developers <tails@boum.org>
+# Copyright 2012-2019 Tails developers <tails@boum.org>
# Copyright 2011 Max <govnototalitarizm@gmail.com>
# Copyright 2011 Martin Owens
#
@@ -22,13 +22,21 @@ GDM greeter for Tails project using gtk
"""
import gettext
+import gi
import locale
-import logging
import logging.config
import sys
-import traceback # NOQA: F401
+import traceback
+from tailsgreeter.greeter import GreeterApplication
+import tailsgreeter.config
+import tailsgreeter.gdmclient
+gi.require_version('GLib', '2.0')
+gi.require_version("Gtk", "3.0")
+from gi.repository import GLib, Gtk
+
+# Logging
logging.config.fileConfig('tails-logging.conf')
# Set loglevel if debug is found in kernel command line
with open('/proc/cmdline') as cmdline_fd:
@@ -38,6 +46,7 @@ if "debug" in cmdline.split() or \
logging.getLogger().setLevel(logging.DEBUG)
+# Hook to print exceptions with stack trace
def log_exc(etype, value, tb):
for line in traceback.format_exception(etype, value, tb):
print(line, file=sys.stderr)
@@ -46,132 +55,13 @@ def log_exc(etype, value, tb):
sys.excepthook = log_exc
-import gi # NOQA: F401
-gi.require_version('GLib', '2.0')
-from gi.repository import GLib # NOQA: F401
-from gi.repository import Gio # NOQA: F401
-gi.require_version("Gtk", "3.0")
-from gi.repository import Gtk # NOQA: F401
-
-import tailsgreeter # NOQA: F401
-import tailsgreeter.config # NOQA: F401
-import tailsgreeter.gdmclient # NOQA: F401
-
-from tailsgreeter.settings import localization
-from tailsgreeter.settings.localization_settings import LocalisationSettings
-from tailsgreeter.settings.persistence import PersistenceSettings
-from tailsgreeter.settings.physicalsecurity import PhysicalSecuritySettings
-from tailsgreeter.settings.rootaccess import RootAccessSettings
-from tailsgreeter.translatable_window import TranslatableWindow
-from tailsgreeter.ui.main_window import GreeterMainWindow # NOQA: F401
-from tailsgreeter.ui.settings_collection import GreeterSettingsCollection
-from tailsgreeter.ui.region_settings import TextSetting, KeyboardSetting, FormatsSetting
-from tailsgreeter.ui.additional_settings import AdminSetting, MACSpoofSetting, NetworkSetting
-
-gettext.install(tailsgreeter.__appname__, tailsgreeter.config.locales_path)
-locale.bindtextdomain(tailsgreeter.__appname__,
- tailsgreeter.config.locales_path)
+gettext.install(tailsgreeter.__appname__, tailsgreeter.config.system_locale_dir)
+locale.bindtextdomain(tailsgreeter.__appname__, tailsgreeter.config.system_locale_dir)
_ = gettext.gettext
-
-class GreeterApplication():
- """Tails greeter main controller
-
- This class is the greeter dbus service"""
-
- def __init__(self):
- self.language = 'en_US.UTF-8'
- self.session = None
- self.forced = False
- self.postponed = False
- self.postponed_text = None
- self.ready = False
- self.translated = False
-
- self._sessionmanager = Gio.DBusProxy.new_for_bus_sync(
- Gio.BusType.SESSION,
- Gio.DBusProxyFlags.NONE,
- None,
- "org.gnome.SessionManager",
- "/org/gnome/SessionManager",
- "org.gnome.SessionManager")
-
- # Load models
- self.gdmclient = tailsgreeter.gdmclient.GdmClient(
- session_opened_cb=self.close_app
- )
-
- persistence = PersistenceSettings()
- self.localisationsettings = LocalisationSettings(
- usermanager_loaded_cb=self.usermanager_loaded,
- locale_selected_cb=self.locale_selected
- )
- rootaccess = RootAccessSettings()
- physical_security = PhysicalSecuritySettings()
-
- # Initialize the settings
- settings = GreeterSettingsCollection(
- TextSetting(self.localisationsettings.language),
- KeyboardSetting(self.localisationsettings.keyboard),
- FormatsSetting(self.localisationsettings.formats),
- AdminSetting(rootaccess),
- MACSpoofSetting(physical_security),
- NetworkSetting(physical_security),
- )
-
- # Initialize main window
- self.mainwindow = GreeterMainWindow(self, persistence, settings)
-
- # Inhibit the session being marked as idle
- self.inhibit_idle()
-
- def translate_to(self, lang):
- """Translate all windows to target language"""
- TranslatableWindow.translate_all(lang)
-
- def login(self):
- """Login GDM to the server"""
- logging.debug("login called")
- self.mainwindow.hide()
- self.gdmclient.do_login()
-
- def usermanager_loaded(self):
- """UserManager is ready"""
- logging.debug("Entering usermanager_loaded")
- self.ready = True
- self.localisationsettings.language.set_value('en_US')
- logging.info("tails-greeter is ready.")
- self.mainwindow.show()
-
- def locale_selected(self, locale_code):
- """Translate to the given locale"""
- self.translate_to(locale_code)
- self.mainwindow.current_language = localization.language_from_locale(locale_code)
-
- def close_app(self):
- """We're done, quit gtk app"""
- logging.info("Finished.")
- Gtk.main_quit()
-
- def shutdown(self):
- """Shuts down the computer using GNOME Session Manager"""
- logging.info("Shutdown")
- self._sessionmanager.Shutdown()
-
- def inhibit_idle(self):
- cookie = self._sessionmanager.Inhibit(
- "(susu)",
- "org.boum.tails.Greeter",
- 0,
- "Greeter session shouldn't idle",
- 8) # Inhibit the session being marked as idle
- logging.debug("inhibitor cookie=%i", cookie)
-
-
if __name__ == "__main__":
GLib.set_prgname(tailsgreeter.APPLICATION_TITLE)
- GLib.set_application_name(
- _(tailsgreeter.APPLICATION_TITLE)) # NOQA: F821
+ GLib.set_application_name(_(tailsgreeter.APPLICATION_TITLE))
Gtk.init(sys.argv)
Gtk.Window.set_default_icon_name(tailsgreeter.APPLICATION_ICON_NAME)