aboutsummaryrefslogtreecommitdiffstats
path: root/swaylock/password.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaylock/password.c')
-rw-r--r--swaylock/password.c190
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
14void 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
24static 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
32static 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
43static 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
50static 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
58static 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
67static 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
75static void handle_preverify_timeout(void *data) {
76 struct swaylock_state *state = data;
77 state->verify_password_timer = NULL;
78}
79
80static 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
124void 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}