~mrooney/ecryptfs/nautilus-integration

« back to all changes in this revision

Viewing changes to src/python/ecryptui.py

  • Committer: Michael Rooney
  • Date: 2009-05-28 10:40:56 UTC
  • Revision ID: mrooney@ubuntu.com-20090528104056-mqirt68bbs3quj5t
reflect api changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
#
 
3
#    ecryptui.py, Copyright 2008 Mike Rooney (https://launchpad.net/~mrooney)
 
4
#    Date: 2008-12-12
 
5
#    Version: 0.3
 
6
#
 
7
#    This is a graphical GTK utility to manage an encrypted ~/Private
 
8
#    directory, allowing the user to mount and unmount, as well as enable
 
9
#    auto-mounting at login.
 
10
#
 
11
#    This program is free software: you can redistribute it and/or modify
 
12
#    it under the terms of the GNU General Public License as published by
 
13
#    the Free Software Foundation, either version 3 of the License, or
 
14
#    (at your option) any later version.
 
15
#
 
16
#    This program is distributed in the hope that it will be useful,
 
17
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
#    GNU General Public License for more details.
 
20
#
 
21
#    You should have received a copy of the GNU General Public License
 
22
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
23
#
 
24
#    Lock icons courtesy of http://www.famfamfam.com/lab/icons/silk/, via the
 
25
#    Creative Commons Attribution 2.5 License.
 
26
 
 
27
import gtk, os
 
28
from panelcontroller import PanelController
 
29
try:
 
30
    from ecryptfs import ecryptapi
 
31
except ImportError:
 
32
    ecryptapi = None
 
33
 
 
34
LOCKED_ICON = os.path.join(os.path.dirname(__file__), 'lock-secure.png')
 
35
UNLOCKED_ICON = os.path.join(os.path.dirname(__file__), 'lock-insecure.png')
 
36
LOCKED_STATUS = os.path.join(os.path.dirname(__file__), 'lock-secure-small.png')
 
37
UNLOCKED_STATUS = os.path.join(os.path.dirname(__file__), 'lock-insecure-small.png')
 
38
 
 
39
            
 
40
class Window(gtk.Window):
 
41
    def __init__(self):
 
42
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
 
43
        self.set_title("Encrypted Directories")
 
44
        
 
45
        self.hbox = gtk.HBox()
 
46
        self.add(self.hbox)
 
47
        
 
48
        # Initialize some bindings.
 
49
        self.connect("destroy", self.destroy)
 
50
        
 
51
        self.Controller = PanelController(self.showInstall, self.showSetup, self.showManage)
 
52
        self.Controller.showAppropriateStep()
 
53
        self.show()
 
54
        self.show_all()
 
55
        
 
56
    def showInstall(self):
 
57
        print "Step 1: Install"
 
58
        ipanel = InstallFrame()
 
59
        self.hbox.pack_start(ipanel, False, False, 0)
 
60
        #ipanel.show()
 
61
        
 
62
    def showSetup(self):
 
63
        print "Step 2: Setup"
 
64
        spanel = SetupFrame()
 
65
        self.hbox.pack_start(spanel, False, False, 0)
 
66
        #spanel.show()
 
67
    
 
68
    def showManage(self):
 
69
        print "Step 3: Manage"
 
70
        mpanel = ManageFrame()
 
71
        self.hbox.pack_start(mpanel, False, False, 0)
 
72
        #mpanel.show()
 
73
        
 
74
    def showError(self, title, msg):
 
75
        """Show an error dialog with the given title and message body."""
 
76
        dialog = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, msg)
 
77
        dialog.set_title(title)
 
78
        dialog.run()
 
79
        dialog.destroy()
 
80
 
 
81
    def destroy(self, widget, data=None):
 
82
        """Destroy the main window and quit."""
 
83
        gtk.main_quit()
 
84
 
 
85
    def main(self):
 
86
        """All PyGTK applications need a main method (apparently)."""
 
87
        gtk.main()
 
88
        
 
89
            
 
90
class InstallFrame(gtk.Frame):
 
91
    def __init__(self):
 
92
        gtk.Frame.__init__(self)
 
93
        label = gtk.Label("ecryptfs-utils is not currently installed.")
 
