Passed
Push — master ( 7c19f4...afdc63 )
by EMP
03:45
created

main.js ➔ sendMsg1   A

Complexity

Conditions 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 17
rs 9.8
c 0
b 0
f 0
cc 4
1
"use strict";
2
3
sodium.ready.then(function() {
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
4
5
const ae = new AllEars(function(ok) {
1 ignored issue
show
Bug introduced by
The variable AllEars seems to be never declared. If this is a global, consider adding a /** global: AllEars */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
6
	if (ok) {
7
		document.getElementById("txt_skey").style.background = "#404b41";
8
		document.getElementById("txt_skey").maxLength = "64";
9
	} else {
10
		console.log("Failed to load All-Ears");
11
	}
12
});
13
14
let tab="inbox";
15
let page=0;
16
17
// Helper functions
18
function getCountryName(countryCode) {
19
	const opts = document.getElementById("gatekeeper_country");
20
21
	for (let i = 0; i < opts.length; i++) {
22
		if (opts[i].value === countryCode) {
23
			return opts[i].textContent;
24
		}
25
	}
26
27
	return "Unknown countrycode: " + countryCode;
28
}
29
30
function getCountryFlag(countryCode) {
31
	const regionalIndicator1 = 127462 + countryCode.codePointAt(0) - 65;
32
	const regionalIndicator2 = 127462 + countryCode.codePointAt(1) - 65;
33
	return "&#" + regionalIndicator1 + ";&#" + regionalIndicator2 + ";";
34
}
35
36
function displayMsg(isInt, num) {
37
	document.getElementById("midright").scroll(0, 0);
38
39
	const ts = isInt? ae.GetIntMsgTime(num) : ae.GetExtMsgTime(num);
40
41
	document.getElementById("btn_reply").disabled = false;
42
	document.getElementById("btn_reply").onclick = function() {
43
		document.getElementById("write_recv").value = isInt ? ae.GetIntMsgFrom(num) : ae.GetExtMsgFrom(num);
44
		document.getElementById("write_subj").value = "Re: " + (isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num));
45
		document.getElementById("btn_write").click();
46
		document.getElementById("div_write_1").hidden = false;
47
		document.getElementById("div_write_2").hidden = true;
48
		document.getElementById("write_body").focus();
49
		for (const opt of document.getElementById("write_from").options) {
50
			if (opt.value === (isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num))) {
51
				opt.selected = true;
52
			}
53
		}
54
	};
55
56
	document.getElementById("msg").hidden = false;
57
	document.getElementById("msg").getElementsByTagName("h1")[0].textContent = isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num);
58
	document.getElementById("msg").getElementsByTagName("pre")[0].textContent = isInt ? ae.GetIntMsgBody(num) : ae.GetExtMsgBody(num);
59
60
	document.getElementById("readmsg_to").textContent = isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num);
61
	document.getElementById("readmsg_date").textContent = new Date(ts * 1000).toISOString().slice(0, 19).replace("T", " ");
62
63
	if (!isInt) {
64
		const cc = ae.GetExtMsgCountry(num);
65
66
		document.getElementById("readmsg_greet").textContent = ae.GetExtMsgGreet(num);
67
		document.getElementById("readmsg_ip").textContent = ae.GetExtMsgIp(num);
68
		document.getElementById("readmsg_tls").textContent = ae.GetExtMsgTLS(num);
69
		document.getElementById("readmsg_country").innerHTML = getCountryFlag(cc) + " " + getCountryName(cc);
70
		document.getElementById("readmsg_envfrom").textContent = ae.GetExtMsgFrom(num);
71
72
		let flagText = "";
73
		if (!ae.GetExtMsgFlagPExt(num)) flagText += "<abbr title=\"The sender did not use the Extended (ESMTP) protocol\">SMTP</abbr> ";
74
		if (!ae.GetExtMsgFlagQuit(num)) flagText += "<abbr title=\"The sender did not issue the required QUIT command\">QUIT</abbr> ";
75
		if (ae.GetExtMsgFlagRare(num)) flagText += "<abbr title=\"The sender issued unusual command(s)\">RARE</abbr> ";
76
		if (ae.GetExtMsgFlagFail(num)) flagText += "<abbr title=\"The sender issued invalid command(s)\">FAIL</abbr> ";
77
		if (ae.GetExtMsgFlagPErr(num)) flagText += "<abbr title=\"The sender violated the protocol\">PROT</abbr> ";
78
		document.getElementById("readmsg_flags").innerHTML = flagText.trim();
79
	} else {
80
		document.getElementById("readmsg_from").textContent = ae.GetIntMsgFrom(num);
81
	}
