1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
|
using Gee;
using Gtk;
using Pango;
using Dino.Entities;
using Xmpp;
namespace Dino.Ui.ManageAccounts {
[GtkTemplate (ui = "/im/dino/Dino/preferences_window/add_account_dialog.ui")]
public class AddAccountDialog : Adw.Window {
public signal void added(Account account);
enum Page {
SIGN_IN,
SIGN_IN_TLS_ERROR,
CREATE_ACCOUNT_SELECT_SERVER,
CREATE_ACCOUNT_REGISTER_FORM,
SUCCESS
}
[GtkChild] private unowned Stack stack;
[GtkChild] private unowned Revealer notification_revealer;
[GtkChild] private unowned Label notification_label;
// Sign in - JID
[GtkChild] private unowned Box sign_in_box;
[GtkChild] private unowned Label sign_in_error_label;
[GtkChild] private unowned Adw.EntryRow jid_entry;
[GtkChild] private unowned Adw.PreferencesGroup password_group;
[GtkChild] private unowned Adw.PasswordEntryRow password_entry;
[GtkChild] private unowned Button sign_in_continue_button;
[GtkChild] private unowned Spinner sign_in_continue_spinner;
[GtkChild] private unowned Button sign_in_serverlist_button;
// Sign in - TLS error
[GtkChild] private unowned Box sign_in_tls_box;
[GtkChild] private unowned Label sign_in_tls_label;
[GtkChild] private unowned Button sign_in_tls_back_button;
// Select Server
[GtkChild] private unowned Box create_account_box;
[GtkChild] private unowned Button login_button;
[GtkChild] private unowned Spinner select_server_continue_spinner;
[GtkChild] private unowned Button select_server_continue;
[GtkChild] private unowned Label register_form_continue_label;
[GtkChild] private unowned ListBox server_list_box;
[GtkChild] private unowned Entry server_entry;
// Register Form
[GtkChild] private unowned Button back_button;
[GtkChild] private unowned Box register_box;
[GtkChild] private unowned Box form_box;
[GtkChild] private unowned Spinner register_form_continue_spinner;
[GtkChild] private unowned Button register_form_continue;
// Success
[GtkChild] private unowned Box success_box;
[GtkChild] private unowned Label success_description;
[GtkChild] private unowned Button success_continue_button;
private static string[] server_list = new string[]{
"5222.de",
"jabber.fr",
"movim.eu",
"yax.im"
};
private StreamInteractor stream_interactor;
private Database db;
private HashMap<ListBoxRow, string> list_box_jids = new HashMap<ListBoxRow, string>();
private Jid? server_jid = null;
private Jid? login_jid = null;
private Xep.InBandRegistration.Form? form = null;
public AddAccountDialog(StreamInteractor stream_interactor, Database db) {
this.stream_interactor = stream_interactor;
this.db = db;
this.title = _("Add Account");
// Sign in - Jid
jid_entry.changed.connect(on_jid_entry_changed);
sign_in_continue_button.clicked.connect(on_sign_in_continue_button_clicked);
sign_in_serverlist_button.clicked.connect(show_select_server);
// Sign in - TLS error
sign_in_tls_back_button.clicked.connect(() => show_sign_in() );
// Select Server
server_entry.changed.connect(() => {
try {
Jid jid = new Jid(server_entry.text);
select_server_continue.sensitive = jid != null && jid.localpart == null && jid.resourcepart == null;
} catch (InvalidJidError e) {
select_server_continue.sensitive = false;
}
});
select_server_continue.clicked.connect(on_select_server_continue);
login_button.clicked.connect(() => show_sign_in() );
foreach (string server in server_list) {
ListBoxRow list_box_row = new ListBoxRow();
list_box_row.set_child(new Label(server) { xalign=0, margin_start=7, margin_end=7 });
list_box_jids[list_box_row] = server;
server_list_box.append(list_box_row);
}
// Register Form
register_form_continue.clicked.connect(on_register_form_continue_clicked);
back_button.clicked.connect(() => {
show_select_server();
back_button.visible = false;
});
// Success
success_continue_button.clicked.connect(() => close());
show_sign_in();
}
private void show_sign_in(bool keep_jid = false) {
switch_stack_page(Page.SIGN_IN);
this.title = _("Sign in");
set_default_widget(sign_in_continue_button);
sign_in_error_label.visible = false;
sign_in_continue_spinner.visible = false;
if (!keep_jid) {
jid_entry.text = "";
jid_entry.grab_focus();
}
password_entry.text = "";
password_group.visible = false;
sign_in_serverlist_button.visible = true;
}
private void show_tls_error(string domain, TlsCertificateFlags error_flags) {
switch_stack_page(Page.SIGN_IN_TLS_ERROR);
string error_desc = _("The server could not prove that it is %s.").printf("<b>" + domain + "</b>");
if (TlsCertificateFlags.UNKNOWN_CA in error_flags) {
error_desc += " " + _("Its security certificate is not trusted by your operating system.");
} else if (TlsCertificateFlags.BAD_IDENTITY in error_flags) {
error_desc += " " + _("Its security certificate is issued to another domain.");
} else if (TlsCertificateFlags.NOT_ACTIVATED in error_flags) {
error_desc += " " + _("Its security certificate will only become valid in the future.");
} else if (TlsCertificateFlags.EXPIRED in error_flags) {
error_desc += " " + _("Its security certificate is expired.");
}
sign_in_tls_label.label = error_desc;
}
private void show_select_server() {
switch_stack_page(Page.CREATE_ACCOUNT_SELECT_SERVER);
this.title = _("Create account");
server_entry.text = "";
server_entry.grab_focus();
set_default_widget(select_server_continue);
server_list_box.row_activated.disconnect(on_server_list_row_activated);
server_list_box.unselect_all();
server_list_box.row_activated.connect(on_server_list_row_activated);
}
private void show_register_form() {
switch_stack_page(Page.CREATE_ACCOUNT_REGISTER_FORM);
set_default_widget(register_form_continue);
}
private void show_success(Account account) {
switch_stack_page(Page.SUCCESS);
success_description.label = _("You can now use the account %s.").printf("<b>" + Markup.escape_text(account.bare_jid.to_string()) + "</b>");
set_default_widget(success_continue_button);
}
private void on_jid_entry_changed() {
try {
login_jid = new Jid(jid_entry.text);
if (login_jid.localpart != null && login_jid.resourcepart == null) {
sign_in_continue_button.sensitive = true;
} else {
sign_in_continue_button.sensitive = false;
}
} catch (InvalidJidError e) {
sign_in_continue_button.sensitive = false;
}
}
private async void on_sign_in_continue_button_clicked() {
try {
login_jid = new Jid(jid_entry.text);
sign_in_tls_label.label = "";
sign_in_error_label.visible = false;
sign_in_continue_button.sensitive = false;
sign_in_continue_spinner.visible = true;
ulong jid_entry_changed_handler_id = -1;
jid_entry_changed_handler_id = jid_entry.changed.connect(() => {
jid_entry.disconnect(jid_entry_changed_handler_id);
show_sign_in(true);
return;
});
if (password_group.visible) {
// JID + Psw fields were visible: Try to log in
string password = password_entry.text;
Account account = new Account(login_jid, null, password, null);
ConnectionManager.ConnectionError.Source? error = yield stream_interactor.get_module(Register.IDENTITY).add_check_account(account);
sign_in_continue_spinner.visible = false;
sign_in_continue_button.sensitive = true;
if (error != null) {
sign_in_error_label.visible = true;
switch (error) {
case ConnectionManager.ConnectionError.Source.SASL:
sign_in_error_label.label = _("Wrong username or password");
break;
default:
sign_in_error_label.label = _("Something went wrong");
break;
}
} else {
add_activate_account(account);
show_success(account);
}
} else {
// Only JID field was visible: Check if server exists
Register.ServerAvailabilityReturn server_status = yield Register.check_server_availability(login_jid);
sign_in_continue_spinner.visible = false;
sign_in_continue_button.sensitive = true;
if (server_status.available) {
password_group.visible = true;
password_entry.grab_focus();
sign_in_serverlist_button.visible = false;
} else {
if (server_status.error_flags != null) {
show_tls_error(login_jid.domainpart, server_status.error_flags);
} else {
sign_in_error_label.visible = true;
sign_in_error_label.label = _("Could not connect to %s").printf(login_jid.domainpart);
}
}
}
} catch (InvalidJidError e) {
warning("Invalid address from interface allowed login: %s", e.message);
sign_in_error_label.visible = true;
sign_in_error_label.label = _("Invalid address");
}
}
private void on_select_server_continue() {
try {
server_jid = new Jid(server_entry.text);
request_show_register_form.begin(server_jid);
} catch (InvalidJidError e) {
warning("Invalid address from interface allowed server: %s", e.message);
display_notification(_("Invalid address"));
}
}
private void on_server_list_row_activated(ListBox box, ListBoxRow row) {
try {
server_jid = new Jid(list_box_jids[row]);
request_show_register_form.begin(server_jid);
} catch (InvalidJidError e) {
warning("Invalid address from selected server: %s", e.message);
display_notification(_("Invalid address"));
}
}
private async void request_show_register_form(Jid server_jid) {
select_server_continue_spinner.visible = true;
Register.RegistrationFormReturn form_return = yield Register.get_registration_form(server_jid);
if (select_server_continue_spinner == null) {
return;
}
select_server_continue_spinner.visible = false;
if (form_return.form != null) {
form = form_return.form;
set_register_form(server_jid, form);
show_register_form();
} else if (form_return.error_flags != null) {
show_tls_error(server_jid.domainpart, form_return.error_flags);
} else {
display_notification(_("No response from server"));
}
}
private void set_register_form(Jid server, Xep.InBandRegistration.Form form) {
Widget widget = form_box.get_first_child();
while (widget != null) {
form_box.remove(widget);
widget = form_box.get_first_child();
}
this.title = _("Register on %s").printf(server.to_string());
if (form.oob != null) {
form_box.append(new Label(_("The server requires to sign up through a website")));
form_box.append(new Label(@"<a href=\"$(form.oob)\">$(form.oob)</a>") { use_markup=true });
register_form_continue_label.label = _("Open website");
register_form_continue.visible = true;
register_form_continue.grab_focus();
} else if (form.fields.size > 0) {
if (form.instructions != null && form.instructions != "") {
string markup_instructions = Util.parse_add_markup(form.instructions, null, true, false);
form_box.append(new Label(markup_instructions) { use_markup=true, xalign=0, margin_top=7,
wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR });
}
var form_preference_group = Util.rows_to_preference_group(Util.get_data_form_view_model(form), "");
form_box.append(form_preference_group);
register_form_continue.visible = true;
register_form_continue_label.label = _("Register");
} else {
form_box.append(new Label(_("Check %s for information on how to sign up").printf(@"<a href=\"http://$(server)\">$(server)</a>")) { use_markup=true });
register_form_continue.visible = false;
}
}
private async void on_register_form_continue_clicked() {
notification_revealer.set_reveal_child(false);
// Button is opening a registration website
if (form.oob != null) {
try {
AppInfo.launch_default_for_uri(form.oob, null);
} catch (Error e) { }
show_sign_in();
return;
}
register_form_continue_spinner.visible = true;
string? error = yield Register.submit_form(server_jid, form);
if (register_form_continue_spinner == null) {
return;
}
register_form_continue_spinner.visible = false;
if (error == null) {
string? username = null, password = null;
foreach (Xep.DataForms.DataForm.Field field in form.fields) {
switch (field.var) {
case "username": username = field.get_value_string(); break;
case "password": password = field.get_value_string(); break;
}
}
try {
Account account = new Account(new Jid.components(username, server_jid.domainpart, null), null, password, null);
add_activate_account(account);
show_success(account);
} catch (InvalidJidError e) {
warning("Invalid address from components of registration: %s", e.message);
display_notification(_("Invalid address"));
}
} else {
display_notification(error);
}
}
private void display_notification(string text) {
notification_label.label = text;
notification_revealer.set_reveal_child(true);
Timeout.add_seconds(5, () => {
notification_revealer.set_reveal_child(false);
return false;
});
}
private void add_activate_account(Account account) {
account.enabled = true;
account.persist(db);
stream_interactor.connect_account(account);
added(account);
}
private void switch_stack_page(Page page) {
sign_in_box.visible = page == SIGN_IN;
sign_in_tls_box.visible = page == SIGN_IN_TLS_ERROR;
create_account_box.visible = page == CREATE_ACCOUNT_SELECT_SERVER;
register_box.visible = page == CREATE_ACCOUNT_REGISTER_FORM;
success_box.visible = page == SUCCESS;
stack.visible_child_name = get_visible_stack_child_name(page);
back_button.visible = page == CREATE_ACCOUNT_REGISTER_FORM;
}
private string get_visible_stack_child_name(Page page) {
switch (page) {
case SIGN_IN: return "login_jid";
case SIGN_IN_TLS_ERROR: return "tls_error";
case CREATE_ACCOUNT_SELECT_SERVER: return "server";
case CREATE_ACCOUNT_REGISTER_FORM: return "form";
case SUCCESS: return "success";
default: assert_not_reached();
}
}
}
}
|