~ubuntu-branches/ubuntu/precise/landscape-client/precise-updates

« back to all changes in this revision

Viewing changes to landscape/ui/view/configuration.py

  • Committer: Package Import Robot
  • Author(s): David Britton
  • Date: 2012-03-28 10:59:58 UTC
  • mfrom: (1.1.27)
  • Revision ID: package-import@ubuntu.com-20120328105958-jmz1nv5eyci7azna
Tags: 12.04.3-0ubuntu1
* Warn on unicode entry into settings UI (LP: #956612).
* Sanitise hostname field in settings UI (LP: #954507).
* Make it clear that the Landscape service is commercial (LP: #965850)
* Further internationalize the settings UI (LP: #962899)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import re
1
2
import os
2
3
 
 
4
from gettext import gettext as _
 
5
 
3
6
from gi.repository import GObject, Gtk
4
7
 
5
8
from landscape.ui.constants import (
6
9
    CANONICAL_MANAGED, LOCAL_MANAGED, NOT_MANAGED)
7
10
 
 
11
# Note, I think this may not be fully compliant with the changes in RFC 1123
 
12
HOST_NAME_REGEXP = re.compile("^(([a-zA-Z][a-zA-Z0-9\-]*)?[a-zA-Z0-9][\.]?)*"
 
13
                              "(([A-Za-z][A-Za-z0-9\-]*)?[A-Za-z0-9])$")
 
14
 
 
15
 
 
16
def sanitise_host_name(host_name):
 
17
    """
 
18
    Do some minimal host name sanitation.
 
19
    """
 
20
    return host_name.strip()
 
21
 
 
22
 
 
23
def is_valid_host_name(host_name):
 
24
    """
 
25
    Check that the provided host name complies with L{HOST_NAME_REGEXP} and is
 
26
    therefor valid.
 
27
    """
 
28
    return HOST_NAME_REGEXP.match(host_name) is not None
 
29
 
 
30
 
 
31
def is_ascii(text):
 
32
    """
 
33
    Test that the provided string contains only characters from the ASCII set.
 
34
    """
 
35
    try:
 
36
        text.decode("ascii")
 
37
        return True
 
38
    except UnicodeDecodeError:
 
39
        return False
 
40
 
8
41
 
9
42
class ClientSettingsDialog(Gtk.Dialog):
10
43
    """
14
47
    """
15
48
 
16
49
    GLADE_FILE = "landscape-client-settings.glade"
17
 
    NO_SERVICE_TEXT = "None"
18
 
    HOSTED_SERVICE_TEXT = "Landscape - hosted by Canonical"
19
 
    LOCAL_SERVICE_TEXT = "Landscape - dedicated server"
20
 
    REGISTER_BUTTON_TEXT = "Register"
21
 
    DISABLE_BUTTON_TEXT = "Disable"
 
50
    INVALID_HOST_NAME = 0
 
51
    UNICODE_IN_ENTRY = 1
22
52
 
23
53
    def __init__(self, controller):
24
54
        super(ClientSettingsDialog, self).__init__(
25
 
            title="Management Service",
 
55
            title=_("Management Service"),
26
56
            flags=Gtk.DialogFlags.MODAL)
27
57
        self.set_default_icon_name("preferences-management-service")
28
58
        self.set_resizable(False)
29
59
        self._initialised = False
 
60
        self._validation_errors = set()
 
61
        self._errored_entries = []
30
62
        self.controller = controller
31
63
        self.setup_ui()
32
64
        self.load_data()
33
65
        # One extra revert to reset after loading data
34
66
        self.controller.revert()
35
67
 
 
68
    def indicate_error_on_entry(self, entry):
 
69
        """
 
70
        Show a warning icon on a L{Gtk.Entry} to indicate some associated
 
71
        error.
 
72
        """
 
73
        entry.set_icon_from_stock(
 
74
            Gtk.EntryIconPosition.PRIMARY, Gtk.STOCK_DIALOG_WARNING)
 
75
        self._errored_entries.append(entry)
 
76
 
 
77
    def check_local_landscape_host_name_entry(self):
 
78
        host_name = sanitise_host_name(
 
79
            self.local_landscape_host_entry.get_text())
 
80
        ascii_ok = is_ascii(host_name)
 
81
        host_name_ok = is_valid_host_name(host_name)
 
82
        if ascii_ok and host_name_ok:
 
83
            self.local_landscape_host_entry.set_text(host_name)
 
84
            return True
 
85
        else:
 
86
            self.indicate_error_on_entry(self.local_landscape_host_entry)
 
87
            if not host_name_ok:
 
88
                self._validation_errors.add(self.INVALID_HOST_NAME)
 
89
            if not ascii_ok:
 
90
                self._validation_errors.add(self.UNICODE_IN_ENTRY)
 
91
            return False
 
92
 
 
93
    def check_entry(self, entry):
 
94
        """
 
95
        Check that the text content of a L{Gtk.Entry} is acceptable.
 
96
        """
 
97
        if is_ascii(entry.get_text()):
 
98
            return True
 
99
        else:
 
100
            self.indicate_error_on_entry(entry)
 
101
            self._validation_errors.add(self.UNICODE_IN_ENTRY)
 
102
            return False
 
103
 
 
104
    def validity_check(self):
 
105
        self._validation_errors = set()
 
106
        if self._info_bar_container.get_visible():
 
107
            self.dismiss_infobar(None)
 
108
        active_iter = self.liststore.get_iter(
 
109
            self.use_type_combobox.get_active())
 
110
        [management_type] = self.liststore.get(active_iter, 0)
 
111
        if management_type == NOT_MANAGED:
 
112
            return True
 
113
        elif management_type == CANONICAL_MANAGED:
 
114
            account_name_ok = self.check_entry(self.hosted_account_name_entry)
 
115
            password_ok = self.check_entry(self.hosted_password_entry)
 
116
            return account_name_ok and password_ok
 
117
        else:
 
118
            host_name_ok = self.check_local_landscape_host_name_entry()
 
119
            password_ok = self.check_entry(self.local_password_entry)
 
120
            return host_name_ok and password_ok
 
121
 
 
122
    @property
 
123
    def NO_SERVICE_TEXT(self):
 
124
        return _("None")
 
125
 
 
126
    @property
 
127
    def HOSTED_SERVICE_TEXT(self):
 
128
        return _("Landscape - hosted by Canonical")
 
129
 
 
130
    @property
 
131
    def LOCAL_SERVICE_TEXT(self):
 
132
        return _("Landscape - dedicated server")
 
133
 
 
134
    @property
 
135
    def REGISTER_BUTTON_TEXT(self):
 
136
        return _("Register")
 
137
 
 
138
    @property
 
139
    def DISABLE_BUTTON_TEXT(self):
 
140
        return _("Disable")
 
141
 
 
142
    @property
 
143
    def INVALID_HOST_NAME_MESSAGE(self):
 
144
        return _("Invalid host name.")
 
145
 
 
146
    @property
 
147
    def UNICODE_IN_ENTRY_MESSAGE(self):
 
148
        return _("Only ASCII characters are allowed.")
 
149
 
36
150
    def _set_use_type_combobox_from_controller(self):
37
151
        """
38
152
        Load the persisted L{management_type} from the controller and set the
123
237
        self.response(Gtk.ResponseType.CANCEL)
124
238
 
125
239
    def register_response(self, widget):
126
 
        self.response(Gtk.ResponseType.OK)
 
240
        if self.validity_check():
 
241
            self.response(Gtk.ResponseType.OK)
 
242
        else:
 
243
            error_text = []
 
244
            if self.UNICODE_IN_ENTRY in self._validation_errors:
 
245
                error_text.append(self.UNICODE_IN_ENTRY_MESSAGE)
 
246
            if self.INVALID_HOST_NAME in self._validation_errors:
 
247
                error_text.append(self.INVALID_HOST_NAME_MESSAGE)
 
248
            self.info_message.set_text("\n".join(error_text))
 
249
            self._info_bar_container.show()
127
250
 
128
251
    def set_button_text(self, management_type):
129
252
        [alignment] = self.register_button.get_children()
148
271
        self.register_button.show()
149
272
        self.register_button.connect("clicked", self.register_response)
150
273
 
 
274
    def dismiss_infobar(self, widget):
 
275
        self._info_bar_container.hide()
 
276
        for entry in self._errored_entries:
 
277
            entry.set_icon_from_stock(Gtk.EntryIconPosition.PRIMARY, None)
 
278
        self._errored_entries = []
 
279
 
 
280
    def setup_info_bar(self):
 
281
        labels_size_group = self._builder.get_object("labels-sizegroup")
 
282
        entries_size_group = self._builder.get_object("entries-sizegroup")
 
283
        labels_size_group.set_ignore_hidden(False)
 
284
        entries_size_group.set_ignore_hidden(False)
 
285
        self._info_bar_container = Gtk.HBox()
 
286
        self._info_bar_container.set_spacing(12)
 
287
        info_bar = Gtk.InfoBar()
 
288
        entries_size_group.add_widget(info_bar)
 
289
        info_bar.show()
 
290
        empty_label = Gtk.Label()
 
291
        labels_size_group.add_widget(empty_label)
 
292
        empty_label.show()
 
293
        self._info_bar_container.pack_start(empty_label, expand=False,
 
294
                                            fill=False, padding=0)
 
295
        self._info_bar_container.pack_start(info_bar, expand=False, fill=False,
 
296
                                            padding=0)
 
297
        content_area = info_bar.get_content_area()
 
298
        hbox = Gtk.HBox()
 
299
        self.info_message = Gtk.Label()
 
300
        self.info_message.set_alignment(0, 0.5)
 
301
        self.info_message.show()
 
302
        hbox.pack_start(self.info_message, expand=True, fill=True, padding=6)
 
303
        ok_button = Gtk.Button("Dismiss")
 
304
        ok_button.connect("clicked", self.dismiss_infobar)
 
305
        ok_button.show()
 
306
        hbox.pack_start(ok_button, expand=True, fill=True, padding=0)
 
307
        hbox.show()
 
308
        content_area.pack_start(hbox, expand=True, fill=True, padding=0)
 
309
 
151
310
    def setup_ui(self):
152
311
        self._builder = Gtk.Builder()
 
312
        self._builder.set_translation_domain("landscape-client")
153
313
        self._builder.add_from_file(
154
314
            os.path.join(
155
315
                os.path.dirname(__file__), "ui", self.GLADE_FILE))
156
316
        content_area = self.get_content_area()
157
317
        content_area.set_spacing(12)
158
318
        self.set_border_width(12)
 
319
        self.setup_info_bar()
159
320
        self._vbox = self._builder.get_object("toplevel-vbox")
160
321
        self._vbox.unparent()
161
 
        content_area.pack_start(self._vbox, expand=True, fill=True, padding=12)
 
322
        content_area.pack_start(self._vbox, expand=True, fill=True,
 
323
                                padding=12)
 
324
        self._vbox.pack_start(self._info_bar_container, expand=False,
 
325
                              fill=False, padding=0)
162
326
        self.liststore = self.make_liststore()
163
327
        self.link_use_type_combobox(self.liststore)
164
328
        self.link_hosted_service_widgets()