82
}
83
84
// Interface
85
function addMsg(isInt, i) {
86
	const inbox = document.getElementById("tbl_inbox");
87
	const sent = document.getElementById("tbl_sent");
88
89
	const isSent = isInt? ae.GetIntMsgIsSent(i) : false;
90
	const table = isSent ? sent : inbox;
91
92
	const row = table.insertRow(-1);
93
	const cellTime = row.insertCell(-1);
94
	const cellSubj = row.insertCell(-1);
95
	const cellSnd1 = row.insertCell(-1);
96
	const cellSnd2 = row.insertCell(-1);
97
98
	const ts = isInt? ae.GetIntMsgTime(i) : ae.GetExtMsgTime(i);
99
	cellTime.setAttribute("data-ts", ts);
100
	cellTime.textContent = new Date(ts * 1000).toISOString().slice(0, 16).replace("T", " ");
101
102
	cellSubj.textContent = isInt? ae.GetIntMsgTitle(i) : ae.GetExtMsgTitle(i);
103
104
	if (isInt) {
105
		cellSnd1.textContent = ae.GetIntMsgFrom(i);
106
		cellSnd1.className = (ae.GetIntMsgFrom(i).length === 24) ? "mono" : "";
107
	} else {
108
		const from1 = ae.GetExtMsgFrom(i);
109
		const from2 = from1.substring(from1.indexOf("@") + 1);
110
		const cc = ae.GetExtMsgCountry(i);
111
112
		cellSnd1.textContent = from1.substring(0, from1.indexOf("@"));
113
		cellSnd2.innerHTML = "<abbr title=\"" + getCountryName(cc) + "\">" + getCountryFlag(cc) + "</abbr>";
114
115
		const fromText = document.createElement("span");
116
		fromText.textContent = " " + from2;
117
		cellSnd2.appendChild(fromText);
118
	}
119
120
//	divDel.innerHTML = "<input class=\"delMsg\" type=\"checkbox\" data-id=\"" + ae.GetIntMsgIdHex(i) + "\">";
121
122
	row.onclick = function() {
123
		displayMsg(isInt, i);
124
	};
125
/*
126
	cellDel.children[0].onchange = function() {
127
		if (!divDel.children[0].checked) {
128
			const checkboxes = elmt.getElementsByTagName("input");
129
			let checked = false;
130
131
			for (let j = 0; j < checkboxes.length; j++) {
132
				if (checkboxes[j].checked) {
133
					checked = true;
134
					break;
135
				}
136
			}
137
138
			if (!checked) {
139
				document.getElementById(isSent ? "btn_sentdel" : "btn_msgdel").hidden = true;
140
				return;
141
			}
142
		}
143
144
		document.getElementById(isSent? "btn_sentdel" : "btn_msgdel").hidden = false;
145
	};
146
*/
147
}
148
149
function addMessages() {
150
	const maxExt = ae.GetExtMsgCount();
151
	const maxInt = ae.GetIntMsgCount();
152
153
	let numExt = 0;
154
	let numInt = 0;
155
156
	for (let i = 0; i < (page * 20) + 20; i++) {
157
		const tsInt = (numInt < maxInt) ? ae.GetIntMsgTime(numInt) : 0;
158
		const tsExt = (numExt < maxExt) ? ae.GetExtMsgTime(numExt) : 0;
159
		if (tsInt === 0 && tsExt === 0) break;
160
161
		if (tsInt !== 0 && (tsExt === 0 || tsInt > tsExt)) {
162
			if (i < (page * 20)) {
163
				numInt++;
164
				continue;
165
			}
166
167
			addMsg(true, numInt);
168
			numInt++;
169
		} else if (tsExt !== 0) {
170
			if (i < (page * 20)) {
171
				numExt++;
172
				continue;
173
			}
174
175
			addMsg(false, numExt);
176
			numExt++;
177
		}
178
	}
179
}
180
181
function clearMessages() {
182
	document.getElementById("tbl_inbox").innerHTML = "";
183
//	document.getElementById("tbl_sentm").innerHTML = "";
184
//	document.getElementById("tbl_notes").innerHTML = "";
185
//	document.getElementById("tbl_files").innerHTML = "";
186
}
187
188
function updateAddressCounts() {
189
	document.getElementById("limit_normal").textContent = (ae.GetAddressCountNormal() + "/" + ae.GetAddressLimitNormal(ae.GetUserLevel())).padStart(ae.GetAddressLimitNormal(ae.GetUserLevel()) > 9 ? 5 : 1);
190
	document.getElementById("limit_shield").textContent = (ae.GetAddressCountShield() + "/" + ae.GetAddressLimitShield(ae.GetUserLevel())).padStart(ae.GetAddressLimitShield(ae.GetUserLevel()) > 9 ? 5 : 1);
191
	document.getElementById("limit_total").textContent = ((ae.GetAddressCountNormal() + ae.GetAddressCountShield()) + "/" + ae.GetAddrPerUser()).padStart(5);
192
}
193
194
function reloadInterface() {
195
	document.getElementById("div_begin").hidden = true;
196
	document.getElementById("div_main").style.display = "grid";
197
198
	// Contacts
199
	for (let i = 0; i < ae.GetContactCount(); i++) {
200
		addContact(
201
			ae.GetContactMail(i),
202
			ae.GetContactName(i),
203
			ae.GetContactNote(i)
204
		);
205
	}
206
207
	// Addresses
208
	for (let i = 0; i < ae.GetAddressCount(); i++) {
209
		addAddress(i);
210
	}
211
212
	document.getElementById("table_addrs").getElementsByTagName("caption")[0].textContent = "Level " + ae.GetUserLevel() + " User";
213
	updateAddressCounts();
214
}
215
216 View Code Duplication
function deleteAddress(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
217
	let btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
218
	for (let i = 0; i < btns.length; i++) btns[i].disabled = true;
219
220
	let addressToDelete = -1;
221
222
	for (let i = 0; i < ae.GetAddressCount(); i++) {
223
		if (addr === ae.GetAddress(i)) {
224
			addressToDelete = i;
225
			break;
226
		}
227
	}
228
229
	if (addressToDelete === -1) return;
230
231
	ae.Address_Delete(addressToDelete, function(success) {
232
		if (success) {
233
			document.getElementById("tbl_addrs").deleteRow(addressToDelete);
234
			document.getElementById("write_from").remove(addressToDelete);
235
			updateAddressCounts();
236
237
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) document.getElementById("btn_address_create_normal").disabled = false;
238
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) document.getElementById("btn_address_create_shield").disabled = false;
239
240
			ae.Private_Update(function(success2) {
241
				if (!success2) console.log("Failed to update the Private field");
242
243
				btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
244
				for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
245
			});
246
		} else {
247
			console.log("Failed to delete address");
248
249
			btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
250
			for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
251
		}
252
	});