94
        self.add(label)
 
95
 
 
96
class SetupFrame(gtk.Frame):
 
97
    def __init__(self):
 
98
        gtk.Frame.__init__(self)
 
99
        vbox = gtk.VBox(False, 5)
 
100
 
 
101
        label = gtk.Label("Choose how your encrypted Private directory will be configured.")
 
102
        label2 = gtk.Label("If you don't understand what a particular option does, leave it at its default value.")
 
103
        
 
104
        self.encryptFilenamesCheckbox = gtk.CheckButton("Encrypt filenames")
 
105
        self.encryptFilenamesCheckbox.set_active(True)
 
106
        
 
107
        self.checkPasswordValidityCheckbox = gtk.CheckButton("Check the validity of the specified login password")
 
108
        self.checkPasswordValidityCheckbox.set_active(True)
 
109
        
 
110
        self.createPrivateButton = gtk.Button("Create Private directory")
 
111
        
 
112
        vbox.pack_start(label, False, True, 5)
 
113
        vbox.pack_start(label2, False, False, 5)
 
114
        vbox.pack_start(self.encryptFilenamesCheckbox, False, False, 5)
 
115
        vbox.pack_start(self.checkPasswordValidityCheckbox, False, False, 5)
 
116
        vbox.pack_start(self.createPrivateButton, False, False, 5)
 
117
        self.add(vbox)
 
118
        
 
119
        self.createPrivateButton.connect("clicked", self.onCreatePrivate, None)
 
120
        
 
121
    def generateCommand(self):
 
122
        args = ["ecryptfs-setup-private"]
 
123
        if not self.encryptFilenamesCheckbox.get_active():
 
124
            args.append("--no-fnek")
 
125
        if not self.checkPasswordValidityCheckbox.get_active():
 
126
            args.append("--nopwcheck")
 
127
            
 
128
        command = " ".join(args)
 
129
        return command
 
130
    
 
131
    def onCreatePrivate(self, widget, data=None):
 
132
        print self.generateCommand()
 
133
        
 
134
class ManageFrame(gtk.Frame):
 
135
    def __init__(self):
 
136
        """Create and layout the user interface."""
 
137
        gtk.Frame.__init__(self)
 
138
 
 
139
        # When this is True, ignore toggle events, such as when we manually set it.
 
140
        # Initially True because we need to set the value.
 
141
        self.autoMountFrozen = True
 
142
        self.autoUnmountFrozen = True
 
143
 
 
144
        # The state variable, later wrapped in a property.
 
145
        self._MountedState = ecryptapi.get_mounted()
 
146
 
 
147
        # The main, vertical sizer, for holding the controls.
 
148
        hbox = gtk.HBox(False, 5)
 
149
        vbox = gtk.VBox(False, 5)
 
150
        hbox.pack_start(vbox, False, False, 5)
 
151
        self.add(hbox)
 
152
 
 
153
        # Create the label controls with explain the current status.
 
154
        labelHbox = gtk.HBox()
 
155
        label = gtk.Label("Your Private directory is currently: ")
 
156
        self.statusImage = gtk.Image()
 
157
        self.buttonImage = gtk.Image()
 
158
        self.statusLabel = gtk.Label("")
 
159
        self.statusLabel.set_use_markup(True)
 
160
        labelHbox.pack_start(label, False, False, 2)
 
161
        #labelHbox.pack_start(gtk.Label(""), True, True, 0) # Just a spacer.
 
162
        labelHbox.pack_start(self.statusLabel, False, False, 0)
 
163
        labelHbox.pack_start(self.statusImage, False, False, 2)
 
164
 
 
165
        # Create the button allowing the user to toggle the state.
 
166
        self.toggleButton = gtk.Button("")
 
167
 
 
168
        # Create a checkbox for toggling automounting.
 
169
        self.autoCheck = gtk.CheckButton("Automatically unlock Private directory at login")
 
170
        self.autoCheck.set_active(ecryptapi.get_automount())
 
171
        self.autoMountFrozen = False # Now we set, unfreeze.
 
172
 
 
173
        # Create a checkbox for toggling autounmounting.
 
