diff options
Diffstat (limited to 'swaylock/password.c')
-rw-r--r-- | swaylock/password.c | 190 |
1 files changed, 0 insertions, 190 deletions
diff --git a/swaylock/password.c b/swaylock/password.c deleted file mode 100644 index 3bd113ad..00000000 --- a/swaylock/password.c +++ /dev/null | |||
@@ -1,190 +0,0 @@ | |||
1 | #include <assert.h> | ||
2 | #include <errno.h> | ||
3 | #include <pwd.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | #include <unistd.h> | ||
7 | #include <wlr/util/log.h> | ||
8 | #include <xkbcommon/xkbcommon.h> | ||
9 | #include "swaylock/swaylock.h" | ||
10 | #include "swaylock/seat.h" | ||
11 | #include "loop.h" | ||
12 | #include "unicode.h" | ||
13 | |||
14 | void clear_password_buffer(struct swaylock_password *pw) { | ||
15 | // Use volatile keyword so so compiler can't optimize this out. | ||
16 | volatile char *buffer = pw->buffer; | ||
17 | volatile char zero = '\0'; | ||
18 | for (size_t i = 0; i < sizeof(pw->buffer); ++i) { | ||
19 | buffer[i] = zero; | ||
20 | } | ||
21 | pw->len = 0; | ||
22 | } | ||
23 | |||
24 | static bool backspace(struct swaylock_password *pw) { | ||
25 | if (pw->len != 0) { | ||
26 | pw->buffer[--pw->len] = 0; | ||
27 | return true; | ||
28 | } | ||
29 | return false; | ||
30 | } | ||
31 | |||
32 | static void append_ch(struct swaylock_password *pw, uint32_t codepoint) { | ||
33 | size_t utf8_size = utf8_chsize(codepoint); | ||
34 | if (pw->len + utf8_size + 1 >= sizeof(pw->buffer)) { | ||
35 | // TODO: Display error | ||
36 | return; | ||
37 | } | ||
38 | utf8_encode(&pw->buffer[pw->len], codepoint); | ||
39 | pw->buffer[pw->len + utf8_size] = 0; | ||
40 | pw->len += utf8_size; | ||
41 | } | ||
42 | |||
43 | static void clear_indicator(void *data) { | ||
44 | struct swaylock_state *state = data; | ||
45 | state->clear_indicator_timer = NULL; | ||
46 | state->auth_state = AUTH_STATE_IDLE; | ||
47 | damage_state(state); | ||
48 | } | ||
49 | |||
50 | static void schedule_indicator_clear(struct swaylock_state *state) { | ||
51 | if (state->clear_indicator_timer) { | ||
52 | loop_remove_timer(state->eventloop, state->clear_indicator_timer); | ||
53 | } | ||
54 | state->clear_indicator_timer = loop_add_timer( | ||
55 | state->eventloop, 3000, clear_indicator, state); | ||
56 | } | ||
57 | |||
58 | static void clear_password(void *data) { | ||
59 | struct swaylock_state *state = data; | ||
60 | state->clear_password_timer = NULL; | ||
61 | state->auth_state = AUTH_STATE_CLEAR; | ||
62 | clear_password_buffer(&state->password); | ||
63 | damage_state(state); | ||
64 | schedule_indicator_clear(state); | ||
65 | } | ||
66 | |||
67 | static void schedule_password_clear(struct swaylock_state *state) { | ||
68 | if (state->clear_password_timer) { | ||
69 | loop_remove_timer(state->eventloop, state->clear_password_timer); | ||
70 | } | ||
71 | state->clear_password_timer = loop_add_timer( | ||
72 | state->eventloop, 10000, clear_password, state); | ||
73 | } | ||
74 | |||
75 | static void handle_preverify_timeout(void *data) { | ||
76 | struct swaylock_state *state = data; | ||
77 | state->verify_password_timer = NULL; | ||
78 | } | ||
79 | |||
80 | static void submit_password(struct swaylock_state *state) { | ||
81 | if (state->args.ignore_empty && state->password.len == 0) { | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | state->auth_state = AUTH_STATE_VALIDATING; | ||
86 | damage_state(state); | ||
87 | |||
88 | // We generally want to wait until all surfaces are showing the | ||
89 | // "verifying" state before we go and verify the password, because | ||
90 | // verifying it is a blocking operation. However, if the surface is on | ||
91 | // an output with DPMS off then it won't update, so we set a timer. | ||
92 | state->verify_password_timer = loop_add_timer( | ||
93 | state->eventloop, 50, handle_preverify_timeout, state); | ||
94 | |||
95 | while (state->run_display && state->verify_password_timer) { | ||
96 | errno = 0; | ||
97 | if (wl_display_flush(state->display) == -1 && errno != EAGAIN) { | ||
98 | break; | ||
99 | } | ||
100 | loop_poll(state->eventloop); | ||
101 | |||
102 | bool ok = 1; | ||
103 | struct swaylock_surface *surface; | ||
104 | wl_list_for_each(surface, &state->surfaces, link) { | ||
105 | if (surface->dirty) { | ||
106 | ok = 0; | ||
107 | } | ||
108 | } | ||
109 | if (ok) { | ||
110 | break; | ||
111 | } | ||
112 | } | ||
113 | wl_display_flush(state->display); | ||
114 | |||
115 | if (attempt_password(&state->password)) { | ||
116 | state->run_display = false; | ||
117 | return; | ||
118 | } | ||
119 | state->auth_state = AUTH_STATE_INVALID; | ||
120 | damage_state(state); | ||
121 | schedule_indicator_clear(state); | ||
122 | } | ||
123 | |||
124 | void swaylock_handle_key(struct swaylock_state *state, | ||
125 | xkb_keysym_t keysym, uint32_t codepoint) { | ||
126 | switch (keysym) { | ||
127 | case XKB_KEY_KP_Enter: /* fallthrough */ | ||
128 | case XKB_KEY_Return: | ||
129 | submit_password(state); | ||
130 | break; | ||
131 | case XKB_KEY_Delete: | ||
132 | case XKB_KEY_BackSpace: | ||
133 | if (backspace(&state->password)) { | ||
134 | state->auth_state = AUTH_STATE_BACKSPACE; | ||
135 | } else { | ||
136 | state->auth_state = AUTH_STATE_CLEAR; | ||
137 | } | ||
138 | damage_state(state); | ||
139 | schedule_indicator_clear(state); | ||
140 | schedule_password_clear(state); | ||
141 | break; | ||
142 | case XKB_KEY_Escape: | ||
143 | clear_password_buffer(&state->password); | ||
144 | state->auth_state = AUTH_STATE_CLEAR; | ||
145 | damage_state(state); | ||
146 | schedule_indicator_clear(state); | ||
147 | break; | ||
148 | case XKB_KEY_Caps_Lock: | ||
149 | case XKB_KEY_Shift_L: | ||
150 | case XKB_KEY_Shift_R: | ||
151 | case XKB_KEY_Control_L: | ||
152 | case XKB_KEY_Control_R: | ||
153 | case XKB_KEY_Meta_L: | ||
154 | case XKB_KEY_Meta_R: | ||
155 | case XKB_KEY_Alt_L: | ||
156 | case XKB_KEY_Alt_R: | ||
157 | case XKB_KEY_Super_L: | ||
158 | case XKB_KEY_Super_R: | ||
159 | state->auth_state = AUTH_STATE_INPUT_NOP; | ||
160 | damage_state(state); | ||
161 | schedule_indicator_clear(state); | ||
162 | schedule_password_clear(state); | ||
163 | break; | ||
164 | case XKB_KEY_d: | ||
165 | if (state->xkb.control) { | ||
166 | submit_password(state); | ||
167 | break; | ||
168 | } | ||
169 | // fallthrough | ||
170 | case XKB_KEY_c: /* fallthrough */ | ||
171 | case XKB_KEY_u: | ||
172 | if (state->xkb.control) { | ||
173 | clear_password_buffer(&state->password); | ||
174 | state->auth_state = AUTH_STATE_CLEAR; | ||
175 | damage_state(state); | ||
176 | schedule_indicator_clear(state); | ||
177 | break; | ||
178 | } | ||
179 | // fallthrough | ||
180 | default: | ||
181 | if (codepoint) { | ||
182 | append_ch(&state->password, codepoint); | ||
183 | state->auth_state = AUTH_STATE_INPUT; | ||
184 | damage_state(state); | ||
185 | schedule_indicator_clear(state); | ||
186 | schedule_password_clear(state); | ||
187 | } | ||
188 | break; | ||
189 | } | ||
190 | } | ||