Merge lp:~donadigo/switchboard-plug-parental-controls/merge-cli-daemon into lp:~elementary-pantheon/switchboard-plug-parental-controls/trunk
- merge-cli-daemon
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Felipe Escoto |
Approved revision: | 234 |
Merged at revision: | 226 |
Proposed branch: | lp:~donadigo/switchboard-plug-parental-controls/merge-cli-daemon |
Merge into: | lp:~elementary-pantheon/switchboard-plug-parental-controls/trunk |
Diff against target: |
3420 lines (+1413/-1256) 32 files modified
lib/exec-monitor.c (+6/-6) lib/exec-monitor.h (+1/-0) src/CMakeLists.txt (+3/-2) src/Plug.vala (+0/-1) src/Widgets/AppsBox.vala (+48/-51) src/Widgets/ControlPage.vala (+24/-34) src/Widgets/GeneralBox.vala (+61/-115) src/Widgets/InternetBox.vala (+14/-14) src/Widgets/UserItem.vala (+8/-2) src/Widgets/WeekSpinBox.vala (+7/-13) src/cli/Application.vala (+0/-191) src/cli/CMakeLists.txt (+0/-28) src/cli/PAMWriter.vala (+0/-204) src/client/AppUnavailableDialog.vala (+3/-3) src/client/CMakeLists.txt (+3/-1) src/client/Client.vala (+20/-50) src/daemon/CMakeLists.txt (+6/-2) src/daemon/Daemon.vala (+9/-10) src/daemon/Interfaces.vala (+30/-34) src/daemon/IptablesHelper.vala (+46/-48) src/daemon/ProcessWatcher.vala (+49/-74) src/daemon/Server.vala (+213/-7) src/daemon/SessionHandler.vala (+47/-163) src/daemon/SessionManager.vala (+53/-38) src/daemon/Timer.vala (+116/-0) src/daemon/UserConfig.vala (+208/-0) src/shared/PAM/Reader.vala (+66/-0) src/shared/PAM/Token.vala (+190/-0) src/shared/PAM/Writer.vala (+110/-0) src/shared/PAMControl.vala (+0/-128) src/shared/Utils.vala (+71/-34) src/shared/Vars.vala (+1/-3) |
To merge this branch: | bzr merge lp:~donadigo/switchboard-plug-parental-controls/merge-cli-daemon |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Felipe Escoto (community) | Approve | ||
Review via email: mp+304403@code.launchpad.net |
Commit message
* Merge CLI functionalities with daemon
* Remove unneded code
* Rework PAM time module parsing
* Use more native objects like Resolver to resolve addresses
* Expose Get and Set methods over DBus for easier access
* Code cleanup and rework
* Split big classes onto smaller ones for better code understanding
Description of the change
This branch is an update for Loki stable or either Loki update. It reworks how the daemon and removes the unneded code, makes it a lot easier to read and understand. It does not introduce any new features or string replacements over trunk.
The command line utility is now completely removed. It's function is now built-in to the daemon, through a DBus server. We now have different classes for parsing PAM time module which use native string utilities unlike the old parsing methods. The PAM timer logic (to show a timeout to the user) was moved into a Timer class which is also much simpler than the previous handling of this feature. There is also UserConfig class which is a representation of a key file in ~/.config/
All Get () methods of the daemon are accessible to the normal user (for displaying them in the UI without authentication) and all Set () methods need authentication to be done before calling them.
- 233. By Adam Bieńkowski
-
Remove C debug prints
- 234. By Adam Bieńkowski
-
Moved set active contents of AppsBox to ControlPage
Felipe Escoto (philip.scott) : | # |
Preview Diff
1 | === modified file 'lib/exec-monitor.c' |
2 | --- lib/exec-monitor.c 2016-05-19 19:47:38 +0000 |
3 | +++ lib/exec-monitor.c 2016-08-30 20:17:54 +0000 |
4 | @@ -110,12 +110,12 @@ |
5 | |
6 | iface = EXEC_MONITOR_GET_IFACE (self); |
7 | iface->monitor_events = FALSE; |
8 | + close (iface->sk_nl); |
9 | } |
10 | |
11 | void |
12 | exec_monitor_start_internal (ExecMonitor *self) |
13 | { |
14 | - int sk_nl; |
15 | int err; |
16 | struct sockaddr_nl my_nla, kern_nla, from_nla; |
17 | socklen_t from_nla_len; |
18 | @@ -132,8 +132,8 @@ |
19 | ExecMonitorInterface *iface; |
20 | iface = EXEC_MONITOR_GET_IFACE (self); |
21 | |
22 | - sk_nl = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); |
23 | - if (sk_nl == -1) { |
24 | + iface->sk_nl = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); |
25 | + if (iface->sk_nl == -1) { |
26 | return; |
27 | } |
28 | |
29 | @@ -145,7 +145,7 @@ |
30 | kern_nla.nl_groups = CN_IDX_PROC; |
31 | kern_nla.nl_pid = 1; |
32 | |
33 | - err = bind (sk_nl, (struct sockaddr *)&my_nla, sizeof (my_nla)); |
34 | + err = bind (iface->sk_nl, (struct sockaddr *)&my_nla, sizeof (my_nla)); |
35 | if (err == -1) { |
36 | return; |
37 | } |
38 | @@ -169,7 +169,7 @@ |
39 | cn_hdr->ack = 0; |
40 | cn_hdr->len = sizeof (enum proc_cn_mcast_op); |
41 | |
42 | - if (send (sk_nl, nl_hdr, nl_hdr->nlmsg_len, 0) != nl_hdr->nlmsg_len) { |
43 | + if (send (iface->sk_nl, nl_hdr, nl_hdr->nlmsg_len, 0) != nl_hdr->nlmsg_len) { |
44 | return; |
45 | } |
46 | |
47 | @@ -182,7 +182,7 @@ |
48 | struct nlmsghdr *nlh = (struct nlmsghdr*)buff; |
49 | memcpy (&from_nla, &kern_nla, sizeof (from_nla)); |
50 | |
51 | - recv_len = recvfrom (sk_nl, buff, BUFF_SIZE, 0, |
52 | + recv_len = recvfrom (iface->sk_nl, buff, BUFF_SIZE, 0, |
53 | (struct sockaddr*)&from_nla, &from_nla_len); |
54 | if (from_nla.nl_pid != 0) { |
55 | continue; |
56 | |
57 | === modified file 'lib/exec-monitor.h' |
58 | --- lib/exec-monitor.h 2016-02-21 18:52:25 +0000 |
59 | +++ lib/exec-monitor.h 2016-08-30 20:17:54 +0000 |
60 | @@ -42,6 +42,7 @@ |
61 | { |
62 | GTypeInterface parent_iface; |
63 | gboolean monitor_events; |
64 | + int sk_nl; |
65 | |
66 | void (* handle_pid) (ExecMonitor *exec_monitor, |
67 | gint pid); |
68 | |
69 | === modified file 'src/CMakeLists.txt' |
70 | --- src/CMakeLists.txt 2016-02-25 18:47:22 +0000 |
71 | +++ src/CMakeLists.txt 2016-08-30 20:17:54 +0000 |
72 | @@ -23,8 +23,10 @@ |
73 | Widgets/AppChooser.vala |
74 | Widgets/WeekSpinBox.vala |
75 | shared/Vars.vala |
76 | - shared/PAMControl.vala |
77 | shared/Utils.vala |
78 | + shared/PAM/Token.vala |
79 | + shared/PAM/Reader.vala |
80 | + shared/PAM/Writer.vala |
81 | ${CMAKE_CURRENT_BINARY_DIR}/config.vala |
82 | PACKAGES |
83 | gtk+-3.0 |
84 | @@ -38,7 +40,6 @@ |
85 | --thread |
86 | ) |
87 | |
88 | -add_subdirectory (cli) |
89 | add_subdirectory (client) |
90 | add_subdirectory (daemon) |
91 | |
92 | |
93 | === modified file 'src/Plug.vala' |
94 | --- src/Plug.vala 2016-06-16 20:22:58 +0000 |
95 | +++ src/Plug.vala 2016-08-30 20:17:54 +0000 |
96 | @@ -35,7 +35,6 @@ |
97 | private Act.UserManager usermanager; |
98 | |
99 | public MainBox () { |
100 | - Utils.set_user_name (Environment.get_user_name ()); |
101 | usermanager = Utils.get_usermanager (); |
102 | |
103 | stack = new Gtk.Stack (); |
104 | |
105 | === modified file 'src/Widgets/AppsBox.vala' |
106 | --- src/Widgets/AppsBox.vala 2016-05-19 18:58:09 +0000 |
107 | +++ src/Widgets/AppsBox.vala 2016-08-30 20:17:54 +0000 |
108 | @@ -22,12 +22,6 @@ |
109 | |
110 | namespace PC.Widgets { |
111 | public class AppsBox : Gtk.Grid { |
112 | - public signal void update_key_file (); |
113 | - |
114 | - public string[] targets = {}; |
115 | - public bool admin = false; |
116 | - public bool daemon_active = false; |
117 | - |
118 | private List<AppEntry> entries; |
119 | private Act.User user; |
120 | |
121 | @@ -37,7 +31,6 @@ |
122 | private Gtk.Button remove_button; |
123 | private Gtk.Button clear_button; |
124 | |
125 | - |
126 | protected class AppEntry : Gtk.ListBoxRow { |
127 | public signal void deleted (); |
128 | |
129 | @@ -101,7 +94,7 @@ |
130 | header_label.get_style_context ().add_class ("h4"); |
131 | |
132 | list_box = new Gtk.ListBox (); |
133 | - list_box.row_selected.connect (on_changed); |
134 | + list_box.row_selected.connect (update_sensitivity); |
135 | scrolled.add (list_box); |
136 | |
137 | var add_button = new Gtk.Button.from_icon_name ("list-add-symbolic", Gtk.IconSize.MENU); |
138 | @@ -142,25 +135,16 @@ |
139 | |
140 | admin_switch_btn = new Gtk.Switch (); |
141 | admin_switch_btn.halign = Gtk.Align.START; |
142 | - admin_switch_btn.notify["active"].connect (on_changed); |
143 | + admin_switch_btn.notify["active"].connect (update_admin); |
144 | |
145 | attach (frame, 0, 0, 2, 1); |
146 | attach (admin_label, 0, 1, 1, 1); |
147 | attach (admin_switch_btn, 1, 1, 1, 1); |
148 | |
149 | - load_existing (); |
150 | + load_existing.begin (); |
151 | show_all (); |
152 | } |
153 | |
154 | - public bool get_active () { |
155 | - return daemon_active; |
156 | - } |
157 | - |
158 | - public void set_active (bool active) { |
159 | - daemon_active = active; |
160 | - on_changed (); |
161 | - } |
162 | - |
163 | private void on_add_button_clicked () { |
164 | apps_popover.show_all (); |
165 | } |
166 | @@ -180,15 +164,17 @@ |
167 | } |
168 | |
169 | private void load_info (AppInfo info) { |
170 | - if (!get_info_loaded (info)) { |
171 | - var row = new AppEntry (info); |
172 | - row.deleted.connect (on_deleted); |
173 | - |
174 | - entries.append (row); |
175 | - list_box.add (row); |
176 | - list_box.show_all (); |
177 | - on_changed (); |
178 | + if (get_info_loaded (info)) { |
179 | + return; |
180 | } |
181 | + |
182 | + var row = new AppEntry (info); |
183 | + row.deleted.connect (on_deleted); |
184 | + |
185 | + entries.append (row); |
186 | + list_box.add (row); |
187 | + list_box.show_all (); |
188 | + update_targets (); |
189 | } |
190 | |
191 | private bool get_info_loaded (AppInfo info) { |
192 | @@ -204,39 +190,50 @@ |
193 | private void on_deleted (AppEntry row) { |
194 | entries.remove (row); |
195 | row.destroy (); |
196 | - on_changed (); |
197 | - } |
198 | - |
199 | - private void on_changed () { |
200 | + update_targets (); |
201 | + } |
202 | + |
203 | + private void update_admin () { |
204 | + update_sensitivity (); |
205 | + |
206 | + if (Utils.get_permission ().get_allowed ()) { |
207 | + Utils.get_api ().set_user_daemon_admin.begin (user.get_user_name (), admin_switch_btn.get_active ()); |
208 | + } |
209 | + } |
210 | + |
211 | + private void update_targets () { |
212 | + update_sensitivity (); |
213 | + |
214 | + if (!Utils.get_permission ().get_allowed ()) { |
215 | + return; |
216 | + } |
217 | + |
218 | + string[] targets = {}; |
219 | + foreach (var entry in entries) { |
220 | + targets += Environment.find_program_in_path (entry.get_executable ()); |
221 | + } |
222 | + |
223 | + Utils.get_api ().set_user_daemon_targets.begin (user.get_user_name (), targets); |
224 | + } |
225 | + |
226 | + private void update_sensitivity () { |
227 | remove_button.sensitive = (list_box.get_selected_row () != null); |
228 | clear_button.sensitive = (entries.length () > 0); |
229 | - |
230 | - string[] _targets = {}; |
231 | - foreach (var entry in entries) { |
232 | - _targets += Environment.find_program_in_path (entry.get_executable ()); |
233 | - } |
234 | - |
235 | - admin = admin_switch_btn.get_active (); |
236 | - targets = _targets; |
237 | - update_key_file (); |
238 | } |
239 | |
240 | - private void load_existing () { |
241 | - var key_file = new KeyFile (); |
242 | + private async void load_existing () { |
243 | try { |
244 | - key_file.load_from_file (Utils.build_daemon_conf_path (user), 0); |
245 | - string[] _targets = key_file.get_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_TARGETS); |
246 | - daemon_active = key_file.get_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ACTIVE); |
247 | + string[] targets = yield Utils.get_api ().get_user_daemon_targets (user.get_user_name ()); |
248 | + bool admin = yield Utils.get_api ().get_user_daemon_admin (user.get_user_name ()); |
249 | + admin_switch_btn.set_active (admin); |
250 | + |
251 | foreach (var info in AppInfo.get_all ()) { |
252 | - if (info.should_show () |
253 | - && Environment.find_program_in_path (info.get_executable ()) in _targets) { |
254 | + if (info.should_show () && Environment.find_program_in_path (info.get_executable ()) in targets) { |
255 | load_info (info); |
256 | } |
257 | } |
258 | - } catch (KeyFileError e) { |
259 | - warning ("%s\n", e.message); |
260 | - } catch (FileError e) { |
261 | - warning ("%s\n", e.message); |
262 | + } catch (Error e) { |
263 | + warning (e.message); |
264 | } |
265 | } |
266 | } |
267 | |
268 | === modified file 'src/Widgets/ControlPage.vala' |
269 | --- src/Widgets/ControlPage.vala 2016-05-20 13:35:36 +0000 |
270 | +++ src/Widgets/ControlPage.vala 2016-08-30 20:17:54 +0000 |
271 | @@ -29,25 +29,6 @@ |
272 | private AppsBox apps_box; |
273 | private KeyFile key_file; |
274 | |
275 | - public bool active { |
276 | - get { |
277 | - return apps_box.get_active (); |
278 | - } |
279 | - set { |
280 | - apps_box.set_active (value); |
281 | - if (Utils.get_permission ().get_allowed ()) { |
282 | - if (value) { |
283 | - general_box.refresh (); |
284 | - Utils.call_cli ({"--user", user.get_user_name (), "--enable-restrict"}); |
285 | - } else { |
286 | - general_box.set_lock_dock_active (false); |
287 | - general_box.set_printer_active (true); |
288 | - Utils.call_cli ({"--user", user.get_user_name (), "--disable-restrict"}); |
289 | - } |
290 | - } |
291 | - } |
292 | - } |
293 | - |
294 | public ControlPage (Act.User user) { |
295 | this.user = user; |
296 | |
297 | @@ -64,11 +45,9 @@ |
298 | |
299 | internet_box = new InternetBox (user); |
300 | internet_box.expand = true; |
301 | - internet_box.update_key_file.connect (on_update_key_file); |
302 | |
303 | apps_box = new AppsBox (user); |
304 | apps_box.expand = true; |
305 | - apps_box.update_key_file.connect (on_update_key_file); |
306 | |
307 | stack = new Gtk.Stack (); |
308 | stack.add_titled (general_box, "general", _("General")); |
309 | @@ -87,24 +66,35 @@ |
310 | show_all (); |
311 | } |
312 | |
313 | + public void set_active (bool active) { |
314 | + if (Utils.get_permission ().get_allowed ()) { |
315 | + Utils.get_api ().set_user_daemon_active.begin (user.get_user_name (), active); |
316 | + if (active) { |
317 | + general_box.refresh (); |
318 | + general_box.update_pam (); |
319 | + } else { |
320 | + general_box.set_lock_dock_active (false); |
321 | + general_box.set_printer_active (true); |
322 | + Utils.get_api ().remove_restriction_for_user.begin (user.get_user_name ()); |
323 | + } |
324 | + } |
325 | + } |
326 | + |
327 | + public async bool get_active () { |
328 | + try { |
329 | + return yield Utils.get_api ().get_user_daemon_active (user.get_user_name ()); |
330 | + } catch (IOError e) { |
331 | + warning (e.message); |
332 | + } |
333 | + |
334 | + return false; |
335 | + } |
336 | + |
337 | private void update_view_state () { |
338 | bool allowed = Utils.get_permission ().get_allowed (); |
339 | general_box.sensitive = allowed; |
340 | internet_box.sensitive = allowed; |
341 | apps_box.sensitive = allowed; |
342 | } |
343 | - |
344 | - private void on_update_key_file () { |
345 | - if (!Utils.get_permission ().get_allowed ()) { |
346 | - return; |
347 | - } |
348 | - |
349 | - key_file.set_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ACTIVE, apps_box.daemon_active); |
350 | - key_file.set_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_TARGETS, apps_box.targets); |
351 | - key_file.set_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ADMIN, apps_box.admin); |
352 | - key_file.set_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_BLOCK_URLS, internet_box.urls); |
353 | - |
354 | - Utils.call_cli ({ "--set-contents", key_file.to_data (), "--file", Utils.build_daemon_conf_path (user) }); |
355 | - } |
356 | } |
357 | } |
358 | |
359 | === modified file 'src/Widgets/GeneralBox.vala' |
360 | --- src/Widgets/GeneralBox.vala 2016-07-27 16:14:53 +0000 |
361 | +++ src/Widgets/GeneralBox.vala 2016-08-30 20:17:54 +0000 |
362 | @@ -50,8 +50,6 @@ |
363 | weekday_box.changed.connect (update_pam); |
364 | weekend_box.changed.connect (update_pam); |
365 | |
366 | - monitor_updates (); |
367 | - update (); |
368 | load_restrictions (); |
369 | } |
370 | |
371 | @@ -89,10 +87,10 @@ |
372 | |
373 | limit_combobox = new Gtk.ComboBoxText (); |
374 | limit_combobox.hexpand = true; |
375 | - limit_combobox.append (Vars.ALL_ID, _("On weekdays and weekends")); |
376 | - limit_combobox.append (Vars.WEEKDAYS_ID, _("Only on weekdays")); |
377 | - limit_combobox.append (Vars.WEEKENDS_ID, _("Only on weekends")); |
378 | - limit_combobox.active_id = "all"; |
379 | + limit_combobox.append (PAM.DayType.WEEKDAY.to_string () + PAM.DayType.WEEKEND.to_string (), _("On weekdays and weekends")); |
380 | + limit_combobox.append (PAM.DayType.WEEKDAY.to_string (), _("Only on weekdays")); |
381 | + limit_combobox.append (PAM.DayType.WEEKEND.to_string (), _("Only on weekends")); |
382 | + limit_combobox.active = 0; |
383 | |
384 | frame = new Gtk.Frame (null); |
385 | frame.get_style_context ().add_class (Gtk.STYLE_CLASS_VIEW); |
386 | @@ -134,104 +132,54 @@ |
387 | } |
388 | |
389 | private void load_restrictions () { |
390 | - var restricts = PAMControl.get_all_restrictions (); |
391 | - foreach (var restrict in restricts) { |
392 | - if (restrict.user == user.get_user_name ()) { |
393 | - limit_switch.active = true; |
394 | - |
395 | - limit_combobox.active_id = restrict.day_id; |
396 | - switch (restrict.day_id) { |
397 | - case Vars.ALL_ID: |
398 | - string from_weekday = restrict.weekday_hours.split ("-")[0]; |
399 | - string to_weekday = restrict.weekday_hours.split ("-")[1]; |
400 | - string from_weekend = restrict.weekend_hours.split ("-")[0]; |
401 | - string to_weekend = restrict.weekend_hours.split ("-")[1]; |
402 | - |
403 | - weekday_box.set_from (from_weekday); |
404 | - weekday_box.set_to (to_weekday); |
405 | - |
406 | - weekend_box.set_from (from_weekend); |
407 | - weekend_box.set_to (to_weekend); |
408 | - break; |
409 | - case Vars.WEEKDAYS_ID: |
410 | - weekday_box.set_from (restrict.from); |
411 | - weekday_box.set_to (restrict.to); |
412 | - break; |
413 | - case Vars.WEEKENDS_ID: |
414 | - weekend_box.set_from (restrict.from); |
415 | - weekend_box.set_to (restrict.to); |
416 | - break; |
417 | - default: |
418 | - break; |
419 | - } |
420 | + var token = PAM.Reader.get_token_for_user (Vars.PAM_TIME_CONF_PATH, user.get_user_name ()); |
421 | + if (token == null) { |
422 | + return; |
423 | + } |
424 | + |
425 | + limit_switch.active = true; |
426 | + |
427 | + string[] ids = {}; |
428 | + foreach (PAM.TimeInfo info in token.get_times_info ()) { |
429 | + ids += info.day_type.to_string (); |
430 | + switch (info.day_type) { |
431 | + case PAM.DayType.WEEKDAY: |
432 | + weekday_box.set_from (info.from); |
433 | + weekday_box.set_to (info.to); |
434 | + break; |
435 | + case PAM.DayType.WEEKEND: |
436 | + weekend_box.set_from (info.from); |
437 | + weekend_box.set_to (info.to); |
438 | + break; |
439 | + default: |
440 | + break; |
441 | } |
442 | } |
443 | + |
444 | + if (ids.length > 0) { |
445 | + limit_combobox.active_id = string.joinv ("|", ids); |
446 | + } |
447 | } |
448 | |
449 | - private void update_pam () { |
450 | - string restrict = ""; |
451 | + public void update_pam () { |
452 | + if (!Utils.get_permission ().get_allowed ()) { |
453 | + return; |
454 | + } |
455 | + |
456 | + string[] times = {}; |
457 | + string[] users = { user.get_user_name () }; |
458 | string id = limit_combobox.get_active_id (); |
459 | - switch (id) { |
460 | - case Vars.ALL_ID: |
461 | - restrict = generate_pam_conf_restriction (id, weekday_box.get_from (), weekday_box.get_to ()); |
462 | - restrict += "|" + weekend_box.get_from () + "-" + weekend_box.get_to (); |
463 | - break; |
464 | - case Vars.WEEKDAYS_ID: |
465 | - restrict = generate_pam_conf_restriction (id, weekday_box.get_from (), weekday_box.get_to ()); |
466 | - break; |
467 | - case Vars.WEEKENDS_ID: |
468 | - restrict = generate_pam_conf_restriction (id, weekend_box.get_from (), weekend_box.get_to ()); |
469 | - break; |
470 | - } |
471 | - |
472 | - PAMControl.try_add_restrict_line (user.get_user_name (), restrict); |
473 | - } |
474 | - |
475 | - private string generate_pam_conf_restriction (string id, string from, string to) { |
476 | - string retval = "*;*;"; |
477 | - string days = ""; |
478 | - switch (id) { |
479 | - case Vars.ALL_ID: |
480 | - days = "Al"; |
481 | - break; |
482 | - case Vars.WEEKDAYS_ID: |
483 | - days = "Wk"; |
484 | - break; |
485 | - case Vars.WEEKENDS_ID: |
486 | - days = "Wd"; |
487 | - break; |
488 | - } |
489 | - |
490 | - retval += user.get_user_name () + ";" + days + from + "-" + to; |
491 | - return retval; |
492 | - } |
493 | - |
494 | - private void monitor_updates () { |
495 | - try { |
496 | - var monitor = File.new_for_path (plank_conf_file_path).monitor_file (FileMonitorFlags.NONE); |
497 | - monitor.changed.connect (update); |
498 | - } catch (IOError e) { |
499 | - warning ("%s\n", e.message); |
500 | - } |
501 | - } |
502 | - |
503 | - private void update () { |
504 | - var key_file = new KeyFile (); |
505 | - try { |
506 | - key_file.load_from_file (plank_conf_file_path, KeyFileFlags.NONE); |
507 | - dock_btn.active = !key_file.get_boolean (Vars.PLANK_CONF_GROUP, Vars.PLANK_CONF_LOCK_ITEMS_KEY); |
508 | - } catch (FileError e) { |
509 | - dock_btn.active = true; |
510 | - warning ("%s\n", e.message); |
511 | - } catch (Error e) { |
512 | - dock_btn.active = true; |
513 | - warning ("%s\n", e.message); |
514 | - } |
515 | - |
516 | - /* TODO: Get denied users for printing configuration */ |
517 | - |
518 | - /* For now, we assume that printing is enabled */ |
519 | - print_btn.active = true; |
520 | + |
521 | + if (PAM.DayType.WEEKDAY.to_string () in id) { |
522 | + times += PAM.DayType.WEEKDAY.to_string () + weekday_box.get_from () + "-" + weekday_box.get_to (); |
523 | + } |
524 | + |
525 | + if (PAM.DayType.WEEKEND.to_string () in id) { |
526 | + times += PAM.DayType.WEEKEND.to_string () + weekend_box.get_from () + "-" + weekend_box.get_to (); |
527 | + } |
528 | + |
529 | + string input = PAM.Token.construct_pam_restriction_simple (users, times); |
530 | + Utils.get_api ().add_restriction_for_user.begin (input, true); |
531 | } |
532 | |
533 | private void on_dock_btn_activate () { |
534 | @@ -240,7 +188,7 @@ |
535 | |
536 | public void set_lock_dock_active (bool active) { |
537 | if (Utils.get_permission ().get_allowed ()) { |
538 | - Utils.call_cli ({"--user", user.get_user_name (), "--lock-dock", active.to_string ()}); |
539 | + Utils.get_api ().lock_dock_icons_for_user.begin (user.get_user_name (), active); |
540 | } |
541 | } |
542 | |
543 | @@ -272,25 +220,23 @@ |
544 | private void on_limit_switch_changed () { |
545 | if (limit_switch.get_active ()) { |
546 | update_pam (); |
547 | - } else { |
548 | - PAMControl.try_remove_user_restrict (user.get_user_name ()); |
549 | + } else if (Utils.get_permission ().get_allowed ()) { |
550 | + Utils.get_api ().remove_restriction_for_user.begin (user.get_user_name ()); |
551 | } |
552 | } |
553 | |
554 | private void on_limit_combobox_changed () { |
555 | - switch (limit_combobox.get_active_id ()) { |
556 | - case Vars.ALL_ID: |
557 | - weekday_box.sensitive = true; |
558 | - weekend_box.sensitive = true; |
559 | - break; |
560 | - case Vars.WEEKDAYS_ID: |
561 | - weekday_box.sensitive = true; |
562 | - weekend_box.sensitive = false; |
563 | - break; |
564 | - case Vars.WEEKENDS_ID: |
565 | - weekday_box.sensitive = false; |
566 | - weekend_box.sensitive = true; |
567 | - break; |
568 | + string id = limit_combobox.get_active_id (); |
569 | + |
570 | + if (PAM.DayType.WEEKDAY.to_string () in id && PAM.DayType.WEEKEND.to_string () in id) { |
571 | + weekday_box.sensitive = true; |
572 | + weekend_box.sensitive = true; |
573 | + } else if (PAM.DayType.WEEKDAY.to_string () in id) { |
574 | + weekday_box.sensitive = true; |
575 | + weekend_box.sensitive = false; |
576 | + } else if (PAM.DayType.WEEKEND.to_string () in id) { |
577 | + weekday_box.sensitive = false; |
578 | + weekend_box.sensitive = true; |
579 | } |
580 | |
581 | update_pam (); |
582 | |
583 | === modified file 'src/Widgets/InternetBox.vala' |
584 | --- src/Widgets/InternetBox.vala 2016-05-19 18:58:09 +0000 |
585 | +++ src/Widgets/InternetBox.vala 2016-08-30 20:17:54 +0000 |
586 | @@ -22,7 +22,6 @@ |
587 | |
588 | namespace PC.Widgets { |
589 | public class InternetBox : Gtk.Grid { |
590 | - public signal void update_key_file (); |
591 | public string[] urls; |
592 | |
593 | private const string URL_REGEX_RULE = "[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,4}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)"; |
594 | @@ -118,16 +117,14 @@ |
595 | frame.add (main_box); |
596 | |
597 | add (frame); |
598 | - load_existing (); |
599 | + load_existing.begin (); |
600 | show_all (); |
601 | } |
602 | |
603 | - private void load_existing () { |
604 | - var key_file = new KeyFile (); |
605 | + private async void load_existing () { |
606 | try { |
607 | - key_file.load_from_file (Utils.build_daemon_conf_path (user), 0); |
608 | - urls = key_file.get_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_BLOCK_URLS); |
609 | - foreach (string url in urls) { |
610 | + string[] block_urls = yield Utils.get_api ().get_user_daemon_block_urls (user.get_user_name ()); |
611 | + foreach (string url in block_urls) { |
612 | add_entry (new UrlEntry (url)); |
613 | } |
614 | } catch (Error e) { |
615 | @@ -135,14 +132,17 @@ |
616 | } |
617 | } |
618 | |
619 | - private void update () { |
620 | - string[] _urls = {}; |
621 | + private void update_block_urls () { |
622 | + if (!Utils.get_permission ().get_allowed ()) { |
623 | + return; |
624 | + } |
625 | + |
626 | + string[] block_urls = {}; |
627 | foreach (var url_entry in url_list) { |
628 | - _urls += url_entry.get_url (); |
629 | + block_urls += url_entry.get_url (); |
630 | } |
631 | |
632 | - urls = _urls; |
633 | - update_key_file (); |
634 | + Utils.get_api ().set_user_daemon_block_urls.begin (user.get_user_name (), block_urls); |
635 | } |
636 | |
637 | private void on_entry_changed () { |
638 | @@ -173,7 +173,7 @@ |
639 | add_entry (url_entry); |
640 | |
641 | entry.text = ""; |
642 | - update (); |
643 | + update_block_urls (); |
644 | } |
645 | |
646 | private void add_entry (UrlEntry url_entry) { |
647 | @@ -186,7 +186,7 @@ |
648 | private void on_url_entry_deleted (UrlEntry url_entry) { |
649 | url_list.remove (url_entry); |
650 | list_box.remove (url_entry); |
651 | - update (); |
652 | + update_block_urls (); |
653 | } |
654 | } |
655 | } |
656 | |
657 | === modified file 'src/Widgets/UserItem.vala' |
658 | --- src/Widgets/UserItem.vala 2016-05-20 21:18:29 +0000 |
659 | +++ src/Widgets/UserItem.vala 2016-08-30 20:17:54 +0000 |
660 | @@ -64,7 +64,10 @@ |
661 | grid.attach (username_label, 1, 1, 1, 1); |
662 | grid.attach (master_switch, 2, 0, 1, 2); |
663 | |
664 | - master_switch.bind_property ("active", page, "active", BindingFlags.DEFAULT); |
665 | + master_switch.notify["active"].connect (() => { |
666 | + page.set_active (master_switch.get_active ()); |
667 | + }); |
668 | + |
669 | master_switch.bind_property ("active", page.stack, "sensitive", BindingFlags.SYNC_CREATE); |
670 | |
671 | Utils.get_permission ().notify["allowed"].connect (update_view); |
672 | @@ -75,7 +78,10 @@ |
673 | } |
674 | |
675 | public void update_view () { |
676 | - master_switch.active = page.active; |
677 | + page.get_active.begin ((obj, res) => { |
678 | + master_switch.active = page.get_active.end (res); |
679 | + }); |
680 | + |
681 | master_switch.sensitive = Utils.get_permission ().get_allowed (); |
682 | |
683 | try { |
684 | |
685 | === modified file 'src/Widgets/WeekSpinBox.vala' |
686 | --- src/Widgets/WeekSpinBox.vala 2016-05-20 21:48:27 +0000 |
687 | +++ src/Widgets/WeekSpinBox.vala 2016-08-30 20:17:54 +0000 |
688 | @@ -32,14 +32,14 @@ |
689 | spacing = 12; |
690 | |
691 | picker_from = new Granite.Widgets.TimePicker (); |
692 | + picker_from.time_changed.connect (() => changed ()); |
693 | + |
694 | picker_to = new Granite.Widgets.TimePicker (); |
695 | + picker_to.time_changed.connect (() => changed ()); |
696 | |
697 | var label = new Gtk.Label (title); |
698 | label.get_style_context ().add_class ("h4"); |
699 | |
700 | - picker_from.time_changed.connect (_changed); |
701 | - picker_to.time_changed.connect (_changed); |
702 | - |
703 | add (label); |
704 | add (new Gtk.Label (_("From:"))); |
705 | add (picker_from); |
706 | @@ -59,27 +59,21 @@ |
707 | } |
708 | |
709 | public void set_from (string from) { |
710 | - char[] data = from.to_utf8 (); |
711 | - string hours = data[0].to_string () + data[1].to_string (); |
712 | - string minutes = data[2].to_string () + data[3].to_string (); |
713 | + string hours = from.slice (0, 2); |
714 | + string minutes = from.substring (2); |
715 | |
716 | var time = new DateTime.local (new DateTime.now_local ().get_year (), 1, 1, int.parse (hours), int.parse (minutes), 0); |
717 | picker_from.time = time; |
718 | } |
719 | |
720 | public void set_to (string to) { |
721 | - char[] data = to.to_utf8 (); |
722 | - string hours = data[0].to_string () + data[1].to_string (); |
723 | - string minutes = data[2].to_string () + data[3].to_string (); |
724 | + string hours = to.slice (0, 2); |
725 | + string minutes = to.substring (2); |
726 | |
727 | var time = new DateTime.local (new DateTime.now_local ().get_year (), 1, 1, int.parse (hours), int.parse (minutes), 0); |
728 | picker_to.time = time; |
729 | } |
730 | |
731 | - private void _changed () { |
732 | - changed (); |
733 | - } |
734 | - |
735 | private string format_time_string (int val) { |
736 | if (val < 10) { |
737 | return "0" + val.to_string (); |
738 | |
739 | === removed directory 'src/cli' |
740 | === removed file 'src/cli/Application.vala' |
741 | --- src/cli/Application.vala 2016-05-18 15:29:00 +0000 |
742 | +++ src/cli/Application.vala 1970-01-01 00:00:00 +0000 |
743 | @@ -1,191 +0,0 @@ |
744 | -// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
745 | -/*- |
746 | - * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls) |
747 | - * |
748 | - * This library is free software; you can redistribute it and/or |
749 | - * modify it under the terms of the GNU Library General Public |
750 | - * License as published by the Free Software Foundation; either |
751 | - * version 3 of the License, or (at your option) any later version. |
752 | - * |
753 | - * This library is distributed in the hope that it will be useful, |
754 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
755 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
756 | - * Library General Public License for more details. |
757 | - * |
758 | - * You should have received a copy of the GNU Library General Public |
759 | - * License along with this library; if not, write to the |
760 | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
761 | - * Boston, MA 02111-1307, USA. |
762 | - * |
763 | - * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
764 | - */ |
765 | - |
766 | -namespace PC.Cli { |
767 | - public class App : Application { |
768 | - private const string TIME_CONF_FILE = "/etc/security/time.conf"; |
769 | - private string plank_conf_file_path = ""; |
770 | - |
771 | - public App () { |
772 | - Object (flags: ApplicationFlags.HANDLES_COMMAND_LINE); |
773 | - } |
774 | - |
775 | - public static int main (string[] args) { |
776 | - var app = new App (); |
777 | - return app.run (args); |
778 | - } |
779 | - |
780 | - private int _command_line (ApplicationCommandLine command_line) { |
781 | - string? user = null; |
782 | - string? restrict_pam_line = null; |
783 | - string? lock_dock = null; |
784 | - string? set_contents = null; |
785 | - string? file = null; |
786 | - |
787 | - bool remove_restrict = false; |
788 | - bool enable_restrict = false; |
789 | - bool disable_restrict = false; |
790 | - |
791 | - var options = new OptionEntry[9]; |
792 | - options[0] = { "user", 0, 0, OptionArg.STRING, ref user, "Use specific user", null }; |
793 | - options[1] = { "lock-dock", 0, 0, OptionArg.STRING, ref lock_dock, "Lock the given user dock", null }; |
794 | - options[2] = { "restrict-pam-line", 0, 0, OptionArg.STRING, ref restrict_pam_line, "Add specified line to pam configuration", null }; |
795 | - options[3] = { "remove-restrict", 0, 0, OptionArg.NONE, ref remove_restrict, "Remove all time restrictions for specified user", null }; |
796 | - options[4] = { "set-contents", 0, 0, OptionArg.STRING, ref set_contents, "Set contents of specified filename", null }; |
797 | - options[5] = { "file", 0, 0, OptionArg.FILENAME, ref file, "A file to write contents to", null }; |
798 | - options[6] = { "enable-restrict", 0, 0, OptionArg.NONE, ref enable_restrict, "Enable PAM restrictions for the user", null }; |
799 | - options[7] = { "disable-restrict", 0, 0, OptionArg.NONE, ref disable_restrict, "Disable PAM restrictions for the user", null }; |
800 | - |
801 | - string[] args = command_line.get_arguments (); |
802 | - string*[] _args = new string[args.length]; |
803 | - for (int i = 0; i < args.length; i++) { |
804 | - _args[i] = args[i]; |
805 | - } |
806 | - |
807 | - try { |
808 | - var opt_context = new OptionContext ("context"); |
809 | - opt_context.set_help_enabled (true); |
810 | - opt_context.add_main_entries (options, null); |
811 | - unowned string[] tmp = _args; |
812 | - opt_context.parse (ref tmp); |
813 | - } catch (OptionError e) { |
814 | - command_line.print ("error: %s\n", e.message); |
815 | - command_line.print ("Run '%s --help' to see a full list of available command line options.\n", args[0]); |
816 | - return 1; |
817 | - } |
818 | - |
819 | - if (Posix.getuid () != 0) { |
820 | - command_line.print ("Error: To run this program you need root privigiles\n\n"); |
821 | - Process.exit (1); |
822 | - } |
823 | - |
824 | - if (remove_restrict && user != "") { |
825 | - var pam_writer = new PAMWriter (File.new_for_path (TIME_CONF_FILE)); |
826 | - pam_writer.remove_user_restrictions (user); |
827 | - } |
828 | - |
829 | - if (enable_restrict && user != "") { |
830 | - var pam_writer = new PAMWriter (File.new_for_path (TIME_CONF_FILE)); |
831 | - pam_writer.modify_user_restrictions (user, true); |
832 | - } |
833 | - |
834 | - if (disable_restrict && user != "") { |
835 | - var pam_writer = new PAMWriter (File.new_for_path (TIME_CONF_FILE)); |
836 | - pam_writer.modify_user_restrictions (user, false); |
837 | - } |
838 | - |
839 | - if (restrict_pam_line != null && user != null) { |
840 | - ensure_pam_lightdm_enabled (); |
841 | - |
842 | - var pam_writer = new PAMWriter (File.new_for_path (TIME_CONF_FILE)); |
843 | - pam_writer.add_conf_line (restrict_pam_line, user); |
844 | - } |
845 | - |
846 | - if (user != null && lock_dock != null) { |
847 | - var loop = new MainLoop (); |
848 | - |
849 | - Utils.get_usermanager ().notify["is-loaded"].connect (() => { |
850 | - if (Utils.get_usermanager ().is_loaded) { |
851 | - lock_dock_for_user (user, bool.parse (lock_dock)); |
852 | - loop.quit (); |
853 | - } |
854 | - }); |
855 | - |
856 | - loop.run (); |
857 | - } |
858 | - |
859 | - if (set_contents != null && file != null) { |
860 | - set_file_contents (file, set_contents); |
861 | - } |
862 | - |
863 | - return 0; |
864 | - } |
865 | - |
866 | - private void set_file_contents (string path, string contents) { |
867 | - var file = File.new_for_path (path); |
868 | - if (!file.query_exists ()) { |
869 | - try { |
870 | - var os = file.create (FileCreateFlags.REPLACE_DESTINATION); |
871 | - os.write (contents.data); |
872 | - } catch (Error e) { |
873 | - warning ("%s\n", e.message); |
874 | - } |
875 | - } else { |
876 | - try { |
877 | - FileUtils.set_contents (path, contents); |
878 | - } catch (Error e) { |
879 | - warning ("%s\n", e.message); |
880 | - } |
881 | - } |
882 | - } |
883 | - |
884 | - private void ensure_pam_lightdm_enabled () { |
885 | - string path = "/etc/pam.d/lightdm"; |
886 | - string contents = ""; |
887 | - try { |
888 | - FileUtils.get_contents (path, out contents); |
889 | - } catch (FileError e) { |
890 | - warning ("%s\n", e.message); |
891 | - } |
892 | - |
893 | - string conf_line = "\naccount required pam_time.so"; |
894 | - if (!(conf_line in contents)) { |
895 | - contents += conf_line; |
896 | - |
897 | - try { |
898 | - FileUtils.set_contents (path, contents); |
899 | - } catch (FileError e) { |
900 | - warning ("%s\n", e.message); |
901 | - } |
902 | - } |
903 | - } |
904 | - |
905 | - private void lock_dock_for_user (string user, bool lock) { |
906 | - plank_conf_file_path = Path.build_filename (Utils.get_usermanager ().get_user (user).get_home_dir (), Vars.PLANK_CONF_DIR); |
907 | - if (plank_conf_file_path != "" && File.new_for_path (plank_conf_file_path).query_exists ()) { |
908 | - var key_file = new KeyFile (); |
909 | - try { |
910 | - key_file.load_from_file (plank_conf_file_path, KeyFileFlags.KEEP_COMMENTS | KeyFileFlags.KEEP_TRANSLATIONS); |
911 | - } catch (KeyFileError e) { |
912 | - warning ("%s\n", e.message); |
913 | - } catch (FileError e) { |
914 | - warning ("%s\n", e.message); |
915 | - } |
916 | - |
917 | - key_file.set_boolean (Vars.PLANK_CONF_GROUP, Vars.PLANK_CONF_LOCK_ITEMS_KEY, lock); |
918 | - |
919 | - try { |
920 | - key_file.save_to_file (plank_conf_file_path); |
921 | - } catch (FileError e) { |
922 | - warning ("%s\n", e.message); |
923 | - } |
924 | - } |
925 | - } |
926 | - |
927 | - public override int command_line (ApplicationCommandLine command_line) { |
928 | - this.hold (); |
929 | - int res = _command_line (command_line); |
930 | - this.release (); |
931 | - return res; |
932 | - } |
933 | - } |
934 | -} |
935 | \ No newline at end of file |
936 | |
937 | === removed file 'src/cli/CMakeLists.txt' |
938 | --- src/cli/CMakeLists.txt 2016-03-06 18:26:44 +0000 |
939 | +++ src/cli/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
940 | @@ -1,28 +0,0 @@ |
941 | -find_package (PkgConfig) |
942 | - |
943 | -pkg_check_modules (CLI_DEPS REQUIRED glib-2.0 gio-2.0 polkit-gobject-1 accountsservice) |
944 | -add_definitions (${CLI_DEPS_CFLAGS}) |
945 | -link_directories (${CLI_DEPS_LIBRARY_DIRS}) |
946 | - |
947 | -set (CLI_EXEC_NAME pantheon-parental-controls-cli) |
948 | - |
949 | -vala_precompile (VALA_C ${CLI_EXEC_NAME} |
950 | - Application.vala |
951 | - PAMWriter.vala |
952 | - ${CMAKE_SOURCE_DIR}/src/shared/Vars.vala |
953 | - ${CMAKE_SOURCE_DIR}/src/shared/Utils.vala |
954 | -PACKAGES |
955 | - gio-2.0 |
956 | - accountsservice |
957 | - polkit-gobject-1 |
958 | - posix |
959 | -OPTIONS |
960 | - --vapidir=${CMAKE_SOURCE_DIR}/vapi/ |
961 | - --thread |
962 | -) |
963 | - |
964 | -add_executable (${CLI_EXEC_NAME} ${VALA_C}) |
965 | -target_link_libraries (${CLI_EXEC_NAME} ${DEPS_LIBRARIES}) |
966 | - |
967 | -# Installation |
968 | -install (TARGETS ${CLI_EXEC_NAME} RUNTIME DESTINATION bin) |
969 | \ No newline at end of file |
970 | |
971 | === removed file 'src/cli/PAMWriter.vala' |
972 | --- src/cli/PAMWriter.vala 2016-03-06 18:26:44 +0000 |
973 | +++ src/cli/PAMWriter.vala 1970-01-01 00:00:00 +0000 |
974 | @@ -1,204 +0,0 @@ |
975 | -// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
976 | -/*- |
977 | - * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls) |
978 | - * |
979 | - * This library is free software; you can redistribute it and/or |
980 | - * modify it under the terms of the GNU Library General Public |
981 | - * License as published by the Free Software Foundation; either |
982 | - * version 3 of the License, or (at your option) any later version. |
983 | - * |
984 | - * This library is distributed in the hope that it will be useful, |
985 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
986 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
987 | - * Library General Public License for more details. |
988 | - * |
989 | - * You should have received a copy of the GNU Library General Public |
990 | - * License along with this library; if not, write to the |
991 | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
992 | - * Boston, MA 02111-1307, USA. |
993 | - * |
994 | - * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
995 | - */ |
996 | - |
997 | -namespace PC.Cli { |
998 | - public class PAMWriter : Object { |
999 | - public File file; |
1000 | - |
1001 | - public PAMWriter (File file) { |
1002 | - this.file = file; |
1003 | - } |
1004 | - |
1005 | - public string get_conf_section () { |
1006 | - string contents = read_contents (file); |
1007 | - try { |
1008 | - var regex = new Regex (Vars.PAM_CONF_REGEX); |
1009 | - |
1010 | - if (regex.match (contents)) { |
1011 | - int i = 0; |
1012 | - foreach (string str in regex.split (contents)) { |
1013 | - // Do not replace the contents of the PC plug section |
1014 | - if (i != 1) { |
1015 | - contents = contents.replace (str, ""); |
1016 | - } |
1017 | - |
1018 | - i++; |
1019 | - } |
1020 | - } else { |
1021 | - return ""; |
1022 | - } |
1023 | - } catch (RegexError e) { |
1024 | - warning ("%s\n", e.message); |
1025 | - } |
1026 | - |
1027 | - |
1028 | - return contents; |
1029 | - } |
1030 | - |
1031 | - public void remove_conf_section () { |
1032 | - string contents = read_contents (file); |
1033 | - string final_contents = contents.replace (get_conf_section (), ""); |
1034 | - |
1035 | - try { |
1036 | - FileUtils.set_contents (file.get_path (), final_contents); |
1037 | - } catch (FileError e) { |
1038 | - warning ("%s\n", e.message); |
1039 | - } |
1040 | - } |
1041 | - |
1042 | - public void remove_user_restrictions (string user) { |
1043 | - string contents = read_contents (file); |
1044 | - string conf_section = get_conf_section (); |
1045 | - |
1046 | - string new_conf = ""; |
1047 | - if (conf_section != "" && user != "") { |
1048 | - int i = 0; |
1049 | - string[] split = conf_section.split ("\n"); |
1050 | - foreach (string section_line in split) { |
1051 | - bool contains = (user in section_line); |
1052 | - if (!contains) { |
1053 | - if (i > 0) { |
1054 | - new_conf += "\n"; |
1055 | - } |
1056 | - |
1057 | - new_conf += section_line; |
1058 | - } |
1059 | - |
1060 | - i++; |
1061 | - } |
1062 | - |
1063 | - try { |
1064 | - FileUtils.set_contents (file.get_path (), contents.replace (conf_section, new_conf)); |
1065 | - } catch (FileError e) { |
1066 | - warning ("%s\n", e.message); |
1067 | - } |
1068 | - } |
1069 | - } |
1070 | - |
1071 | - public void modify_user_restrictions (string user, bool enable) { |
1072 | - string contents = read_contents (file); |
1073 | - string conf_section = get_conf_section (); |
1074 | - |
1075 | - string new_conf = ""; |
1076 | - if (conf_section != "" && user != "") { |
1077 | - int i = 0; |
1078 | - string[] split = conf_section.split ("\n"); |
1079 | - foreach (string section_line in split) { |
1080 | - if (i > 0) { |
1081 | - new_conf += "\n"; |
1082 | - } |
1083 | - |
1084 | - bool contains = (user in section_line); |
1085 | - if (!contains) { |
1086 | - new_conf += section_line; |
1087 | - } else { |
1088 | - string prefix = "#"; |
1089 | - if (enable) { |
1090 | - prefix = ""; |
1091 | - section_line = section_line.replace ("#", ""); |
1092 | - } |
1093 | - |
1094 | - new_conf += prefix + section_line; |
1095 | - } |
1096 | - |
1097 | - i++; |
1098 | - } |
1099 | - |
1100 | - try { |
1101 | - FileUtils.set_contents (file.get_path (), contents.replace (conf_section, new_conf)); |
1102 | - } catch (FileError e) { |
1103 | - warning ("%s\n", e.message); |
1104 | - } |
1105 | - } |
1106 | - } |
1107 | - |
1108 | - public void add_conf_line (string line, string? user = null) { |
1109 | - string contents = read_contents (file); |
1110 | - string conf_section = get_conf_section (); |
1111 | - |
1112 | - string new_conf = ""; |
1113 | - if (conf_section != "" && user != null) { |
1114 | - int i = 0; |
1115 | - string[] split = conf_section.split ("\n"); |
1116 | - foreach (string section_line in split) { |
1117 | - bool contains = (user in section_line); |
1118 | - if (!contains) { |
1119 | - if (i > 0) { |
1120 | - new_conf += "\n"; |
1121 | - } |
1122 | - |
1123 | - new_conf += section_line; |
1124 | - } |
1125 | - |
1126 | - i++; |
1127 | - } |
1128 | - |
1129 | - try { |
1130 | - FileUtils.set_contents (file.get_path (), contents.replace (conf_section, new_conf)); |
1131 | - } catch (FileError e) { |
1132 | - warning ("%s\n", e.message); |
1133 | - } |
1134 | - |
1135 | - contents = read_contents (file); |
1136 | - conf_section = get_conf_section (); |
1137 | - } |
1138 | - |
1139 | - |
1140 | - string final_contents = ""; |
1141 | - |
1142 | - if (conf_section == "") { |
1143 | - final_contents = contents + |
1144 | - "\n" + |
1145 | - Vars.PAM_CONF_START + |
1146 | - "\n" + |
1147 | - line + |
1148 | - "\n" + |
1149 | - Vars.PAM_CONF_END; |
1150 | - } else { |
1151 | - final_contents = conf_section.replace (Vars.PAM_CONF_END, ""); |
1152 | - final_contents += line + "\n" + Vars.PAM_CONF_END; |
1153 | - final_contents = contents.replace (conf_section, final_contents); |
1154 | - } |
1155 | - |
1156 | - try { |
1157 | - FileUtils.set_contents (file.get_path (), final_contents); |
1158 | - } catch (FileError e) { |
1159 | - warning ("%s\n", e.message); |
1160 | - } |
1161 | - } |
1162 | - |
1163 | - private string read_contents (File file) { |
1164 | - string data = ""; |
1165 | - if (!file.query_exists ()) { |
1166 | - return ""; |
1167 | - } |
1168 | - |
1169 | - try { |
1170 | - FileUtils.get_contents (file.get_path (), out data); |
1171 | - } catch (FileError e) { |
1172 | - warning ("%s\n", e.message); |
1173 | - } |
1174 | - |
1175 | - return data; |
1176 | - } |
1177 | - } |
1178 | -} |
1179 | \ No newline at end of file |
1180 | |
1181 | === renamed file 'src/client/AppLockDialog.vala' => 'src/client/AppUnavailableDialog.vala' |
1182 | --- src/client/AppLockDialog.vala 2016-02-25 18:47:22 +0000 |
1183 | +++ src/client/AppUnavailableDialog.vala 2016-08-30 20:17:54 +0000 |
1184 | @@ -20,9 +20,9 @@ |
1185 | * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
1186 | */ |
1187 | |
1188 | -namespace AppLock { |
1189 | - public class AppLockDialog : Gtk.MessageDialog { |
1190 | - public AppLockDialog () { |
1191 | +namespace PC.Client { |
1192 | + public class AppUnavailableDialog : Gtk.MessageDialog { |
1193 | + public AppUnavailableDialog () { |
1194 | deletable = false; |
1195 | text = _("You cannot run this application"); |
1196 | secondary_text = _("You are not permitted to run this application."); |
1197 | |
1198 | === modified file 'src/client/CMakeLists.txt' |
1199 | --- src/client/CMakeLists.txt 2016-02-25 18:47:22 +0000 |
1200 | +++ src/client/CMakeLists.txt 2016-08-30 20:17:54 +0000 |
1201 | @@ -8,11 +8,13 @@ |
1202 | |
1203 | vala_precompile (VALA_C ${CLIENT_EXEC_NAME} |
1204 | Client.vala |
1205 | - AppLockDialog.vala |
1206 | + AppUnavailableDialog.vala |
1207 | ${CMAKE_SOURCE_DIR}/src/shared/Vars.vala |
1208 | + ${CMAKE_SOURCE_DIR}/src/shared/Utils.vala |
1209 | PACKAGES |
1210 | posix |
1211 | polkit-gobject-1 |
1212 | + accountsservice |
1213 | gio-2.0 |
1214 | gtk+-3.0 |
1215 | OPTIONS |
1216 | |
1217 | === modified file 'src/client/Client.vala' |
1218 | --- src/client/Client.vala 2016-07-31 00:18:06 +0000 |
1219 | +++ src/client/Client.vala 2016-08-30 20:17:54 +0000 |
1220 | @@ -20,19 +20,8 @@ |
1221 | * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
1222 | */ |
1223 | |
1224 | - namespace PC.Client { |
1225 | - [DBus (name = "org.pantheon.ParentalControls")] |
1226 | - public interface ParentalControls : Object { |
1227 | - public signal void show_app_lock_dialog (); |
1228 | - public signal void authorize (string user, string action_id); |
1229 | - public signal void launch (string[] args); |
1230 | - public signal void send_time_notification (int hours, int minutes); |
1231 | - |
1232 | - public abstract void end_authorization (int client_pid) throws IOError; |
1233 | - } |
1234 | - |
1235 | +namespace PC.Client { |
1236 | public class Client : Gtk.Application { |
1237 | - private ParentalControls? parental_controls; |
1238 | private Polkit.Permission? permission = null; |
1239 | |
1240 | public static int main (string[] args) { |
1241 | @@ -43,31 +32,22 @@ |
1242 | } |
1243 | |
1244 | public override void activate () { |
1245 | - try { |
1246 | - parental_controls = Bus.get_proxy_sync (BusType.SYSTEM, Vars.PARENTAL_CONTROLS_IFACE, Vars.PARENTAL_CONTROLS_OBJECT_PATH); |
1247 | - } catch (Error e) { |
1248 | - warning ("%s\n", e.message); |
1249 | - return; |
1250 | - } |
1251 | - |
1252 | - if (parental_controls == null) { |
1253 | - return; |
1254 | - } |
1255 | - |
1256 | - parental_controls.show_app_lock_dialog.connect (on_show_app_lock_dialog); |
1257 | - parental_controls.authorize.connect (on_authorize); |
1258 | - parental_controls.launch.connect (on_launch); |
1259 | - parental_controls.send_time_notification.connect (on_send_time_notification); |
1260 | + var api = Utils.get_api (); |
1261 | + |
1262 | + api.show_app_unavailable.connect (on_show_app_unavailable); |
1263 | + api.app_authorize.connect (on_authorize); |
1264 | + api.launch.connect (on_launch); |
1265 | + api.show_timeout.connect (on_show_timeout); |
1266 | |
1267 | Gtk.main (); |
1268 | } |
1269 | |
1270 | - private void on_show_app_lock_dialog () { |
1271 | - var app_lock_dialog = new AppLock.AppLockDialog (); |
1272 | + private void on_show_app_unavailable (string path) { |
1273 | + var app_lock_dialog = new AppUnavailableDialog (); |
1274 | app_lock_dialog.show_all (); |
1275 | } |
1276 | |
1277 | - private void on_authorize (string user_name, string action_id) { |
1278 | + private void on_authorize (string username, string path, string action_id) { |
1279 | if (permission != null && permission.get_can_release ()) { |
1280 | try { |
1281 | permission.release (); |
1282 | @@ -77,36 +57,26 @@ |
1283 | } |
1284 | |
1285 | try { |
1286 | - var user = (Polkit.UnixUser)Polkit.UnixUser.new_for_name (user_name); |
1287 | + var user = (Polkit.UnixUser)Polkit.UnixUser.new_for_name (username); |
1288 | permission = new Polkit.Permission.sync (action_id, |
1289 | Polkit.UnixProcess.new_for_owner (Posix.getpid (), 0, user.get_uid ())); |
1290 | } catch (Error e) { |
1291 | warning ("%s\n", e.message); |
1292 | } |
1293 | |
1294 | + ulong signal_id = 0; |
1295 | + signal_id = permission.notify["allowed"].connect (() => { |
1296 | + Utils.get_api ().end_app_authorization.begin (); |
1297 | + permission.disconnect (signal_id); |
1298 | + }); |
1299 | + |
1300 | permission.acquire_async.begin (); |
1301 | - permission.notify["allowed"].connect (() => { |
1302 | - if (parental_controls != null) { |
1303 | - try { |
1304 | - parental_controls.end_authorization (Posix.getpid ()); |
1305 | - } catch (IOError e) { |
1306 | - warning ("%s\n", e.message); |
1307 | - } |
1308 | - } |
1309 | - }); |
1310 | } |
1311 | |
1312 | private void on_launch (string[] args) { |
1313 | - string[] _args = {}; |
1314 | - for (int i = 0; i < args.length; i++) { |
1315 | - if (args[i].strip () != "") { |
1316 | - _args[i] = args[i]; |
1317 | - } |
1318 | - } |
1319 | - |
1320 | try { |
1321 | GLib.Process.spawn_async ("/", |
1322 | - _args, |
1323 | + args, |
1324 | Environ.get (), |
1325 | SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD, |
1326 | null, |
1327 | @@ -117,7 +87,7 @@ |
1328 | } |
1329 | |
1330 | |
1331 | - private void on_send_time_notification (int hours, int minutes) { |
1332 | + private void on_show_timeout (int hours, int minutes) { |
1333 | string hours_str = ""; |
1334 | string minutes_str = ""; |
1335 | string info = ""; |
1336 | @@ -138,8 +108,8 @@ |
1337 | var notification = new Notification (_("Time left")); |
1338 | var icon = new ThemedIcon ("dialog-warning"); |
1339 | notification.set_icon (icon); |
1340 | - |
1341 | notification.set_body (body); |
1342 | + |
1343 | send_notification (null, notification); |
1344 | } |
1345 | } |
1346 | |
1347 | === modified file 'src/daemon/CMakeLists.txt' |
1348 | --- src/daemon/CMakeLists.txt 2016-06-03 20:27:01 +0000 |
1349 | +++ src/daemon/CMakeLists.txt 2016-08-30 20:17:54 +0000 |
1350 | @@ -9,16 +9,20 @@ |
1351 | |
1352 | vala_precompile (VALA_C ${DAEMON_EXEC_NAME} |
1353 | Daemon.vala |
1354 | - Core.vala |
1355 | + ProcessWatcher.vala |
1356 | Process.vala |
1357 | IptablesHelper.vala |
1358 | + Timer.vala |
1359 | SessionManager.vala |
1360 | SessionHandler.vala |
1361 | Interfaces.vala |
1362 | + UserConfig.vala |
1363 | Server.vala |
1364 | ${CMAKE_SOURCE_DIR}/src/shared/Vars.vala |
1365 | ${CMAKE_SOURCE_DIR}/src/shared/Utils.vala |
1366 | - ${CMAKE_SOURCE_DIR}/src/shared/PAMControl.vala |
1367 | + ${CMAKE_SOURCE_DIR}/src/shared/PAM/Token.vala |
1368 | + ${CMAKE_SOURCE_DIR}/src/shared/PAM/Reader.vala |
1369 | + ${CMAKE_SOURCE_DIR}/src/shared/PAM/Writer.vala |
1370 | PACKAGES |
1371 | posix |
1372 | accountsservice |
1373 | |
1374 | === modified file 'src/daemon/Daemon.vala' |
1375 | --- src/daemon/Daemon.vala 2016-05-19 19:47:38 +0000 |
1376 | +++ src/daemon/Daemon.vala 2016-08-30 20:17:54 +0000 |
1377 | @@ -45,22 +45,16 @@ |
1378 | |
1379 | public static void on_exit (int signum) { |
1380 | if (session_manager != null) { |
1381 | - session_manager.current_handler.stop (); |
1382 | - session_manager.current_handler.unref (); |
1383 | + session_manager.stop (); |
1384 | } |
1385 | |
1386 | terminate (); |
1387 | } |
1388 | |
1389 | public override void activate () { |
1390 | + Utils.get_usermanager ().notify["is-loaded"].connect (on_usermanager_loaded); |
1391 | + |
1392 | loop = new MainLoop (); |
1393 | - |
1394 | - Bus.own_name (BusType.SYSTEM, Vars.PARENTAL_CONTROLS_IFACE, BusNameOwnerFlags.REPLACE, |
1395 | - on_bus_aquired, |
1396 | - () => {}, |
1397 | - on_bus_lost); |
1398 | - Utils.get_usermanager ().notify["is-loaded"].connect (on_usermanager_loaded); |
1399 | - |
1400 | loop.run (); |
1401 | } |
1402 | |
1403 | @@ -68,7 +62,7 @@ |
1404 | warning ("Could not acquire name: %s\n", name); |
1405 | } |
1406 | |
1407 | - private void on_bus_aquired (DBusConnection connection) { |
1408 | + private void on_bus_acquired (DBusConnection connection) { |
1409 | try { |
1410 | connection.register_object (Vars.PARENTAL_CONTROLS_OBJECT_PATH, Server.get_default ()); |
1411 | } catch (IOError e) { |
1412 | @@ -81,6 +75,11 @@ |
1413 | return; |
1414 | } |
1415 | |
1416 | + Bus.own_name (BusType.SYSTEM, Vars.PARENTAL_CONTROLS_IFACE, BusNameOwnerFlags.REPLACE, |
1417 | + on_bus_acquired, |
1418 | + () => {}, |
1419 | + on_bus_lost); |
1420 | + |
1421 | session_manager = new SessionManager (); |
1422 | session_manager.start (); |
1423 | } |
1424 | |
1425 | === modified file 'src/daemon/Interfaces.vala' |
1426 | --- src/daemon/Interfaces.vala 2016-05-18 14:56:00 +0000 |
1427 | +++ src/daemon/Interfaces.vala 2016-08-30 20:17:54 +0000 |
1428 | @@ -19,38 +19,34 @@ |
1429 | * |
1430 | * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
1431 | */ |
1432 | - |
1433 | -public struct SessionStruct { |
1434 | - string name; |
1435 | - uint32 uid; |
1436 | - string user; |
1437 | - string seat; |
1438 | - GLib.ObjectPath object_path; |
1439 | -} |
1440 | - |
1441 | -public struct ActiveSessionStruct { |
1442 | - string session_id; |
1443 | - GLib.ObjectPath object_path; |
1444 | -} |
1445 | - |
1446 | -[DBus (name = "org.freedesktop.login1.Manager")] |
1447 | -public interface IManager : Object { |
1448 | - public abstract SessionStruct[] list_sessions () throws IOError; |
1449 | - public abstract GLib.ObjectPath get_seat (string seat) throws IOError; |
1450 | - public signal void session_new (string user, GLib.ObjectPath object_path); |
1451 | - public signal void session_removed (string user, GLib.ObjectPath object_path); |
1452 | -} |
1453 | - |
1454 | -[DBus (name = "org.freedesktop.login1.Session")] |
1455 | -public interface ISession : Object { |
1456 | - public abstract string name { owned get; } |
1457 | - |
1458 | - public abstract void lock () throws IOError; |
1459 | - |
1460 | - public signal void unlock (); |
1461 | -} |
1462 | - |
1463 | -[DBus (name = "org.freedesktop.login1.Seat")] |
1464 | -public interface ISeat : Object { |
1465 | - public abstract ActiveSessionStruct active_session { owned get; } |
1466 | +namespace PC.Daemon { |
1467 | + public struct SessionStruct { |
1468 | + string name; |
1469 | + uint32 uid; |
1470 | + string user; |
1471 | + string seat; |
1472 | + GLib.ObjectPath object_path; |
1473 | + } |
1474 | + |
1475 | + public struct SeatStruct { |
1476 | + string seat_id; |
1477 | + GLib.ObjectPath object_path; |
1478 | + } |
1479 | + |
1480 | + [DBus (name = "org.freedesktop.login1.Manager")] |
1481 | + public interface IManager : Object { |
1482 | + public abstract SessionStruct[] list_sessions () throws IOError; |
1483 | + public abstract SeatStruct[] list_seats () throws IOError; |
1484 | + public abstract GLib.ObjectPath get_seat (string seat) throws IOError; |
1485 | + public signal void session_new (string session, GLib.ObjectPath object_path); |
1486 | + public signal void session_removed (string session, GLib.ObjectPath object_path); |
1487 | + } |
1488 | + |
1489 | + [DBus (name = "org.freedesktop.login1.Session")] |
1490 | + public interface ISession : Object { |
1491 | + public abstract bool active { owned get; } |
1492 | + public abstract string name { owned get; } |
1493 | + public abstract string id { owned get; } |
1494 | + public abstract void terminate () throws IOError; |
1495 | + } |
1496 | } |
1497 | \ No newline at end of file |
1498 | |
1499 | === modified file 'src/daemon/IptablesHelper.vala' |
1500 | --- src/daemon/IptablesHelper.vala 2016-05-17 13:51:36 +0000 |
1501 | +++ src/daemon/IptablesHelper.vala 2016-08-30 20:17:54 +0000 |
1502 | @@ -20,66 +20,64 @@ |
1503 | * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
1504 | */ |
1505 | |
1506 | - namespace PC { |
1507 | + namespace PC.Daemon { |
1508 | public class IptablesHelper : Object { |
1509 | - public bool valid = false; |
1510 | - |
1511 | private const string IPTABLES_EXEC = "iptables"; |
1512 | - private const string HOST_EXEC = "host"; |
1513 | - private const int ADDRESS_INDEX = 3; |
1514 | private const int DPORT = 80; |
1515 | |
1516 | - private string[] urls; |
1517 | - |
1518 | - public IptablesHelper (string[] urls) { |
1519 | - this.urls = urls; |
1520 | - valid = Environment.find_program_in_path (IPTABLES_EXEC) != null && |
1521 | - Environment.find_program_in_path (HOST_EXEC) != null && |
1522 | - urls.length > 0; |
1523 | - } |
1524 | - |
1525 | - public void add_rules () { |
1526 | - foreach (string url in urls) { |
1527 | - string[] addresses = get_addresses_from_url (url); |
1528 | + private UserConfig config; |
1529 | + private string[] current_urls; |
1530 | + private ulong changed_signal_id; |
1531 | + |
1532 | + public static bool get_can_start () { |
1533 | + return Environment.find_program_in_path (IPTABLES_EXEC) != null; |
1534 | + } |
1535 | + |
1536 | + public IptablesHelper (UserConfig config) { |
1537 | + this.config = config; |
1538 | + } |
1539 | + |
1540 | + public void start () { |
1541 | + this.current_urls = config.get_block_urls (); |
1542 | + add_rules (); |
1543 | + |
1544 | + changed_signal_id = config.changed.connect (() => { |
1545 | + remove_rules (); |
1546 | + |
1547 | + current_urls = config.get_block_urls (); |
1548 | + add_rules (); |
1549 | + }); |
1550 | + } |
1551 | + |
1552 | + public void stop () { |
1553 | + remove_rules (); |
1554 | + disconnect (changed_signal_id); |
1555 | + } |
1556 | + |
1557 | + private void add_rules () { |
1558 | + foreach (string url in current_urls) { |
1559 | + string[] addresses = get_addresses_from_name (url); |
1560 | foreach (string address in addresses) { |
1561 | process_adress (address, "-A"); |
1562 | } |
1563 | } |
1564 | } |
1565 | |
1566 | - private string[] get_addresses_from_url (string url) { |
1567 | - string[] result = {}; |
1568 | - |
1569 | - string output; |
1570 | - int status; |
1571 | - |
1572 | + private string[] get_addresses_from_name (string name) { |
1573 | + string[] address_list = {}; |
1574 | + var resolver = Resolver.get_default (); |
1575 | try { |
1576 | - GLib.Process.spawn_sync ("/", |
1577 | - { HOST_EXEC, url }, |
1578 | - Environ.get (), |
1579 | - SpawnFlags.SEARCH_PATH, |
1580 | - null, |
1581 | - out output, |
1582 | - null, |
1583 | - out status); |
1584 | - } catch (SpawnError e) { |
1585 | - warning ("%s\n", e.message); |
1586 | - } |
1587 | - |
1588 | - if (status != 0) { |
1589 | - return result; |
1590 | - } |
1591 | - |
1592 | - foreach (string line in output.split ("\n")) { |
1593 | - if (line.contains ("has address")) { |
1594 | - string[] elements = line.split (" "); |
1595 | - if (elements.length >= 3) { |
1596 | - result += elements[ADDRESS_INDEX]; |
1597 | + var addresses = resolver.lookup_by_name (name, null); |
1598 | + foreach (InetAddress address in addresses) { |
1599 | + if (address.get_family () == SocketFamily.IPV4) { |
1600 | + address_list += address.to_string (); |
1601 | } |
1602 | } |
1603 | + } catch (Error e) { |
1604 | + warning (e.message); |
1605 | } |
1606 | |
1607 | - return result; |
1608 | + return address_list; |
1609 | } |
1610 | |
1611 | private void process_adress (string address, string option) { |
1612 | @@ -97,9 +95,9 @@ |
1613 | } |
1614 | } |
1615 | |
1616 | - public void reset () { |
1617 | - foreach (string url in urls) { |
1618 | - string[] addresses = get_addresses_from_url (url); |
1619 | + private void remove_rules () { |
1620 | + foreach (string url in current_urls) { |
1621 | + string[] addresses = get_addresses_from_name (url); |
1622 | foreach (string address in addresses) { |
1623 | process_adress (address, "-D"); |
1624 | } |
1625 | |
1626 | === renamed file 'src/daemon/Core.vala' => 'src/daemon/ProcessWatcher.vala' |
1627 | --- src/daemon/Core.vala 2016-05-19 19:54:37 +0000 |
1628 | +++ src/daemon/ProcessWatcher.vala 2016-08-30 20:17:54 +0000 |
1629 | @@ -21,68 +21,42 @@ |
1630 | */ |
1631 | |
1632 | namespace PC.Daemon { |
1633 | - public class Core : GLib.Object, ExecMonitor { |
1634 | - public bool valid = true; |
1635 | - public KeyFile key_file; |
1636 | - |
1637 | - private Act.User user; |
1638 | - |
1639 | - private string[] targets = {}; |
1640 | - private bool admin = false; |
1641 | - |
1642 | + public class ProcessWatcher : GLib.Object, ExecMonitor { |
1643 | + public UserConfig? config = null; |
1644 | private List<string> allowed_executables; |
1645 | - |
1646 | private Polkit.Authority authority; |
1647 | - private Server server; |
1648 | |
1649 | - public Core (Act.User _user, Server _server) { |
1650 | - user = _user; |
1651 | - server = _server; |
1652 | + public ProcessWatcher () { |
1653 | allowed_executables = new List<string> (); |
1654 | + |
1655 | try { |
1656 | authority = Polkit.Authority.get_sync (); |
1657 | } catch (Error e) { |
1658 | warning ("%s\n", e.message); |
1659 | } |
1660 | - |
1661 | - if (user == null) { |
1662 | - valid = false; |
1663 | - return; |
1664 | - } |
1665 | - |
1666 | - key_file = new KeyFile (); |
1667 | - |
1668 | - string conf_path = Utils.build_daemon_conf_path (user); |
1669 | - if (conf_path.strip () != "" && FileUtils.test (conf_path, FileTest.EXISTS)) { |
1670 | - try { |
1671 | - key_file.load_from_file (conf_path, 0); |
1672 | - |
1673 | - targets = key_file.get_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_TARGETS); |
1674 | - admin = key_file.get_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ADMIN); |
1675 | - |
1676 | - valid = targets.length > 0; |
1677 | - } catch (FileError e) { |
1678 | - warning ("%s\n", e.message); |
1679 | - } catch (Error e) { |
1680 | - warning ("%s\n", e.message); |
1681 | - } |
1682 | - } else { |
1683 | - valid = false; |
1684 | - } |
1685 | + } |
1686 | + |
1687 | + public void set_config (UserConfig? config) { |
1688 | + this.config = config; |
1689 | + allowed_executables = new List<string> (); |
1690 | } |
1691 | |
1692 | private void handle_pid (int pid) { |
1693 | + if (config == null) { |
1694 | + return; |
1695 | + } |
1696 | + |
1697 | var process = new Process (pid); |
1698 | |
1699 | - string command = process.get_command (); |
1700 | + string? command = process.get_command (); |
1701 | if (command == null || command == "") { |
1702 | return; |
1703 | } |
1704 | |
1705 | string[]? args = {}; |
1706 | try { |
1707 | - bool success = Shell.parse_argv (command, out args); |
1708 | - if (!success || args == null || args.length < 1) { |
1709 | + Shell.parse_argv (command, out args); |
1710 | + if (args == null || args.length < 1) { |
1711 | return; |
1712 | } |
1713 | } catch (ShellError e) { |
1714 | @@ -91,43 +65,44 @@ |
1715 | } |
1716 | |
1717 | string executable = args[0]; |
1718 | - foreach (string _executable in allowed_executables) { |
1719 | - if (_executable == executable) { |
1720 | - allowed_executables.remove (_executable); |
1721 | - return; |
1722 | - } |
1723 | - } |
1724 | |
1725 | - if (executable != null && !executable.has_prefix (Path.DIR_SEPARATOR_S)) { |
1726 | + if (!executable.has_prefix (Path.DIR_SEPARATOR_S)) { |
1727 | executable = Environment.find_program_in_path (executable); |
1728 | } |
1729 | |
1730 | - if (executable != null && executable != "") { |
1731 | - if (executable in targets) { |
1732 | - process.kill (); |
1733 | - |
1734 | - if (admin && authority != null) { |
1735 | - server.authorize (user.get_user_name (), Vars.PARENTAL_CONTROLS_ACTION_ID); |
1736 | - ulong signal_id = 0; |
1737 | - signal_id = server.authorization_ended.connect ((client_pid) => { |
1738 | - try { |
1739 | - var result = authority.check_authorization_sync (Polkit.UnixProcess.new_for_owner (client_pid, 0, (int)user.get_uid ()), |
1740 | - Vars.PARENTAL_CONTROLS_ACTION_ID, |
1741 | - null, |
1742 | - Polkit.CheckAuthorizationFlags.ALLOW_USER_INTERACTION); |
1743 | - if (result.get_is_authorized ()) { |
1744 | - allowed_executables.append (args[0]); |
1745 | - server.launch (args); |
1746 | - } |
1747 | - } catch (Error e) { |
1748 | - warning ("%s\n", e.message); |
1749 | + unowned List<string> link = allowed_executables.find_custom (executable, strcmp); |
1750 | + if (link != null) { |
1751 | + allowed_executables.remove_link (link); |
1752 | + return; |
1753 | + } |
1754 | + |
1755 | + if (executable != null && executable in config.get_targets ()) { |
1756 | + process.kill (); |
1757 | + |
1758 | + var server = Server.get_default (); |
1759 | + if (config.get_admin () && authority != null) { |
1760 | + ulong signal_id = 0; |
1761 | + signal_id = server.app_authorization_ended.connect ((client_pid) => { |
1762 | + try { |
1763 | + var unix_user = (Polkit.UnixUser)Polkit.UnixUser.new_for_name (config.username); |
1764 | + var result = authority.check_authorization_sync (Polkit.UnixProcess.new_for_owner (client_pid, 0, unix_user.get_uid ()), |
1765 | + Vars.PARENTAL_CONTROLS_ACTION_ID, |
1766 | + null, |
1767 | + Polkit.CheckAuthorizationFlags.NONE); |
1768 | + if (result.get_is_authorized ()) { |
1769 | + allowed_executables.append (executable); |
1770 | + server.launch (args); |
1771 | } |
1772 | - |
1773 | - server.disconnect (signal_id); |
1774 | - }); |
1775 | - } else { |
1776 | - server.show_app_lock_dialog (); |
1777 | - } |
1778 | + } catch (Error e) { |
1779 | + warning ("%s\n", e.message); |
1780 | + } |
1781 | + |
1782 | + server.disconnect (signal_id); |
1783 | + }); |
1784 | + |
1785 | + server.app_authorize (config.username, executable, Vars.PARENTAL_CONTROLS_ACTION_ID); |
1786 | + } else { |
1787 | + server.show_app_unavailable (executable); |
1788 | } |
1789 | } |
1790 | } |
1791 | |
1792 | === modified file 'src/daemon/Server.vala' |
1793 | --- src/daemon/Server.vala 2016-02-25 18:47:22 +0000 |
1794 | +++ src/daemon/Server.vala 2016-08-30 20:17:54 +0000 |
1795 | @@ -21,9 +21,26 @@ |
1796 | */ |
1797 | |
1798 | namespace PC.Daemon { |
1799 | + [DBus (name = "org.freedesktop.DBus")] |
1800 | + private interface DBus : Object { |
1801 | + [DBus (name = "GetConnectionUnixProcessID")] |
1802 | + public abstract uint32 get_connection_unix_process_id (string name) throws IOError; |
1803 | + |
1804 | + public abstract uint32 get_connection_unix_user (string name) throws IOError; |
1805 | + } |
1806 | + |
1807 | + [DBus (name = "org.pantheon.ParentalControls")] |
1808 | + public errordomain ParentalControlsError { |
1809 | + NOT_AUTHORIZED, |
1810 | + NOT_IMPLEMENTED, |
1811 | + USER_CONFIG_NOT_VAILD, |
1812 | + DBUS_CONNECTION_FAILED |
1813 | + } |
1814 | + |
1815 | [DBus (name = "org.pantheon.ParentalControls")] |
1816 | public class Server : Object { |
1817 | private static Server? instance = null; |
1818 | + private DBus? bus_proxy = null; |
1819 | |
1820 | [DBus (visible = false)] |
1821 | public static Server get_default () { |
1822 | @@ -34,16 +51,205 @@ |
1823 | return instance; |
1824 | } |
1825 | |
1826 | + protected Server () { |
1827 | + try { |
1828 | + bus_proxy = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.DBus", "/"); |
1829 | + } catch (Error e) { |
1830 | + warning (e.message); |
1831 | + bus_proxy = null; |
1832 | + } |
1833 | + |
1834 | + UserConfig.init (); |
1835 | + } |
1836 | + |
1837 | [DBus (visible = false)] |
1838 | - public signal void authorization_ended (int client_pid); |
1839 | + public signal void app_authorization_ended (int client_pid); |
1840 | |
1841 | - public signal void show_app_lock_dialog (); |
1842 | - public signal void authorize (string user, string action_id); |
1843 | + public signal void app_authorize (string username, string path, string action_id); |
1844 | public signal void launch (string[] args); |
1845 | - public signal void send_time_notification (int hours, int minutes); |
1846 | - |
1847 | - public void end_authorization (int client_pid) { |
1848 | - authorization_ended (client_pid); |
1849 | + public signal void show_app_unavailable (string path); |
1850 | + public signal void show_timeout (int hours, int minutes); |
1851 | + public signal void user_config_changed (string username); |
1852 | + |
1853 | + public void end_app_authorization (BusName sender) { |
1854 | + uint32 pid = get_pid_from_sender (sender); |
1855 | + app_authorization_ended ((int)pid); |
1856 | + } |
1857 | + |
1858 | + public void add_restriction_for_user (string input, bool clean, BusName sender) throws ParentalControlsError { |
1859 | + if (!get_sender_is_authorized (sender)) { |
1860 | + throw new ParentalControlsError.NOT_AUTHORIZED ("Error: sender not authorized"); |
1861 | + } |
1862 | + |
1863 | + ensure_pam_lightdm_enabled (); |
1864 | + |
1865 | + var writer = PAM.Writer.new_for_time (); |
1866 | + writer.add_restriction_for_user (input, clean); |
1867 | + } |
1868 | + |
1869 | + public void remove_restriction_for_user (string username, BusName sender) throws ParentalControlsError { |
1870 | + if (!get_sender_is_authorized (sender)) { |
1871 | + throw new ParentalControlsError.NOT_AUTHORIZED ("Error: sender not authorized"); |
1872 | + } |
1873 | + |
1874 | + var writer = PAM.Writer.new_for_time (); |
1875 | + writer.remove_restriction_for_user (username); |
1876 | + } |
1877 | + |
1878 | + public void lock_dock_icons_for_user (string username, bool lock, BusName sender) throws ParentalControlsError { |
1879 | + throw new ParentalControlsError.NOT_IMPLEMENTED ("Error: not implemented"); |
1880 | + } |
1881 | + |
1882 | + public void set_user_daemon_active (string username, bool active, BusName sender) throws ParentalControlsError { |
1883 | + if (!get_sender_is_authorized (sender)) { |
1884 | + throw new ParentalControlsError.NOT_AUTHORIZED ("Error: sender not authorized"); |
1885 | + } |
1886 | + |
1887 | + var config = UserConfig.get_for_username (username, true); |
1888 | + if (config == null) { |
1889 | + throw new ParentalControlsError.USER_CONFIG_NOT_VAILD ("Error: config for %s is not valid or could not be created".printf (username)); |
1890 | + } |
1891 | + |
1892 | + config.set_active (active); |
1893 | + } |
1894 | + |
1895 | + public void set_user_daemon_targets (string username, string[] targets, BusName sender) throws ParentalControlsError { |
1896 | + if (!get_sender_is_authorized (sender)) { |
1897 | + throw new ParentalControlsError.NOT_AUTHORIZED ("Error: sender not authorized"); |
1898 | + } |
1899 | + |
1900 | + var config = UserConfig.get_for_username (username, true); |
1901 | + if (config == null) { |
1902 | + throw new ParentalControlsError.USER_CONFIG_NOT_VAILD ("Error: config for %s is not valid or could not be created".printf (username)); |
1903 | + } |
1904 | + |
1905 | + config.set_targets (targets); |
1906 | + } |
1907 | + |
1908 | + public void set_user_daemon_block_urls (string username, string[] block_urls, BusName sender) throws ParentalControlsError { |
1909 | + if (!get_sender_is_authorized (sender)) { |
1910 | + throw new ParentalControlsError.NOT_AUTHORIZED ("Error: sender not authorized"); |
1911 | + } |
1912 | + |
1913 | + var config = UserConfig.get_for_username (username, true); |
1914 | + if (config == null) { |
1915 | + throw new ParentalControlsError.USER_CONFIG_NOT_VAILD ("Error: config for %s is not valid or could not be created".printf (username)); |
1916 | + } |
1917 | + |
1918 | + config.set_block_urls (block_urls); |
1919 | + } |
1920 | + |
1921 | + public void set_user_daemon_admin (string username, bool admin, BusName sender) throws ParentalControlsError { |
1922 | + if (!get_sender_is_authorized (sender)) { |
1923 | + throw new ParentalControlsError.NOT_AUTHORIZED ("Error: sender not authorized"); |
1924 | + } |
1925 | + |
1926 | + var config = UserConfig.get_for_username (username, true); |
1927 | + if (config == null) { |
1928 | + throw new ParentalControlsError.USER_CONFIG_NOT_VAILD ("Error: config for %s is not valid or could not be created".printf (username)); |
1929 | + } |
1930 | + |
1931 | + config.set_admin (admin); |
1932 | + } |
1933 | + |
1934 | + public bool get_user_daemon_active (string username) throws ParentalControlsError { |
1935 | + var config = UserConfig.get_for_username (username, false); |
1936 | + if (config == null) { |
1937 | + throw new ParentalControlsError.USER_CONFIG_NOT_VAILD ("Error: config for %s is not valid or does not exist".printf (username)); |
1938 | + } |
1939 | + |
1940 | + return config.get_active (); |
1941 | + } |
1942 | + |
1943 | + public string[] get_user_daemon_targets (string username) throws ParentalControlsError { |
1944 | + var config = UserConfig.get_for_username (username, false); |
1945 | + if (config == null) { |
1946 | + throw new ParentalControlsError.USER_CONFIG_NOT_VAILD ("Error: config for %s is not valid or does not exist".printf (username)); |
1947 | + } |
1948 | + |
1949 | + return config.get_targets (); |
1950 | + } |
1951 | + |
1952 | + public string[] get_user_daemon_block_urls (string username) throws ParentalControlsError { |
1953 | + var config = UserConfig.get_for_username (username, false); |
1954 | + if (config == null) { |
1955 | + throw new ParentalControlsError.USER_CONFIG_NOT_VAILD ("Error: config for %s is not valid or does not exist".printf (username)); |
1956 | + } |
1957 | + |
1958 | + return config.get_block_urls (); |
1959 | + } |
1960 | + |
1961 | + public bool get_user_daemon_admin (string username) throws ParentalControlsError { |
1962 | + var config = UserConfig.get_for_username (username, false); |
1963 | + if (config == null) { |
1964 | + throw new ParentalControlsError.USER_CONFIG_NOT_VAILD ("Error: config for %s is not valid or does not exist".printf (username)); |
1965 | + } |
1966 | + |
1967 | + return config.get_admin (); |
1968 | + } |
1969 | + |
1970 | + private void ensure_pam_lightdm_enabled () { |
1971 | + string path = "/etc/pam.d/lightdm"; |
1972 | + |
1973 | + string contents; |
1974 | + try { |
1975 | + FileUtils.get_contents (path, out contents); |
1976 | + } catch (FileError e) { |
1977 | + warning (e.message); |
1978 | + return; |
1979 | + } |
1980 | + |
1981 | + string conf_line = "\naccount required pam_time.so"; |
1982 | + if (conf_line in contents) { |
1983 | + return; |
1984 | + } |
1985 | + |
1986 | + contents += conf_line; |
1987 | + |
1988 | + try { |
1989 | + FileUtils.set_contents (path, contents); |
1990 | + } catch (FileError e) { |
1991 | + warning ("%s\n", e.message); |
1992 | + } |
1993 | + } |
1994 | + |
1995 | + private bool get_sender_is_authorized (BusName sender) throws ParentalControlsError { |
1996 | + if (bus_proxy == null) { |
1997 | + throw new ParentalControlsError.DBUS_CONNECTION_FAILED ("Error: connecting to org.freedesktop.DBus failed."); |
1998 | + } |
1999 | + |
2000 | + uint32 user = 0, pid = 0; |
2001 | + |
2002 | + try { |
2003 | + pid = get_pid_from_sender (sender); |
2004 | + user = bus_proxy.get_connection_unix_user (sender); |
2005 | + } catch (Error e) { |
2006 | + warning (e.message); |
2007 | + } |
2008 | + |
2009 | + var subject = Polkit.UnixProcess.new_for_owner ((int)pid, 0, (int)user); |
2010 | + |
2011 | + try { |
2012 | + var authority = Polkit.Authority.get_sync (null); |
2013 | + var auth_result = authority.check_authorization_sync (subject, Vars.PARENTAL_CONTROLS_ACTION_ID, null, Polkit.CheckAuthorizationFlags.NONE); |
2014 | + return auth_result.get_is_authorized (); |
2015 | + } catch (Error e) { |
2016 | + warning (e.message); |
2017 | + } |
2018 | + |
2019 | + return false; |
2020 | + } |
2021 | + |
2022 | + private uint32 get_pid_from_sender (BusName sender) { |
2023 | + uint32 pid = 0; |
2024 | + |
2025 | + try { |
2026 | + pid = bus_proxy.get_connection_unix_process_id (sender); |
2027 | + } catch (Error e) { |
2028 | + warning (e.message); |
2029 | + } |
2030 | + |
2031 | + return pid; |
2032 | } |
2033 | } |
2034 | } |
2035 | \ No newline at end of file |
2036 | |
2037 | === modified file 'src/daemon/SessionHandler.vala' |
2038 | --- src/daemon/SessionHandler.vala 2016-05-18 14:52:41 +0000 |
2039 | +++ src/daemon/SessionHandler.vala 2016-08-30 20:17:54 +0000 |
2040 | @@ -22,40 +22,46 @@ |
2041 | |
2042 | namespace PC.Daemon { |
2043 | public class SessionHandler : Object { |
2044 | - private const int MINUTE_INTERVAL = 60; |
2045 | - private const int HOUR_INTERVAL = 3600; |
2046 | - |
2047 | - public Core core; |
2048 | - public IptablesHelper iptables_helper; |
2049 | - |
2050 | - private ISession session; |
2051 | + private IptablesHelper iptables_helper; |
2052 | + private Timer? timer; |
2053 | + |
2054 | + private UserConfig config; |
2055 | + public ISession session; |
2056 | private Server server; |
2057 | |
2058 | private bool can_start = true; |
2059 | |
2060 | - public SessionHandler (ISession _session) { |
2061 | - session = _session; |
2062 | + public SessionHandler (ISession session) { |
2063 | + this.session = session; |
2064 | server = Server.get_default (); |
2065 | - Utils.set_user_name (session.name); |
2066 | - |
2067 | - core = new Core (Utils.get_current_user (), server); |
2068 | - |
2069 | - try { |
2070 | - if (!core.key_file.has_group (Vars.DAEMON_GROUP) || !core.key_file.get_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ACTIVE)) { |
2071 | - can_start = false; |
2072 | - } |
2073 | - } catch (Error e) { |
2074 | - warning ("%s\n", e.message); |
2075 | - } |
2076 | - |
2077 | - string[] block_urls = {}; |
2078 | - try { |
2079 | - block_urls = core.key_file.get_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_BLOCK_URLS); |
2080 | - } catch (KeyFileError e) { |
2081 | - warning ("%s\n", e.message); |
2082 | - } |
2083 | - |
2084 | - iptables_helper = new IptablesHelper (block_urls); |
2085 | + |
2086 | + config = UserConfig.get_for_username (session.name, false); |
2087 | + if (config == null || !config.get_active ()) { |
2088 | + can_start = false; |
2089 | + return; |
2090 | + } |
2091 | + |
2092 | + iptables_helper = new IptablesHelper (config); |
2093 | + |
2094 | + var token = PAM.Reader.get_token_for_user (Vars.PAM_TIME_CONF_PATH, session.name); |
2095 | + if (token != null) { |
2096 | + timer = new Timer (token); |
2097 | + timer.terminate.connect (() => { |
2098 | + try { |
2099 | + session.terminate (); |
2100 | + } catch (IOError e) { |
2101 | + warning (e.message); |
2102 | + } |
2103 | + }); |
2104 | + } |
2105 | + } |
2106 | + |
2107 | + public string get_id () { |
2108 | + return session.id; |
2109 | + } |
2110 | + |
2111 | + public UserConfig get_config () { |
2112 | + return config; |
2113 | } |
2114 | |
2115 | public void start () { |
2116 | @@ -63,142 +69,20 @@ |
2117 | return; |
2118 | } |
2119 | |
2120 | - if (core.valid) { |
2121 | - core.start.begin (); |
2122 | - } |
2123 | - |
2124 | - if (iptables_helper.valid) { |
2125 | - iptables_helper.add_rules (); |
2126 | - } |
2127 | - |
2128 | - var restricts = PAMControl.get_all_restrictions (); |
2129 | - foreach (var restrict in restricts) { |
2130 | - if (restrict.user == Utils.get_current_user ().get_user_name ()) { |
2131 | - var current_date = new DateTime.now_local (); |
2132 | - string minute = current_date.get_minute ().to_string (); |
2133 | - if (int.parse (minute) < 10) { |
2134 | - minute = "0" + minute; |
2135 | - } |
2136 | - |
2137 | - switch (restrict.day_id) { |
2138 | - case Vars.WEEKDAYS_ID: |
2139 | - if (current_date.get_day_of_week () < 6) { |
2140 | - int estimated_time = int.parse (restrict.to); |
2141 | - var span = get_difference_span (estimated_time, current_date); |
2142 | - start_loop ((int)((span / GLib.TimeSpan.MINUTE * -1) + 1) - 24 * MINUTE_INTERVAL); |
2143 | - } |
2144 | - |
2145 | - break; |
2146 | - case Vars.WEEKENDS_ID: |
2147 | - if (current_date.get_day_of_week () >= 6) { |
2148 | - int estimated_time = int.parse (restrict.to); |
2149 | - var span = get_difference_span (estimated_time, current_date); |
2150 | - start_loop ((int)((span / GLib.TimeSpan.MINUTE * -1) + 1) - 24 * MINUTE_INTERVAL); |
2151 | - } |
2152 | - |
2153 | - break; |
2154 | - case Vars.ALL_ID: |
2155 | - int estimated_time = 2400; |
2156 | - if (current_date.get_day_of_week () < 6) { |
2157 | - estimated_time = int.parse (restrict.weekday_hours.split ("-")[1]); |
2158 | - } else if (current_date.get_day_of_week () >= 6) { |
2159 | - estimated_time = int.parse (restrict.weekend_hours.split ("-")[1]); |
2160 | - } |
2161 | - |
2162 | - var span = get_difference_span (estimated_time, current_date); |
2163 | - int minutes = (int)((span / GLib.TimeSpan.MINUTE * -1) + 1) - 24 * MINUTE_INTERVAL; |
2164 | - if (minutes > 0) { |
2165 | - start_loop (minutes); |
2166 | - } else { |
2167 | - lock_session (); |
2168 | - } |
2169 | - |
2170 | - break; |
2171 | - default: |
2172 | - break; |
2173 | - } |
2174 | - } |
2175 | - } |
2176 | + if (IptablesHelper.get_can_start ()) { |
2177 | + iptables_helper.start (); |
2178 | + } |
2179 | + |
2180 | + if (timer != null) { |
2181 | + timer.start (); |
2182 | + } |
2183 | } |
2184 | |
2185 | public void stop () { |
2186 | - core.stop (); |
2187 | - iptables_helper.reset (); |
2188 | - } |
2189 | - |
2190 | - private TimeSpan get_difference_span (int estimated_time, DateTime current_date) { |
2191 | - bool end_day = (estimated_time == 2400 || estimated_time == 0); |
2192 | - if (end_day) { |
2193 | - estimated_time = 2359; |
2194 | - } |
2195 | - |
2196 | - char[] tmp = estimated_time.to_string ().to_utf8 (); |
2197 | - int _h, _m; |
2198 | - _h = int.parse (tmp[0].to_string () + tmp[1].to_string ()); |
2199 | - _m = int.parse (tmp[2].to_string () + tmp[3].to_string ()); |
2200 | - |
2201 | - var estimated_date = new DateTime.local (current_date.get_year (), |
2202 | - current_date.get_month (), |
2203 | - current_date.get_day_of_week (), |
2204 | - _h, _m, 0); |
2205 | - |
2206 | - var span = current_date.difference (estimated_date); |
2207 | - if (end_day) { |
2208 | - span -= GLib.TimeSpan.MINUTE; |
2209 | - } |
2210 | - |
2211 | - return span; |
2212 | - } |
2213 | - |
2214 | - private int get_estimated_hours (int minutes) { |
2215 | - if (minutes >= MINUTE_INTERVAL) { |
2216 | - return minutes / MINUTE_INTERVAL; |
2217 | - } |
2218 | - |
2219 | - return 0; |
2220 | - } |
2221 | - |
2222 | - private void start_loop (int minutes) { |
2223 | - int _hours = get_estimated_hours (minutes); |
2224 | - int remaining_minutes = minutes - (MINUTE_INTERVAL * _hours); |
2225 | - server.send_time_notification (_hours, remaining_minutes); |
2226 | - |
2227 | - schedule_notification (remaining_minutes, 5); |
2228 | - schedule_notification (remaining_minutes, 1); |
2229 | - |
2230 | - Timeout.add_seconds (MINUTE_INTERVAL, () => { |
2231 | - remaining_minutes--; |
2232 | - if (remaining_minutes == 0) { |
2233 | - lock_session (); |
2234 | - } |
2235 | - |
2236 | - return (remaining_minutes != 0); |
2237 | - }); |
2238 | - |
2239 | - Timeout.add_seconds (HOUR_INTERVAL, () => { |
2240 | - int hours = get_estimated_hours (minutes); |
2241 | - if (hours > 0) { |
2242 | - server.send_time_notification (hours, minutes - (MINUTE_INTERVAL * hours)); |
2243 | - } |
2244 | - |
2245 | - return (hours != 0 || minutes != 0); |
2246 | - }); |
2247 | - } |
2248 | - |
2249 | - private void schedule_notification (int remaining_minutes, int minutes) { |
2250 | - Timeout.add_seconds ((remaining_minutes - minutes) * MINUTE_INTERVAL, () => { |
2251 | - server.send_time_notification (0, minutes); |
2252 | - |
2253 | - return false; |
2254 | - }); |
2255 | - } |
2256 | - |
2257 | - private void lock_session () { |
2258 | - try { |
2259 | - session.lock (); |
2260 | - } catch (IOError e) { |
2261 | - warning ("%s\n", e.message); |
2262 | - } |
2263 | - } |
2264 | + iptables_helper.stop (); |
2265 | + if (timer != null) { |
2266 | + timer.stop (); |
2267 | + } |
2268 | + } |
2269 | } |
2270 | } |
2271 | \ No newline at end of file |
2272 | |
2273 | === modified file 'src/daemon/SessionManager.vala' |
2274 | --- src/daemon/SessionManager.vala 2016-05-18 14:56:00 +0000 |
2275 | +++ src/daemon/SessionManager.vala 2016-08-30 20:17:54 +0000 |
2276 | @@ -22,10 +22,12 @@ |
2277 | |
2278 | namespace PC.Daemon { |
2279 | public class SessionManager : Object { |
2280 | - public SessionHandler? current_handler = null; |
2281 | - |
2282 | + private SessionHandler? current_handler = null; |
2283 | private IManager? manager = null; |
2284 | private DBusConnection? conn = null; |
2285 | + private ProcessWatcher pwatcher; |
2286 | + |
2287 | + private uint[] signal_ids; |
2288 | |
2289 | public SessionManager () { |
2290 | try { |
2291 | @@ -34,6 +36,9 @@ |
2292 | } catch (IOError e) { |
2293 | warning ("%s\n", e.message); |
2294 | } |
2295 | + |
2296 | + pwatcher = new ProcessWatcher (); |
2297 | + pwatcher.start.begin (); |
2298 | } |
2299 | |
2300 | public void start () { |
2301 | @@ -44,22 +49,39 @@ |
2302 | manager.session_new.connect (() => update_session ()); |
2303 | manager.session_removed.connect (() => update_session ()); |
2304 | |
2305 | - conn.signal_subscribe (null, |
2306 | - Vars.DBUS_PROPERTIES_IFACE, |
2307 | - "PropertiesChanged", |
2308 | - get_current_seat_path (), |
2309 | - null, |
2310 | - 0, |
2311 | - () => update_session ()); |
2312 | + try { |
2313 | + foreach (SeatStruct seat_s in manager.list_seats ()) { |
2314 | + signal_ids += conn.signal_subscribe (null, |
2315 | + Vars.DBUS_PROPERTIES_IFACE, |
2316 | + "PropertiesChanged", |
2317 | + seat_s.object_path, |
2318 | + null, |
2319 | + 0, |
2320 | + () => update_session ()); |
2321 | + } |
2322 | + } catch (IOError e) { |
2323 | + warning (e.message); |
2324 | + } |
2325 | + |
2326 | update_session (); |
2327 | } |
2328 | |
2329 | + public void stop () { |
2330 | + foreach (uint signal_id in signal_ids) { |
2331 | + conn.signal_unsubscribe (signal_id); |
2332 | + } |
2333 | + |
2334 | + stop_current_handler (); |
2335 | + } |
2336 | + |
2337 | private ISession? get_current_session () { |
2338 | try { |
2339 | - string? seat_path = get_current_seat_path (); |
2340 | - if (seat_path != null) { |
2341 | - ISeat? seat = Bus.get_proxy_sync (BusType.SYSTEM, Vars.LOGIN_IFACE, seat_path); |
2342 | - return Bus.get_proxy_sync (BusType.SYSTEM, Vars.LOGIN_IFACE, seat.active_session.object_path); |
2343 | + var structs = manager.list_sessions (); |
2344 | + foreach (SessionStruct session_s in structs) { |
2345 | + ISession? session = Bus.get_proxy_sync (BusType.SYSTEM, Vars.LOGIN_IFACE, session_s.object_path); |
2346 | + if (session != null && session.active) { |
2347 | + return session; |
2348 | + } |
2349 | } |
2350 | } catch (IOError e) { |
2351 | warning ("%s\n", e.message); |
2352 | @@ -68,37 +90,30 @@ |
2353 | return null; |
2354 | } |
2355 | |
2356 | - private string? get_current_seat_path () { |
2357 | - try { |
2358 | - string seat_id = "seat0"; |
2359 | - string? seat_variable = Environment.get_variable ("XDG_SEAT"); |
2360 | - if (seat_variable != null && seat_variable.has_prefix ("seat")) { |
2361 | - seat_id = seat_variable; |
2362 | - } |
2363 | - |
2364 | - return manager.get_seat (seat_id); |
2365 | - } catch (Error e) { |
2366 | - warning ("%s\n", e.message); |
2367 | - } |
2368 | - |
2369 | - return null; |
2370 | - } |
2371 | - |
2372 | private void update_session () { |
2373 | + var session = get_current_session (); |
2374 | + if (session.id == current_handler.get_id ()) { |
2375 | + return; |
2376 | + } |
2377 | + |
2378 | + stop_current_handler (); |
2379 | + |
2380 | + if (session != null && |
2381 | + session.name != null && |
2382 | + !(session.name in Vars.DAEMON_IGNORED_USERS)) { |
2383 | + current_handler = new SessionHandler (session); |
2384 | + current_handler.start (); |
2385 | + pwatcher.set_config (current_handler.get_config ()); |
2386 | + } |
2387 | + } |
2388 | + |
2389 | + private void stop_current_handler () { |
2390 | if (current_handler != null) { |
2391 | current_handler.stop (); |
2392 | - current_handler.unref (); |
2393 | current_handler = null; |
2394 | } |
2395 | |
2396 | - var current_session = get_current_session (); |
2397 | - if (current_session != null && |
2398 | - current_session.name != null && |
2399 | - current_session.name.strip () != "" && |
2400 | - !(current_session.name in Vars.DAEMON_IGNORED_USERS)) { |
2401 | - current_handler = new SessionHandler (current_session); |
2402 | - current_handler.start (); |
2403 | - } |
2404 | + pwatcher.set_config (null); |
2405 | } |
2406 | } |
2407 | } |
2408 | \ No newline at end of file |
2409 | |
2410 | === added file 'src/daemon/Timer.vala' |
2411 | --- src/daemon/Timer.vala 1970-01-01 00:00:00 +0000 |
2412 | +++ src/daemon/Timer.vala 2016-08-30 20:17:54 +0000 |
2413 | @@ -0,0 +1,116 @@ |
2414 | +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
2415 | +/*- |
2416 | + * Copyright (c) 2016 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls) |
2417 | + * |
2418 | + * This library is free software; you can redistribute it and/or |
2419 | + * modify it under the terms of the GNU Library General Public |
2420 | + * License as published by the Free Software Foundation; either |
2421 | + * version 3 of the License, or (at your option) any later version. |
2422 | + * |
2423 | + * This library is distributed in the hope that it will be useful, |
2424 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2425 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2426 | + * Library General Public License for more details. |
2427 | + * |
2428 | + * You should have received a copy of the GNU Library General Public |
2429 | + * License along with this library; if not, write to the |
2430 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
2431 | + * Boston, MA 02111-1307, USA. |
2432 | + * |
2433 | + * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
2434 | + */ |
2435 | + |
2436 | +namespace PC.Daemon { |
2437 | + public class Timer : Object { |
2438 | + private const int MINUTE_INTERVAL = 60; |
2439 | + private const int HOUR_INTERVAL = 3600; |
2440 | + |
2441 | + public signal void terminate (); |
2442 | + |
2443 | + private PAM.Token token; |
2444 | + private uint[] timeout_ids; |
2445 | + |
2446 | + public Timer (PAM.Token token) { |
2447 | + this.token = token; |
2448 | + } |
2449 | + |
2450 | + public void start () { |
2451 | + var times_info = token.get_times_info (); |
2452 | + if (times_info.length () == 0) { |
2453 | + return; |
2454 | + } |
2455 | + |
2456 | + PAM.TimeInfo? current = null; |
2457 | + |
2458 | + int day_of_week = new DateTime.now_local ().get_day_of_week (); |
2459 | + foreach (PAM.TimeInfo info in times_info) { |
2460 | + if ((day_of_week < 6 && info.day_type == PAM.DayType.WEEKDAY) |
2461 | + || (day_of_week >= 6 && info.day_type == PAM.DayType.WEEKEND) |
2462 | + || info.day_type == PAM.DayType.ALL) { |
2463 | + current = info; |
2464 | + break; |
2465 | + } |
2466 | + } |
2467 | + |
2468 | + if (current == null) { |
2469 | + return; |
2470 | + } |
2471 | + |
2472 | + var span = get_difference_span (current.to); |
2473 | + int minutes = ((int)(span / GLib.TimeSpan.MINUTE)).abs (); |
2474 | + |
2475 | + if (minutes > 0) { |
2476 | + start_loop (minutes); |
2477 | + } else { |
2478 | + terminate (); |
2479 | + } |
2480 | + |
2481 | + timeout_ids += Timeout.add_seconds (HOUR_INTERVAL * 24, () => { |
2482 | + start (); |
2483 | + return true; |
2484 | + }); |
2485 | + } |
2486 | + |
2487 | + public void stop () { |
2488 | + foreach (uint timeout_id in timeout_ids) { |
2489 | + GLib.Source.remove (timeout_id); |
2490 | + } |
2491 | + } |
2492 | + |
2493 | + private TimeSpan get_difference_span (string estimated_time_str) { |
2494 | + int hour = int.parse (estimated_time_str.slice (0, 2)); |
2495 | + int minute = int.parse (estimated_time_str.substring (2)); |
2496 | + |
2497 | + if (hour == 24) { |
2498 | + hour = 0; |
2499 | + } |
2500 | + |
2501 | + var current_date = new DateTime.now_local (); |
2502 | + var estimated_date = current_date.add_full (0, 0, |
2503 | + (hour < current_date.get_hour ()) ? 1 : 0, |
2504 | + hour - current_date.get_hour (), |
2505 | + minute - current_date.get_minute (), |
2506 | + 0); |
2507 | + return estimated_date.difference (current_date); |
2508 | + } |
2509 | + |
2510 | + private void start_loop (int minutes) { |
2511 | + Server.get_default ().show_timeout (minutes / MINUTE_INTERVAL, minutes % MINUTE_INTERVAL); |
2512 | + timeout_ids += Timeout.add_seconds (MINUTE_INTERVAL, () => { |
2513 | + minutes--; |
2514 | + if (minutes == MINUTE_INTERVAL || |
2515 | + minutes == 10 || |
2516 | + minutes == 5 || |
2517 | + minutes == 1) { |
2518 | + Server.get_default ().show_timeout (minutes / MINUTE_INTERVAL, minutes % MINUTE_INTERVAL); |
2519 | + } |
2520 | + |
2521 | + if (minutes == 0) { |
2522 | + terminate (); |
2523 | + } |
2524 | + |
2525 | + return (minutes > 0); |
2526 | + }); |
2527 | + } |
2528 | + } |
2529 | +} |
2530 | \ No newline at end of file |
2531 | |
2532 | === added file 'src/daemon/UserConfig.vala' |
2533 | --- src/daemon/UserConfig.vala 1970-01-01 00:00:00 +0000 |
2534 | +++ src/daemon/UserConfig.vala 2016-08-30 20:17:54 +0000 |
2535 | @@ -0,0 +1,208 @@ |
2536 | +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
2537 | +/*- |
2538 | + * Copyright (c) 2015-2016 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls) |
2539 | + * |
2540 | + * This library is free software; you can redistribute it and/or |
2541 | + * modify it under the terms of the GNU Library General Public |
2542 | + * License as published by the Free Software Foundation; either |
2543 | + * version 3 of the License, or (at your option) any later version. |
2544 | + * |
2545 | + * This library is distributed in the hope that it will be useful, |
2546 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2547 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2548 | + * Library General Public License for more details. |
2549 | + * |
2550 | + * You should have received a copy of the GNU Library General Public |
2551 | + * License along with this library; if not, write to the |
2552 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
2553 | + * Boston, MA 02111-1307, USA. |
2554 | + * |
2555 | + * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
2556 | + */ |
2557 | + |
2558 | +namespace PC.Daemon { |
2559 | + public class UserConfig : Object { |
2560 | + public string username; |
2561 | + public signal void changed (); |
2562 | + |
2563 | + private KeyFile key; |
2564 | + private string config_path; |
2565 | + |
2566 | + private static List<UserConfig> config_list; |
2567 | + |
2568 | + public static UserConfig? get_for_username (string username, bool create) { |
2569 | + foreach (UserConfig config in config_list) { |
2570 | + if (config.username == username) { |
2571 | + return config; |
2572 | + } |
2573 | + } |
2574 | + |
2575 | + if (create) { |
2576 | + return create_for_username (username); |
2577 | + } |
2578 | + |
2579 | + return null; |
2580 | + } |
2581 | + |
2582 | + public static List<UserConfig> get_all () { |
2583 | + return config_list.copy (); |
2584 | + } |
2585 | + |
2586 | + public static void init () { |
2587 | + config_list = new List<UserConfig> (); |
2588 | + |
2589 | + foreach (Act.User user in Utils.get_usermanager ().list_users ()) { |
2590 | + string config_path = Utils.build_daemon_conf_path (user); |
2591 | + if (!FileUtils.test (config_path, FileTest.IS_REGULAR)) { |
2592 | + continue; |
2593 | + } |
2594 | + |
2595 | + var key = new KeyFile (); |
2596 | + key.set_list_separator (';'); |
2597 | + try { |
2598 | + if (!key.load_from_file (config_path, KeyFileFlags.NONE)) { |
2599 | + continue; |
2600 | + } |
2601 | + } catch (KeyFileError e) { |
2602 | + warning (e.message); |
2603 | + continue; |
2604 | + } catch (FileError e) { |
2605 | + warning (e.message); |
2606 | + continue; |
2607 | + } |
2608 | + |
2609 | + var user_config = new UserConfig (config_path, user.get_user_name (), key); |
2610 | + config_list.append (user_config); |
2611 | + } |
2612 | + } |
2613 | + |
2614 | + private static UserConfig? create_for_username (string username) { |
2615 | + var user = Utils.get_usermanager ().get_user (username); |
2616 | + if (user == null) { |
2617 | + return null; |
2618 | + } |
2619 | + |
2620 | + string config_path = Utils.build_daemon_conf_path (user); |
2621 | + var file = File.new_for_path (config_path); |
2622 | + try { |
2623 | + file.create (FileCreateFlags.PRIVATE); |
2624 | + } catch (FileError e) { |
2625 | + warning (e.message); |
2626 | + return null; |
2627 | + } catch (Error e) { |
2628 | + warning (e.message); |
2629 | + return null; |
2630 | + } |
2631 | + |
2632 | + var config = new UserConfig (config_path, username, new KeyFile ()); |
2633 | + config_list.append (config); |
2634 | + return config; |
2635 | + } |
2636 | + |
2637 | + private UserConfig (string config_path, string username, KeyFile key) { |
2638 | + this.username = username; |
2639 | + this.key = key; |
2640 | + this.config_path = config_path; |
2641 | + monitor_file (); |
2642 | + } |
2643 | + |
2644 | + public void set_active (bool active) { |
2645 | + key.set_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ACTIVE, active); |
2646 | + save (); |
2647 | + } |
2648 | + |
2649 | + public void set_targets (string[] targets) { |
2650 | + key.set_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_TARGETS, targets); |
2651 | + save (); |
2652 | + } |
2653 | + |
2654 | + public void set_block_urls (string[] block_urls) { |
2655 | + key.set_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_BLOCK_URLS, block_urls); |
2656 | + save (); |
2657 | + } |
2658 | + |
2659 | + public void set_admin (bool admin) { |
2660 | + key.set_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ADMIN, admin); |
2661 | + save (); |
2662 | + } |
2663 | + |
2664 | + public bool get_active () { |
2665 | + try { |
2666 | + return key.get_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ACTIVE); |
2667 | + } catch (KeyFileError e) { |
2668 | + warning (e.message); |
2669 | + } |
2670 | + |
2671 | + return false; |
2672 | + } |
2673 | + |
2674 | + public string[] get_targets () { |
2675 | + try { |
2676 | + return key.get_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_TARGETS); |
2677 | + } catch (KeyFileError e) { |
2678 | + warning (e.message); |
2679 | + } |
2680 | + |
2681 | + return {}; |
2682 | + } |
2683 | + |
2684 | + public string[] get_block_urls () { |
2685 | + try { |
2686 | + return key.get_string_list (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_BLOCK_URLS); |
2687 | + } catch (KeyFileError e) { |
2688 | + warning (e.message); |
2689 | + } |
2690 | + |
2691 | + return {}; |
2692 | + } |
2693 | + |
2694 | + public bool get_admin () { |
2695 | + try { |
2696 | + return key.get_boolean (Vars.DAEMON_GROUP, Vars.DAEMON_KEY_ADMIN); |
2697 | + } catch (KeyFileError e) { |
2698 | + warning (e.message); |
2699 | + } |
2700 | + |
2701 | + return false; |
2702 | + } |
2703 | + |
2704 | + private void monitor_file () { |
2705 | + var file = File.new_for_path (config_path); |
2706 | + try { |
2707 | + var monitor = file.monitor (FileMonitorFlags.NONE, null); |
2708 | + monitor.changed.connect ((src, dest, event) => { |
2709 | + if (event == FileMonitorEvent.CHANGES_DONE_HINT) { |
2710 | + update_key (); |
2711 | + |
2712 | + Server.get_default ().user_config_changed (username); |
2713 | + changed (); |
2714 | + } |
2715 | + }); |
2716 | + } catch (Error e) { |
2717 | + warning (e.message); |
2718 | + } |
2719 | + } |
2720 | + |
2721 | + private void update_key () { |
2722 | + try { |
2723 | + key.load_from_file (config_path, KeyFileFlags.NONE); |
2724 | + } catch (KeyFileError e) { |
2725 | + warning (e.message); |
2726 | + } catch (FileError e) { |
2727 | + warning (e.message); |
2728 | + } |
2729 | + } |
2730 | + |
2731 | + private void save () { |
2732 | + try { |
2733 | + key.save_to_file (config_path); |
2734 | + } catch (FileError e) { |
2735 | + warning (e.message); |
2736 | + return; |
2737 | + } |
2738 | + |
2739 | + Server.get_default ().user_config_changed (username); |
2740 | + changed (); |
2741 | + } |
2742 | + } |
2743 | +} |
2744 | \ No newline at end of file |
2745 | |
2746 | === added directory 'src/shared/PAM' |
2747 | === added file 'src/shared/PAM/Reader.vala' |
2748 | --- src/shared/PAM/Reader.vala 1970-01-01 00:00:00 +0000 |
2749 | +++ src/shared/PAM/Reader.vala 2016-08-30 20:17:54 +0000 |
2750 | @@ -0,0 +1,66 @@ |
2751 | +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
2752 | +/*- |
2753 | + * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls) |
2754 | + * |
2755 | + * This library is free software; you can redistribute it and/or |
2756 | + * modify it under the terms of the GNU Library General Public |
2757 | + * License as published by the Free Software Foundation; either |
2758 | + * version 3 of the License, or (at your option) any later version. |
2759 | + * |
2760 | + * This library is distributed in the hope that it will be useful, |
2761 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2762 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2763 | + * Library General Public License for more details. |
2764 | + * |
2765 | + * You should have received a copy of the GNU Library General Public |
2766 | + * License along with this library; if not, write to the |
2767 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
2768 | + * Boston, MA 02111-1307, USA. |
2769 | + * |
2770 | + * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
2771 | + */ |
2772 | + |
2773 | +namespace PC.PAM { |
2774 | + public class Reader : Object { |
2775 | + public static string get_config (string contents, bool ignore_comments = true) { |
2776 | + string config = ""; |
2777 | + |
2778 | + int start_idx = contents.index_of (Vars.PAM_CONF_START); |
2779 | + int end_idx = contents.index_of (Vars.PAM_CONF_END) + Vars.PAM_CONF_END.char_count (); |
2780 | + if (start_idx == -1 || end_idx == -1) { |
2781 | + return config; |
2782 | + } |
2783 | + |
2784 | + config = contents.slice (start_idx, end_idx); |
2785 | + |
2786 | + if (ignore_comments) { |
2787 | + return Utils.remove_comments (config); |
2788 | + } |
2789 | + |
2790 | + return config; |
2791 | + } |
2792 | + |
2793 | + public static List<Token> get_tokens (string filename) { |
2794 | + string contents; |
2795 | + try { |
2796 | + FileUtils.get_contents (filename, out contents); |
2797 | + } catch (FileError e) { |
2798 | + warning (e.message); |
2799 | + return new List<Token> (); |
2800 | + } |
2801 | + |
2802 | + string config = get_config (contents); |
2803 | + return Token.parse (config); |
2804 | + } |
2805 | + |
2806 | + public static Token? get_token_for_user (string filename, string username) { |
2807 | + foreach (Token token in get_tokens (filename)) { |
2808 | + if (token.get_user_arg0 () == username) { |
2809 | + return token; |
2810 | + } |
2811 | + } |
2812 | + |
2813 | + return null; |
2814 | + } |
2815 | + } |
2816 | +} |
2817 | \ No newline at end of file |
2818 | |
2819 | === added file 'src/shared/PAM/Token.vala' |
2820 | --- src/shared/PAM/Token.vala 1970-01-01 00:00:00 +0000 |
2821 | +++ src/shared/PAM/Token.vala 2016-08-30 20:17:54 +0000 |
2822 | @@ -0,0 +1,190 @@ |
2823 | +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
2824 | +/*- |
2825 | + * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls) |
2826 | + * |
2827 | + * This library is free software; you can redistribute it and/or |
2828 | + * modify it under the terms of the GNU Library General Public |
2829 | + * License as published by the Free Software Foundation; either |
2830 | + * version 3 of the License, or (at your option) any later version. |
2831 | + * |
2832 | + * This library is distributed in the hope that it will be useful, |
2833 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2834 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2835 | + * Library General Public License for more details. |
2836 | + * |
2837 | + * You should have received a copy of the GNU Library General Public |
2838 | + * License along with this library; if not, write to the |
2839 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
2840 | + * Boston, MA 02111-1307, USA. |
2841 | + * |
2842 | + * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
2843 | + */ |
2844 | + |
2845 | +namespace PC.PAM { |
2846 | + public enum DayType { |
2847 | + UNKNOWN, |
2848 | + ALL, |
2849 | + WEEKDAY, |
2850 | + WEEKEND; |
2851 | + |
2852 | + public static DayType to_enum (string str) { |
2853 | + switch (str) { |
2854 | + case "Al": |
2855 | + return ALL; |
2856 | + case "Wk": |
2857 | + return WEEKDAY; |
2858 | + case "Wd": |
2859 | + return WEEKEND; |
2860 | + default: |
2861 | + return UNKNOWN; |
2862 | + } |
2863 | + } |
2864 | + |
2865 | + public string to_string () { |
2866 | + switch (this) { |
2867 | + case ALL: |
2868 | + return "Al"; |
2869 | + case WEEKDAY: |
2870 | + return "Wk"; |
2871 | + case WEEKEND: |
2872 | + return "Wd"; |
2873 | + default: |
2874 | + case UNKNOWN: |
2875 | + return "unknown"; |
2876 | + } |
2877 | + } |
2878 | + } |
2879 | + |
2880 | + public class TimeInfo { |
2881 | + public DayType day_type = DayType.UNKNOWN; |
2882 | + public string from = ""; |
2883 | + public string to = ""; |
2884 | + } |
2885 | + |
2886 | + public class Token : Object { |
2887 | + private const int SERVICES_INDEX = 0; |
2888 | + private const int TTYS_INDEX = 1; |
2889 | + private const int USERS_INDEX = 2; |
2890 | + private const int TIMES_INDEX = 3; |
2891 | + |
2892 | + private const string TYPE_SEPARATOR = ";"; |
2893 | + private const string LIST_SEPARATOR = "|"; |
2894 | + |
2895 | + public string[] services; |
2896 | + public string[] ttys; |
2897 | + public string[] users; |
2898 | + public string[] times; |
2899 | + |
2900 | + public static Token? parse_line (string line) { |
2901 | + string[] strv = line.split (TYPE_SEPARATOR); |
2902 | + if (strv.length != 4) { |
2903 | + return null; |
2904 | + } |
2905 | + |
2906 | + var token = new Token (); |
2907 | + token.services = strv[SERVICES_INDEX].split (LIST_SEPARATOR); |
2908 | + token.ttys = strv[TTYS_INDEX].split (LIST_SEPARATOR); |
2909 | + token.users = strv[USERS_INDEX].split (LIST_SEPARATOR); |
2910 | + token.times = strv[TIMES_INDEX].split (LIST_SEPARATOR); |
2911 | + return token; |
2912 | + } |
2913 | + |
2914 | + public static List<Token> parse (string str) { |
2915 | + var list = new List<Token> (); |
2916 | + |
2917 | + foreach (string line in str.split ("\n")) { |
2918 | + var token = parse_line (line); |
2919 | + if (token != null) { |
2920 | + list.append (token); |
2921 | + } |
2922 | + } |
2923 | + |
2924 | + return list; |
2925 | + } |
2926 | + |
2927 | + public static string construct_pam_restriction (string[] services, string[] ttys, string users[], string[] times) { |
2928 | + string services_str = string.joinv (LIST_SEPARATOR, services); |
2929 | + string ttys_str = string.joinv (LIST_SEPARATOR, ttys); |
2930 | + string users_str = string.joinv (LIST_SEPARATOR, users); |
2931 | + string times_str = string.joinv (LIST_SEPARATOR, times); |
2932 | + |
2933 | + return "%s;%s;%s;%s".printf (services_str, ttys_str, users_str, times_str); |
2934 | + } |
2935 | + |
2936 | + public static string construct_pam_restriction_simple (string[] users, string[] times) { |
2937 | + return construct_pam_restriction ({ "*" }, { "*" }, users, times); |
2938 | + } |
2939 | + |
2940 | + public List<TimeInfo> get_times_info () { |
2941 | + var list = new List<TimeInfo> (); |
2942 | + |
2943 | + if (times.length == 0) { |
2944 | + return list; |
2945 | + } |
2946 | + |
2947 | + foreach (string time in times) { |
2948 | + string[] bounds = time.substring (2).split ("-"); |
2949 | + if (bounds.length < 2) { |
2950 | + continue; |
2951 | + } |
2952 | + |
2953 | + var info = new TimeInfo (); |
2954 | + info.day_type = DayType.to_enum (time.slice (0, 2)); |
2955 | + info.from = bounds[0]; |
2956 | + info.to = bounds[1]; |
2957 | + |
2958 | + list.append (info); |
2959 | + } |
2960 | + |
2961 | + return list; |
2962 | + } |
2963 | + |
2964 | + public string get_user_arg0 () { |
2965 | + if (users.length == 0) { |
2966 | + return ""; |
2967 | + } |
2968 | + |
2969 | + return users[0]; |
2970 | + } |
2971 | + |
2972 | + public string to_string () { |
2973 | + return construct_pam_restriction (services, ttys, users, times); |
2974 | + } |
2975 | + |
2976 | + public void get_weekday_hours (out int from, out int to) { |
2977 | + if (times.length < 1) { |
2978 | + from = 0; |
2979 | + to = 0; |
2980 | + return; |
2981 | + } |
2982 | + |
2983 | + string[] bounds = times[0].substring (2).split ("-"); |
2984 | + if (bounds.length < 2) { |
2985 | + from = 0; |
2986 | + to = 0; |
2987 | + return; |
2988 | + } |
2989 | + |
2990 | + from = int.parse (bounds[0]); |
2991 | + to = int.parse (bounds[1]); |
2992 | + } |
2993 | + |
2994 | + public void get_weekend_hours (out int from, out int to) { |
2995 | + if (times.length < 2) { |
2996 | + from = 0; |
2997 | + to = 0; |
2998 | + return; |
2999 | + } |
3000 | + |
3001 | + string[] bounds = times[1].split ("-"); |
3002 | + if (bounds.length < 2) { |
3003 | + from = 0; |
3004 | + to = 0; |
3005 | + return; |
3006 | + } |
3007 | + |
3008 | + from = int.parse (bounds[0]); |
3009 | + to = int.parse (bounds[1]); |
3010 | + } |
3011 | + } |
3012 | +} |
3013 | \ No newline at end of file |
3014 | |
3015 | === added file 'src/shared/PAM/Writer.vala' |
3016 | --- src/shared/PAM/Writer.vala 1970-01-01 00:00:00 +0000 |
3017 | +++ src/shared/PAM/Writer.vala 2016-08-30 20:17:54 +0000 |
3018 | @@ -0,0 +1,110 @@ |
3019 | +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
3020 | +/*- |
3021 | + * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls) |
3022 | + * |
3023 | + * This library is free software; you can redistribute it and/or |
3024 | + * modify it under the terms of the GNU Library General Public |
3025 | + * License as published by the Free Software Foundation; either |
3026 | + * version 3 of the License, or (at your option) any later version. |
3027 | + * |
3028 | + * This library is distributed in the hope that it will be useful, |
3029 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3030 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
3031 | + * Library General Public License for more details. |
3032 | + * |
3033 | + * You should have received a copy of the GNU Library General Public |
3034 | + * License along with this library; if not, write to the |
3035 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
3036 | + * Boston, MA 02111-1307, USA. |
3037 | + * |
3038 | + * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
3039 | + */ |
3040 | + |
3041 | +namespace PC.PAM { |
3042 | + public class Writer : Object { |
3043 | + private string filename; |
3044 | + |
3045 | + public static Writer new_for_time () { |
3046 | + return new Writer (Vars.PAM_TIME_CONF_PATH); |
3047 | + } |
3048 | + |
3049 | + public Writer (string filename) { |
3050 | + this.filename = filename; |
3051 | + } |
3052 | + |
3053 | + public void add_restriction_for_user (string input, bool clean) { |
3054 | + if (clean) { |
3055 | + var token = Token.parse_line (input); |
3056 | + if (token != null) { |
3057 | + string username = token.get_user_arg0 (); |
3058 | + if (Reader.get_token_for_user (filename, username) != null) { |
3059 | + remove_restriction_for_user (username); |
3060 | + } |
3061 | + } |
3062 | + } |
3063 | + |
3064 | + string contents; |
3065 | + try { |
3066 | + FileUtils.get_contents (filename, out contents); |
3067 | + } catch (FileError e) { |
3068 | + warning (e.message); |
3069 | + return; |
3070 | + } |
3071 | + |
3072 | + string config = Reader.get_config (contents, false); |
3073 | + |
3074 | + var builder = new StringBuilder (Vars.PAM_CONF_START); |
3075 | + if (config != "") { |
3076 | + builder.append ("\n"); |
3077 | + builder.append (Utils.remove_comments (config)); |
3078 | + } else { |
3079 | + builder.append ("\n"); |
3080 | + } |
3081 | + |
3082 | + builder.append (input); |
3083 | + builder.append ("\n"); |
3084 | + builder.append (Vars.PAM_CONF_END); |
3085 | + |
3086 | + try { |
3087 | + if (config != "") { |
3088 | + FileUtils.set_contents (filename, contents.replace (config, builder.str)); |
3089 | + } else { |
3090 | + FileUtils.set_contents (filename, "\n%s\n%s\n".printf (contents, builder.str)); |
3091 | + } |
3092 | + } catch (FileError e) { |
3093 | + warning ("%s\n", e.message); |
3094 | + } |
3095 | + } |
3096 | + |
3097 | + public void remove_restriction_for_user (string username) { |
3098 | + string contents; |
3099 | + try { |
3100 | + FileUtils.get_contents (filename, out contents); |
3101 | + } catch (FileError e) { |
3102 | + warning (e.message); |
3103 | + return; |
3104 | + } |
3105 | + |
3106 | + string config = Reader.get_config (contents); |
3107 | + |
3108 | + if (config == "") { |
3109 | + return; |
3110 | + } |
3111 | + |
3112 | + string buffer = ""; |
3113 | + |
3114 | + foreach (string line in config.split ("\n")) { |
3115 | + var token = Token.parse_line (line); |
3116 | + if (token != null && token.get_user_arg0 () != username) { |
3117 | + buffer += line; |
3118 | + } |
3119 | + } |
3120 | + |
3121 | + try { |
3122 | + FileUtils.set_contents (filename, contents.replace (config, buffer)); |
3123 | + } catch (FileError e) { |
3124 | + warning ("%s\n", e.message); |
3125 | + } |
3126 | + } |
3127 | + } |
3128 | +} |
3129 | \ No newline at end of file |
3130 | |
3131 | === removed file 'src/shared/PAMControl.vala' |
3132 | --- src/shared/PAMControl.vala 2016-02-21 18:52:25 +0000 |
3133 | +++ src/shared/PAMControl.vala 1970-01-01 00:00:00 +0000 |
3134 | @@ -1,128 +0,0 @@ |
3135 | -// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
3136 | -/*- |
3137 | - * Copyright (c) 2015 Adam Bieńkowski (https://launchpad.net/switchboard-plug-parental-controls) |
3138 | - * |
3139 | - * This library is free software; you can redistribute it and/or |
3140 | - * modify it under the terms of the GNU Library General Public |
3141 | - * License as published by the Free Software Foundation; either |
3142 | - * version 3 of the License, or (at your option) any later version. |
3143 | - * |
3144 | - * This library is distributed in the hope that it will be useful, |
3145 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3146 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
3147 | - * Library General Public License for more details. |
3148 | - * |
3149 | - * You should have received a copy of the GNU Library General Public |
3150 | - * License along with this library; if not, write to the |
3151 | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
3152 | - * Boston, MA 02111-1307, USA. |
3153 | - * |
3154 | - * Authored by: Adam Bieńkowski <donadigos159@gmail.com> |
3155 | - */ |
3156 | - |
3157 | -namespace PC { |
3158 | - public class PAMRestrictInfo : Object { |
3159 | - public string user; |
3160 | - public string day_id; |
3161 | - public string weekday_hours; |
3162 | - public string weekend_hours; |
3163 | - public string from; |
3164 | - public string to; |
3165 | - } |
3166 | - |
3167 | - public class PAMControl : Object { |
3168 | - private static string get_conf_section () { |
3169 | - string contents = ""; |
3170 | - try { |
3171 | - FileUtils.get_contents ("/etc/security/time.conf", out contents); |
3172 | - } catch (FileError e) { |
3173 | - warning ("%s\n", e.message); |
3174 | - } |
3175 | - |
3176 | - try { |
3177 | - var regex = new Regex (Vars.PAM_CONF_REGEX); |
3178 | - |
3179 | - if (regex.match (contents)) { |
3180 | - int i = 0; |
3181 | - foreach (string str in regex.split (contents)) { |
3182 | - // Do not replace the contents of the PC plug section |
3183 | - if (i != 1) { |
3184 | - contents = contents.replace (str, ""); |
3185 | - } |
3186 | - |
3187 | - i++; |
3188 | - } |
3189 | - } else { |
3190 | - return ""; |
3191 | - } |
3192 | - } catch (RegexError e) { |
3193 | - warning ("%s\n", e.message); |
3194 | - } |
3195 | - |
3196 | - |
3197 | - return contents; |
3198 | - } |
3199 | - |
3200 | - public static List<PAMRestrictInfo?> get_all_restrictions () { |
3201 | - var retval = new List<PAMRestrictInfo?> (); |
3202 | - string conf = get_conf_section (); |
3203 | - |
3204 | - foreach (string line in conf.split ("\n")) { |
3205 | - if (!line.has_prefix ("#")) { |
3206 | - var restrict_info = new PAMRestrictInfo (); |
3207 | - string[] units = line.split (";"); |
3208 | - if (units.length >= 4) { |
3209 | - restrict_info.user = units[2]; |
3210 | - string time = units[3]; |
3211 | - time = time.replace ("!", ""); |
3212 | - |
3213 | - char[] time_chars = time.to_utf8 (); |
3214 | - string day = time_chars[0].to_string () + time_chars[1].to_string (); |
3215 | - switch (day.down ()) { |
3216 | - case "al": |
3217 | - restrict_info.day_id = "all"; |
3218 | - break; |
3219 | - case "wk": |
3220 | - restrict_info.day_id = "weekdays"; |
3221 | - break; |
3222 | - case "wd": |
3223 | - restrict_info.day_id = "weekends"; |
3224 | - break; |
3225 | - default: |
3226 | - restrict_info.day_id = ""; |
3227 | - break; |
3228 | - } |
3229 | - |
3230 | - string hours = time.replace (day, ""); |
3231 | - string[] tmp = {}; |
3232 | - if ("|" in hours) { |
3233 | - tmp = hours.split ("|"); |
3234 | - restrict_info.weekday_hours = tmp[0]; |
3235 | - restrict_info.weekend_hours = tmp[1]; |
3236 | - } else { |
3237 | - tmp = hours.split ("-"); |
3238 | - restrict_info.from = tmp[0]; |
3239 | - restrict_info.to = tmp[1]; |
3240 | - } |
3241 | - |
3242 | - retval.append (restrict_info); |
3243 | - } |
3244 | - } |
3245 | - } |
3246 | - |
3247 | - return retval; |
3248 | - } |
3249 | - |
3250 | - public static void try_add_restrict_line (string user_name, string restrict) { |
3251 | - if (Utils.get_permission ().allowed) { |
3252 | - Utils.call_cli ({"--user", user_name, "--restrict-pam-line", restrict}); |
3253 | - } |
3254 | - } |
3255 | - |
3256 | - public static void try_remove_user_restrict (string user_name) { |
3257 | - if (Utils.get_permission ().allowed) { |
3258 | - Utils.call_cli ({"--user", user_name, "--remove-restrict"}); |
3259 | - } |
3260 | - } |
3261 | - } |
3262 | -} |
3263 | \ No newline at end of file |
3264 | |
3265 | === modified file 'src/shared/Utils.vala' |
3266 | --- src/shared/Utils.vala 2016-07-27 16:14:53 +0000 |
3267 | +++ src/shared/Utils.vala 2016-08-30 20:17:54 +0000 |
3268 | @@ -27,11 +27,62 @@ |
3269 | public abstract void printer_set_users_denied (string printer, string[] users) throws IOError; |
3270 | } |
3271 | |
3272 | - public class Utils : Object { |
3273 | - public static Polkit.Permission? permission = null; |
3274 | - public static string user_name; |
3275 | - |
3276 | + [DBus (name = "org.pantheon.ParentalControls")] |
3277 | + public interface IParentalControls : Object { |
3278 | + public abstract async void add_restriction_for_user (string input, bool clean) throws IOError; |
3279 | + public abstract async void remove_restriction_for_user (string username) throws IOError; |
3280 | + public abstract async void end_app_authorization () throws IOError; |
3281 | + public abstract async bool get_user_daemon_active (string username) throws IOError; |
3282 | + public abstract async bool get_user_daemon_admin (string username) throws IOError; |
3283 | + public abstract async string[] get_user_daemon_block_urls (string username) throws IOError; |
3284 | + public abstract async string[] get_user_daemon_targets (string username) throws IOError; |
3285 | + public abstract async void lock_dock_icons_for_user (string username, bool lock) throws IOError; |
3286 | + public abstract async void set_user_daemon_active (string username, bool active) throws IOError; |
3287 | + public abstract async void set_user_daemon_admin (string username, bool admin) throws IOError; |
3288 | + public abstract async void set_user_daemon_block_urls (string username, string[] block_urls) throws IOError; |
3289 | + public abstract async void set_user_daemon_targets (string username, string[] targets) throws IOError; |
3290 | + |
3291 | + public signal void app_authorize (string username, string path, string action_id); |
3292 | + public signal void launch (string[] args); |
3293 | + public signal void show_app_unavailable (string path); |
3294 | + public signal void show_timeout (int hours, int minutes); |
3295 | + public signal void user_config_changed (string username); |
3296 | + } |
3297 | + |
3298 | + public class Utils { |
3299 | + public class DummyParentalControls : Object, IParentalControls { |
3300 | + public async void add_restriction_for_user (string input, bool clean) throws IOError {} |
3301 | + public async void remove_restriction_for_user (string username) throws IOError {} |
3302 | + public async void end_app_authorization () throws IOError {} |
3303 | + public async bool get_user_daemon_active (string username) throws IOError { return false; } |
3304 | + public async bool get_user_daemon_admin (string username) throws IOError { return false; } |
3305 | + public async string[] get_user_daemon_block_urls (string username) throws IOError { return {}; } |
3306 | + public async string[] get_user_daemon_targets (string username) throws IOError { return {}; } |
3307 | + public async void lock_dock_icons_for_user (string username, bool lock) throws IOError {} |
3308 | + public async void set_user_daemon_active (string username, bool active) throws IOError {} |
3309 | + public async void set_user_daemon_admin (string username, bool admin) throws IOError {} |
3310 | + public async void set_user_daemon_block_urls (string username, string[] block_urls) throws IOError {} |
3311 | + public async void set_user_daemon_targets (string username, string[] targets) throws IOError {} |
3312 | + } |
3313 | + |
3314 | + private static Polkit.Permission? permission = null; |
3315 | private static Act.UserManager? usermanager = null; |
3316 | + private static IParentalControls? api = null; |
3317 | + |
3318 | + public static IParentalControls? get_api () { |
3319 | + if (api != null) { |
3320 | + return api; |
3321 | + } |
3322 | + |
3323 | + try { |
3324 | + api = Bus.get_proxy_sync (BusType.SYSTEM, Vars.PARENTAL_CONTROLS_IFACE, Vars.PARENTAL_CONTROLS_OBJECT_PATH); |
3325 | + } catch (Error e) { |
3326 | + critical ("%s, using dummy parental controls backend", e.message); |
3327 | + api = new DummyParentalControls (); |
3328 | + } |
3329 | + |
3330 | + return api; |
3331 | + } |
3332 | |
3333 | public static Polkit.Permission? get_permission () { |
3334 | if (permission != null) { |
3335 | @@ -39,9 +90,9 @@ |
3336 | } |
3337 | |
3338 | try { |
3339 | - var user = (Polkit.UnixUser)Polkit.UnixUser.new_for_name (user_name); |
3340 | + var user = (Polkit.UnixUser)Polkit.UnixUser.new_for_name (Environment.get_user_name ()); |
3341 | permission = new Polkit.Permission.sync (Vars.PARENTAL_CONTROLS_ACTION_ID, |
3342 | - Polkit.UnixProcess.new_for_owner (Posix.getpid (), 0, user.get_uid ())); |
3343 | + Polkit.UnixProcess.new_for_owner (Posix.getpid (), 0, user.get_uid ())); |
3344 | return permission; |
3345 | } catch (Error e) { |
3346 | critical (e.message); |
3347 | @@ -56,29 +107,6 @@ |
3348 | return @"<span font_weight=\"bold\" size=\"large\">$escaped_name</span>\n$escaped_comment"; |
3349 | } |
3350 | |
3351 | - public static void call_cli (string[] args) { |
3352 | - string[] spawn_args = { "pkexec", "pantheon-parental-controls-cli" }; |
3353 | - foreach (string arg in args) { |
3354 | - spawn_args += arg; |
3355 | - } |
3356 | - |
3357 | - try { |
3358 | - Pid child_pid; |
3359 | - Process.spawn_async ("/", |
3360 | - spawn_args, |
3361 | - Environ.get (), |
3362 | - SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD, |
3363 | - null, |
3364 | - out child_pid); |
3365 | - ChildWatch.add (child_pid, (pid, status) => { |
3366 | - Process.close_pid (pid); |
3367 | - }); |
3368 | - |
3369 | - } catch (SpawnError e) { |
3370 | - warning ("%s\n", e.message); |
3371 | - } |
3372 | - } |
3373 | - |
3374 | public static unowned Act.UserManager? get_usermanager () { |
3375 | if (usermanager != null) { |
3376 | return usermanager; |
3377 | @@ -89,15 +117,24 @@ |
3378 | } |
3379 | |
3380 | public static unowned Act.User? get_current_user () { |
3381 | - return get_usermanager ().get_user (user_name); |
3382 | + return get_usermanager ().get_user (Environment.get_user_name ()); |
3383 | + } |
3384 | + |
3385 | + public static string remove_comments (string str) { |
3386 | + string buffer = ""; |
3387 | + |
3388 | + foreach (string line in str.split ("\n")) { |
3389 | + if (!line.strip ().has_prefix ("#")) { |
3390 | + buffer += line; |
3391 | + buffer += "\n"; |
3392 | + } |
3393 | + } |
3394 | + |
3395 | + return buffer; |
3396 | } |
3397 | |
3398 | public static string build_daemon_conf_path (Act.User user) { |
3399 | return Path.build_filename (user.get_home_dir (), Vars.DAEMON_CONF_DIR); |
3400 | } |
3401 | - |
3402 | - public static void set_user_name (string _user_name) { |
3403 | - user_name = _user_name; |
3404 | - } |
3405 | } |
3406 | } |
3407 | |
3408 | === modified file 'src/shared/Vars.vala' |
3409 | --- src/shared/Vars.vala 2016-07-27 16:14:53 +0000 |
3410 | +++ src/shared/Vars.vala 2016-08-30 20:17:54 +0000 |
3411 | @@ -41,7 +41,5 @@ |
3412 | public const string PAM_CONF_START = "## PANTHEON_PARENTAL_CONTROLS_START"; |
3413 | public const string PAM_CONF_END = "## PANTHEON_PARENTAL_CONTROLS_END"; |
3414 | public const string PAM_CONF_REGEX = PAM_CONF_START + "|" + PAM_CONF_END; |
3415 | - public const string ALL_ID = "all"; |
3416 | - public const string WEEKDAYS_ID = "weekdays"; |
3417 | - public const string WEEKENDS_ID = "weekends"; |
3418 | + public const string PAM_TIME_CONF_PATH = "/etc/security/time.conf"; |
3419 | } |
3420 | \ No newline at end of file |