253
}
254
255 View Code Duplication
function shieldMix(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
256
	let newAddr = "";
257
258
	for (let i = 0; i < 24; i++) {
259
		switch (addr.charAt(i)) {
260
			case '1':
261
				newAddr += "1iIlL".charAt(Math.floor(Math.random() * 5));
262
				break;
263
			case '0':
264
				newAddr += "0oO".charAt(Math.floor(Math.random() * 3));
265
				break;
266
			case 'w':
267
				newAddr += "VvWw".charAt(Math.floor(Math.random() * 4));
268
				break;
269
			default:
270
				newAddr += (Math.random() > 0.5) ? addr.charAt(i) : addr.charAt(i).toUpperCase();
271
		}
272
	}
273
274
	return newAddr;
275
}
276
277
function addAddress(num) {
278
	const addrTable = document.getElementById("tbl_addrs");
279
	const row = addrTable.insertRow(-1);
280
	const cellAddr = row.insertCell(-1);
281
	const cellChk1 = row.insertCell(-1);
282
	const cellChk2 = row.insertCell(-1);
283
	const cellChk3 = row.insertCell(-1);
284
	const cellBtnD = row.insertCell(-1);
285
286
	cellAddr.textContent = ae.GetAddress(num);
287
	cellAddr.onclick = function() {
288
		if (cellAddr.textContent.length === 24)
289
			navigator.clipboard.writeText(shieldMix(cellAddr.textContent) + "@" + ae.GetDomain());
1 ignored issue
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
290
		else
291
			navigator.clipboard.writeText(cellAddr.textContent + "@" + ae.GetDomain());
292
	};
293
294
	cellChk1.innerHTML = ae.GetAddressAccExt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
295
	cellChk2.innerHTML = ae.GetAddressAccInt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
296
	cellChk3.innerHTML = ae.GetAddressUse_Gk(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
297
298
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
299
	cellBtnD.onclick = function() {deleteAddress(cellAddr.textContent);};
300
301
	const opt = document.createElement("option");
302
	opt.value = cellAddr.textContent;
303
	opt.textContent = cellAddr.textContent + "@" + ae.GetDomain();
304
	document.getElementById("write_from").appendChild(opt);
305
}
306
307
document.getElementById("btn_updt").onclick = function() {
308
	const btn = this;
309
	btn.disabled = true;
310
	btn.blur();
311
312
	if (tab === "inbox") {
313
		ae.Message_Browse(0, function(successBrowse) {
314
			if (successBrowse) {
315
				clearMessages();
316
				addMessages();
317
				btn.disabled = false;
318
			} else {
319
				console.log("Failed to refresh");
320
				btn.disabled = false;
321
			}
322
		});
323
	}
324
};
325
326
function addContact(mail, name, note) {
327
	const tbl = document.getElementById("tbl_ctact");
328
	const row = tbl.insertRow(-1);
329
	const cellMail = row.insertCell(-1);
330
	const cellName = row.insertCell(-1);
331
	const cellNote = row.insertCell(-1);
332
	const cellBtnD = row.insertCell(-1);
333
334
	cellMail.textContent = mail;
335
	cellName.textContent = name;
336
	cellNote.textContent = note;
337
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
338
339
	cellMail.contentEditable = true;
340
	cellName.contentEditable = true;
341
	cellNote.contentEditable = true;
342
343
	cellBtnD.onclick = function() {row.remove();};
344
}
345
346
document.getElementById("btn_newcontact").onclick = function() {
347
	addContact("", "", "");
348
}
349
350
function sendMsg1() {
351
	ae.Address_Lookup(document.getElementById("write_recv").value, function(pk) {
352
		if (pk) {
353
			document.getElementById("div_write_1").hidden = true;
354
			document.getElementById("div_write_2").hidden = false;
355
356
			document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.GetDomain();
357
			document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
358
			document.getElementById("write2_pkey").textContent = sodium.to_hex(pk);
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
359
360
			document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
361
			document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
362
		} else {
363
			console.log("Failed lookup");
364
		}
365
	});
366
}
367
368
// Tabs
369
function setupButtons() {
370
	switch(tab) {
371
		case "inbox":
372
		case "snbox":
373
			document.getElementById("btn_dele").disabled = false;
374
			document.getElementById("btn_left").disabled = false; // depends
375
			document.getElementById("btn_cent").disabled = true;
376
			document.getElementById("btn_rght").disabled = false;
377
			document.getElementById("btn_updt").disabled = false;
378
			break;
379
		case "write":
380
			document.getElementById("btn_dele").disabled = false; // depends
381
			document.getElementById("btn_left").disabled = false; // depends
382
			document.getElementById("btn_cent").disabled = true;
383
			document.getElementById("btn_rght").disabled = false;
384
			document.getElementById("btn_updt").disabled = true;
385
386
			document.getElementById("btn_left").onclick = function() {
387
				document.getElementById("div_write_1").hidden = false;
388
				document.getElementById("div_write_2").hidden = true;
389
			}
390
391
			document.getElementById("btn_rght").onclick = sendMsg1;
392
			break;
393
		case "notes":
394
			document.getElementById("btn_dele").disabled = true;
395
			document.getElementById("btn_left").disabled = false; // depends
396
			document.getElementById("btn_cent").disabled = true;
397
			document.getElementById("btn_rght").disabled = false; // depends
398
			document.getElementById("btn_updt").disabled = true; // depends
399
			break;
400
		case "prefs":
401
			document.getElementById("btn_dele").disabled = true;
402
			document.getElementById("btn_left").disabled = false; // depends
403
			document.getElementById("btn_cent").disabled = true;
404
			document.getElementById("btn_rght").disabled = false; // depends
405
			document.getElementById("btn_updt").disabled = true; // depends
406
			break;
407
	}
408
}
409
410
for (const btn1 of document.getElementById("main1").getElementsByClassName("top")[0].getElementsByTagName("button")) {
411
	btn1.onclick = function() {
412
		for (const btn2 of document.getElementById("main1").getElementsByClassName("top")[0].getElementsByTagName("button")) {
413
			const isMatch = (btn1 === btn2);
414
			btn2.disabled = isMatch;
415
			document.getElementById("div_" + btn2.id.slice(4)).hidden = !isMatch;
416
417
			if (isMatch) {
418
				tab = btn2.id.slice(4);
419
				setupButtons();
420
			}
421
		};
422
	};
423
};
424
425
function addressCreate(addr) {
426
	const btnN = document.getElementById("btn_address_create_normal");
427
	const btnS = document.getElementById("btn_address_create_shield");
428
	btnN.disabled = true;
429
	btnS.disabled = true;
430
431
	ae.Address_Create(addr, function(success1) {
432
		if (success1) {
433
			ae.Private_Update(function(success2) {
434
				addAddress(ae.GetAddressCount() - 1);
435
				if (addr !== "SHIELD") document.getElementById("txt_address_create_normal").value = "";
436
				updateAddressCounts();
437
438
				if (!success2) console.log("Failed to update the Private field");
439
440
				if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
441
				if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
442
			});
443
		} else {
444
			console.log("Failed to add address");
445
446
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
447
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
448
		}
449
	});
450
}
451
452
document.getElementById("btn_address_create_normal").onclick = function() {
453
	if (ae.GetAddressCountNormal() >= ae.GetAddressLimitNormal(ae.GetUserLevel())) return;
454
455
	const txtNewAddr = document.getElementById("txt_address_create_normal");
456
	if (!txtNewAddr.reportValidity()) return;
457
458
	addressCreate(txtNewAddr.value);
459
}
460
461
document.getElementById("btn_address_create_shield").onclick = function() {
462
	if (ae.GetAddressCountShield() >= ae.GetAddressLimitShield(ae.GetUserLevel())) return;
463
464
	addressCreate("SHIELD");
465
};
466
467
document.getElementById("txt_skey").onkeyup = function(event) {
468
	if (event.key === "Enter") {
469
		event.preventDefault();
470
		document.getElementById("btn_enter").click();
471
	}
472
};
473
474
document.getElementById("btn_enter").onclick = function() {
475
	const txtSkey = document.getElementById("txt_skey");
476
	if (!txtSkey.reportValidity()) return;
477
478
	const btn = this;
479
	btn.disabled = true;
480
	document.getElementById("txt_skey").style.background = "#111";
481
482
	ae.SetKeys(txtSkey.value, function(successSetKeys) {
483
		if (successSetKeys) {
484
			ae.Account_Browse(0, function(successBrowse) {
485
				if (successBrowse) {
486
					txtSkey.value = "";
487
					reloadInterface();
488
					document.getElementById("btn_updt").click();
489
				} else {
490
					console.log("Failed to enter");
491
					btn.disabled = false;
492
					document.getElementById("txt_skey").style.background = "#404b41";
493
					txtSkey.focus();
494
				}
495
			});
496
		} else {
497
			console.log("Invalid format for key");
498
			btn.disabled = false;
499
			document.getElementById("txt_skey").style.background = "#404b41";
500
			txtSkey.focus();
501
		}
502
	});
503
};
504
505
});
506