]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/gnome-ask-password-agent.vala
gnome-ask-password-agent.vala: check for VALA_0_12
[thirdparty/systemd.git] / src / gnome-ask-password-agent.vala
CommitLineData
490aed58
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20using Gtk;
21using GLib;
490aed58
LP
22using Linux;
23using Posix;
efb3237e 24using Notify;
490aed58
LP
25
26[CCode (cheader_filename = "time.h")]
27extern int clock_gettime(int id, out timespec ts);
28
29public class PasswordDialog : Dialog {
30
31 public Entry entry;
32
33 public PasswordDialog(string message, string icon) {
34 set_title("System Password");
35 set_has_separator(false);
36 set_border_width(8);
37 set_default_response(ResponseType.OK);
38 set_icon_name(icon);
39
d0ef2204 40#if LIBNOTIFY07
230e5a3f
KS
41 add_button(Stock.CANCEL, ResponseType.CANCEL);
42 add_button(Stock.OK, ResponseType.OK);
d0ef2204
KS
43#else
44 add_button(STOCK_CANCEL, ResponseType.CANCEL);
45 add_button(STOCK_OK, ResponseType.OK);
46#endif
490aed58
LP
47
48 Container content = (Container) get_content_area();
49
50 Box hbox = new HBox(false, 16);
51 hbox.set_border_width(8);
52 content.add(hbox);
53
54 Image image = new Image.from_icon_name(icon, IconSize.DIALOG);
55 hbox.pack_start(image, false, false);
56
57 Box vbox = new VBox(false, 8);
58 hbox.pack_start(vbox, true, true);
59
60 Label label = new Label(message);
61 vbox.pack_start(label, false, false);
62
63 entry = new Entry();
64 entry.set_visibility(false);
65 entry.set_activates_default(true);
66 vbox.pack_start(entry, false, false);
67
68 entry.activate.connect(on_entry_activated);
69
70 show_all();
71 }
72
73 public void on_entry_activated() {
74 response(ResponseType.OK);
75 }
76}
77
78public class MyStatusIcon : StatusIcon {
79
80 File directory;
81 File current;
82 FileMonitor file_monitor;
83
84 string message;
85 string icon;
86 string socket;
87
88 PasswordDialog password_dialog;
89
90 public MyStatusIcon() throws GLib.Error {
91 GLib.Object(icon_name : "dialog-password");
820fa964 92 set_title("System Password Request");
490aed58 93
820fa964 94 directory = File.new_for_path("/var/run/systemd/ask-password/");
490aed58
LP
95 file_monitor = directory.monitor_directory(0);
96 file_monitor.changed.connect(file_monitor_changed);
97
98 current = null;
99 look_for_password();
100
101 activate.connect(status_icon_activate);
102 }
103
26742b3f 104 void file_monitor_changed(GLib.File file, GLib.File? other_file, GLib.FileMonitorEvent event_type) {
490aed58
LP
105
106 if (!file.get_basename().has_prefix("ask."))
107 return;
108
109 if (event_type == FileMonitorEvent.CREATED ||
26742b3f
LP
110 event_type == FileMonitorEvent.DELETED) {
111 try {
112 look_for_password();
113 } catch (Error e) {
114 show_error(e.message);
115 }
116 }
490aed58
LP
117 }
118
119 void look_for_password() throws GLib.Error {
120
121 if (current != null) {
122 if (!current.query_exists()) {
123 current = null;
124 if (password_dialog != null)
125 password_dialog.response(ResponseType.REJECT);
126 }
127 }
128
129 if (current == null) {
130 FileEnumerator enumerator = directory.enumerate_children("standard::name", FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
131
132 FileInfo i;
133 while ((i = enumerator.next_file()) != null) {
134 if (!i.get_name().has_prefix("ask."))
135 continue;
136
137 current = directory.get_child(i.get_name());
138
139 if (load_password())
140 break;
141
142 current = null;
143 }
144 }
145
146 if (current == null)
147 set_visible(false);
490aed58
LP
148 }
149
efb3237e 150 bool load_password() throws GLib.Error {
490aed58
LP
151
152 KeyFile key_file = new KeyFile();
153
154 try {
155 timespec ts;
156
157 key_file.load_from_file(current.get_path(), KeyFileFlags.NONE);
158
159 string not_after_as_string = key_file.get_string("Ask", "NotAfter");
160
161 clock_gettime(1, out ts);
162 uint64 now = (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
163
164 uint64 not_after;
165 if (not_after_as_string.scanf("%llu", out not_after) != 1)
166 return false;
167
168 if (not_after < now)
169 return false;
170
171 socket = key_file.get_string("Ask", "Socket");
172 } catch (GLib.Error e) {
173 return false;
174 }
175
176 try {
177 message = key_file.get_string("Ask", "Message").compress();
178 } catch (GLib.Error e) {
179 message = "Please Enter System Password!";
180 }
820fa964 181
490aed58
LP
182 set_tooltip_text(message);
183
184 try {
185 icon = key_file.get_string("Ask", "Icon");
186 } catch (GLib.Error e) {
187 icon = "dialog-password";
188 }
189 set_from_icon_name(icon);
190
191 set_visible(true);
efb3237e 192
d0ef2204 193#if LIBNOTIFY07
230e5a3f 194 Notification n = new Notification(title, message, icon);
d0ef2204
KS
195#else
196 Notification n = new Notification(title, message, icon, null);
197 n.attach_to_status_icon(this);
198#endif
efb3237e
LP
199 n.set_timeout(5000);
200 n.show();
201
490aed58
LP
202 return true;
203 }
204
26742b3f 205 void status_icon_activate() {
490aed58
LP
206
207 if (current == null)
208 return;
209
210 if (password_dialog != null) {
211 password_dialog.present();
212 return;
213 }
214
215 password_dialog = new PasswordDialog(message, icon);
216
217 int result = password_dialog.run();
218 string password = password_dialog.entry.get_text();
219
220 password_dialog.destroy();
221 password_dialog = null;
222
223 if (result == ResponseType.REJECT ||
224 result == ResponseType.DELETE_EVENT)
225 return;
226
227 int to_process;
228
26742b3f
LP
229 try {
230 Process.spawn_async_with_pipes(
231 null,
232 { "/usr/bin/pkexec", "/lib/systemd/systemd-reply-password", result == ResponseType.OK ? "1" : "0", socket },
233 null,
234 0,
235 null,
236 null,
237 out to_process,
238 null,
239 null);
240
241 OutputStream stream = new UnixOutputStream(to_process, true);
e75c0580 242#if VALA_0_12
202df05e 243 stream.write(password.data, null);
e75c0580
KS
244#else
245 stream.write(password, password.length, null);
e8bf3c88 246#endif
26742b3f
LP
247 } catch (Error e) {
248 show_error(e.message);
249 }
490aed58
LP
250 }
251}
252
253static const OptionEntry entries[] = {
254 { null }
255};
256
257void show_error(string e) {
258 var m = new MessageDialog(null, 0, MessageType.ERROR, ButtonsType.CLOSE, "%s", e);
259 m.run();
260 m.destroy();
261}
262
263int main(string[] args) {
264 try {
265 Gtk.init_with_args(ref args, "[OPTION...]", entries, "systemd-ask-password-agent");
efb3237e 266 Notify.init("Password Agent");
490aed58
LP
267
268 MyStatusIcon i = new MyStatusIcon();
269 Gtk.main();
270
490aed58
LP
271 } catch (GLib.Error e) {
272 show_error(e.message);
273 }
274
275 return 0;
276}