174
        self.autoCheck2 = gtk.CheckButton("Automatically lock Private directory at logoff")
 
175
        self.autoCheck2.set_active(ecryptapi.get_autounmount())
 
176
        self.autoUnmountFrozen = False # Now we set, unfreeze.
 
177
 
 
178
        # Add everything to the main sizer.
 
179
        vbox.pack_start(labelHbox, False, False, 5)
 
180
        vbox.pack_start(self.toggleButton, False, False, 0)
 
181
        vbox.pack_start(self.autoCheck, False, False, 0)
 
182
        vbox.pack_start(self.autoCheck2, False, False, 0)
 
183
 
 
184
        # Update the UI state from the current state.
 
185
        self.updateFromState()
 
186
 
 
187
        # Initilize some bindings
 
188
        self.toggleButton.connect("clicked", self.onStateToggled, None)
 
189
        self.autoCheck.connect("toggled", self.onAutoMountToggled, None)
 
190
        self.autoCheck2.connect("toggled", self.onAutoUnmountToggled, None)
 
191
 
 
192
        # Show everything
 
193
        #self.show()
 
194
        self.show_all()
 
195
 
 
196
    def SetMountedState(self, state):
 
197
        """Sets the internal mount state and triggers a UI update."""
 
198
        self._MountedState = state
 
199
        self.updateFromState()
 
200
 
 
201
    def updateFromState(self):
 
202
        """
 
203
        When the state of the mount changes, this is called to update the GUI.
 
204
        """
 
205
        if self.MountedState:
 
206
            status, action, actionIcon, statusIcon = "Unlocked", "Lock your Private directory", LOCKED_ICON, UNLOCKED_STATUS
 
207
        else:
 
208
            status, action, actionIcon, statusIcon = "Locked", "Unlock your Private directory", UNLOCKED_ICON, LOCKED_STATUS
 
209
 
 
210
        self.statusLabel.set_label("<b>%s</b>"%status)
 
211
        self.toggleButton.set_property("image-position", gtk.POS_TOP)
 
212
        self.toggleButton.set_label(action)
 
213
        self.buttonImage.set_from_file(actionIcon)
 
214
        self.statusImage.set_from_file(statusIcon)
 
215
        self.toggleButton.set_image(self.buttonImage) # Does this only need to be called once in init?
 
216
 
 
217
    def onAutoMountToggled(self, widget, data=None):
 
218
        """The event handler for the automount checkbutton."""
 
219
        if not self.autoMountFrozen:
 
220
            desiredState = widget.get_active()
 
221
            status, output = ecryptapi.set_automount(desiredState)
 
222
            if status != 0:
 
223
                # It failed, unset the checkbox and show the error.
 
224
                self.autoMountFrozen = True
 
225
                widget.set_active(not desiredState)
 
226
                self.autoMountFrozen = False
 
227
                self.showError("Error %s"%status, output)
 
228
                
 
229
    def onAutoUnmountToggled(self, widget, data=None):
 
230
        """The event handler for the automount checkbutton."""
 
231
        if not self.autoUnmountFrozen:
 
232
            desiredState = widget.get_active()
 
233
            status, output = ecryptapi.set_autounmount(desiredState)
 
234
            if status != 0:
 
235
                # It failed, unset the checkbox and show the error.
 
236
                self.autoUnmountFrozen = True
 
237
                widget.set_active(not desiredState)
 
238
                self.autoUnmountFrozen = False
 
239
                self.showError("Error %s"%status, output)
 
240
 
 
241
    def onStateToggled(self, widget, data=None):
 
242
        """The event handler for the mount toggle button."""
 
243
        desiredState = not self.MountedState
 
244
        status, output = ecryptapi.set_mounted(desiredState)
 
245
        if status == 0:
 
246
            # The action was successful, update our state.
 
247
            self.MountedState = desiredState
 
248
        else:
 
249
            # The action failed, report the error.
 
250
            self.showError("Error %s"%status, output)
 
251
 
 
252
    MountedState = property(fget=lambda self: self._MountedState, fset=SetMountedState)
 
253
 
 
254
 
 
255
def main():
 
256
    base = Window()
 
257
    base.main()
 
258
 
 
259
if __name__ == "__main__":
 
260
    main()