| Total Complexity | 191 |
| Complexity/F | 2.33 |
| Lines of Code | 877 |
| Function Count | 82 |
| Duplicated Lines | 40 |
| Ratio | 4.56 % |
| Changes | 0 | ||
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like original/main.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | "use strict"; |
||
| 2 | |||
| 3 | sodium.ready.then(function() { |
||
| 4 | |||
| 5 | const ae = new AllEars(function(ok) { |
||
| 6 | if (ok) { |
||
| 7 | document.getElementById("btn_enter").disabled = false; |
||
| 8 | } else { |
||
| 9 | console.log("Failed to load All-Ears"); |
||
|
|
|||
| 10 | } |
||
| 11 | }); |
||
| 12 | |||
| 13 | let page=0; |
||
| 14 | |||
| 15 | function navMenu(num) { |
||
| 16 | document.getElementById("div_readmsg").hidden = true; |
||
| 17 | |||
| 18 | const b = document.getElementsByTagName("nav")[0].getElementsByTagName("button"); |
||
| 19 | const d = document.getElementsByClassName("maindiv"); |
||
| 20 | |||
| 21 | for (let i = 0; i < 5; i++) { |
||
| 22 | if (i === num) { |
||
| 23 | b[i].disabled = true; |
||
| 24 | d[i].hidden = false; |
||
| 25 | } else { |
||
| 26 | b[i].disabled = false; |
||
| 27 | d[i].hidden = true; |
||
| 28 | } |
||
| 29 | } |
||
| 30 | } |
||
| 31 | |||
| 32 | function getCountryName(countryCode) { |
||
| 33 | return "Unknown countrycode: " + countryCode; |
||
| 34 | } |
||
| 35 | |||
| 36 | function getCountryFlag(countryCode) { |
||
| 37 | return sodium.to_string(new Uint8Array([ |
||
| 38 | 240, 159, 135, 166 + countryCode.codePointAt(0) - 65, |
||
| 39 | 240, 159, 135, 166 + countryCode.codePointAt(1) - 65 |
||
| 40 | ])); |
||
| 41 | } |
||
| 42 | |||
| 43 | function addMessages() { |
||
| 44 | const maxExt = ae.GetExtMsgCount(); |
||
| 45 | const maxInt = ae.GetIntMsgCount(); |
||
| 46 | |||
| 47 | let numExt = 0; |
||
| 48 | let numInt = 0; |
||
| 49 | |||
| 50 | //TODO handle sent messages separately |
||
| 51 | |||
| 52 | for (let i = 0; i < (page * 20) + 20; i++) { |
||
| 53 | const tsInt = (numInt < maxInt) ? ae.GetIntMsgTime(numInt) : 0; |
||
| 54 | const tsExt = (numExt < maxExt) ? ae.GetExtMsgTime(numExt) : 0; |
||
| 55 | if (tsInt === 0 && tsExt === 0) break; |
||
| 56 | |||
| 57 | if (tsInt !== 0 && (tsExt === 0 || tsInt > tsExt)) { |
||
| 58 | if (i < (page * 20)) { |
||
| 59 | numInt++; |
||
| 60 | continue; |
||
| 61 | } |
||
| 62 | |||
| 63 | addIntMessage(numInt); |
||
| 64 | numInt++; |
||
| 65 | } else if (tsExt !== 0) { |
||
| 66 | if (i < (page * 20)) { |
||
| 67 | numExt++; |
||
| 68 | continue; |
||
| 69 | } |
||
| 70 | |||
| 71 | addExtMessage(numExt); |
||
| 72 | numExt++; |
||
| 73 | } |
||
| 74 | } |
||
| 75 | } |
||
| 76 | |||
| 77 | function addExtMessage(i) { |
||
| 78 | const tbl = document.getElementById("tbd_inbox"); |
||
| 79 | |||
| 80 | const row = tbl.insertRow(-1); |
||
| 81 | const cellTime = row.insertCell(-1); |
||
| 82 | const cellSubj = row.insertCell(-1); |
||
| 83 | const cellFrom1 = row.insertCell(-1); |
||
| 84 | const cellFrom2 = row.insertCell(-1); |
||
| 85 | const cellTo = row.insertCell(-1); |
||
| 86 | const cellDel = row.insertCell(-1); |
||
| 87 | |||
| 88 | const ts = ae.GetExtMsgTime(i); |
||
| 89 | cellTime.setAttribute("data-ts", ts); |
||
| 90 | cellTime.textContent = new Date(ts * 1000).toISOString().slice(0, 16).replace("T", " "); |
||
| 91 | cellTime.className = "mono"; |
||
| 92 | |||
| 93 | cellSubj.textContent = ae.GetExtMsgTitle(i); |
||
| 94 | |||
| 95 | const from = ae.GetExtMsgHdrFrom(i); |
||
| 96 | const from2 = from.substring(from.indexOf("@") + 1); |
||
| 97 | const cc = ae.GetExtMsgCountry(i); |
||
| 98 | |||
| 99 | cellFrom1.textContent = from.substring(0, from.indexOf("@")); |
||
| 100 | |||
| 101 | const flag = document.createElement("abbr"); |
||
| 102 | flag.textContent = getCountryFlag(cc); |
||
| 103 | flag.title = getCountryName(cc); |
||
| 104 | cellFrom2.appendChild(flag); |
||
| 105 | |||
| 106 | const fromText = document.createElement("span"); |
||
| 107 | fromText.textContent = " " + from2; |
||
| 108 | cellFrom2.appendChild(fromText); |
||
| 109 | |||
| 110 | cellTo.textContent = ae.GetExtMsgEnvTo(i); |
||
| 111 | cellTo.className = (ae.GetExtMsgEnvTo(i).length === 16) ? "mono" : ""; |
||
| 112 | |||
| 113 | cellDel.innerHTML = "<input class=\"delMsg\" type=\"checkbox\" data-id=\"" + ae.GetExtMsgIdHex(i) + "\">"; |
||
| 114 | |||
| 115 | cellSubj.onclick = function() { |
||
| 116 | navMenu(-1); |
||
| 117 | document.getElementById("div_readmsg").hidden = false; |
||
| 118 | document.getElementById("readmsg_head").hidden = false; |
||
| 119 | document.getElementById("readmsg_levelinfo").hidden = true; |
||
| 120 | document.getElementById("readmsg_extmsg").hidden = false; |
||
| 121 | document.getElementById("readmsg_greet").textContent = ae.GetExtMsgGreet(i); |
||
| 122 | document.getElementById("readmsg_tls").textContent = ae.GetExtMsgTLS(i); |
||
| 123 | document.getElementById("readmsg_ip").textContent = ae.GetExtMsgIp(i); |
||
| 124 | |||
| 125 | document.getElementById("readmsg_country").textContent = getCountryName(cc) + " " + getCountryFlag(cc); |
||
| 126 | |||
| 127 | let flagText = ""; |
||
| 128 | if (!ae.GetExtMsgFlagPExt(i)) flagText += "<abbr title=\"The sender did not use the Extended (ESMTP) protocol\">SMTP</abbr> "; |
||
| 129 | if (!ae.GetExtMsgFlagQuit(i)) flagText += "<abbr title=\"The sender did not issue the required QUIT command\">QUIT</abbr> "; |
||
| 130 | if (ae.GetExtMsgFlagRare(i)) flagText += "<abbr title=\"The sender issued unusual command(s)\">RARE</abbr> "; |
||
| 131 | if (ae.GetExtMsgFlagFail(i)) flagText += "<abbr title=\"The sender issued invalid command(s)\">FAIL</abbr> "; |
||
| 132 | if (ae.GetExtMsgFlagPErr(i)) flagText += "<abbr title=\"The sender violated the protocol\">PROT</abbr> "; |
||
| 133 | document.getElementById("readmsg_flags").innerHTML = flagText.trim(); |
||
| 134 | |||
| 135 | document.getElementById("readmsg_title").textContent = ae.GetExtMsgTitle(i); |
||
| 136 | document.getElementById("readmsg_from").textContent = ae.GetExtMsgEnvFrom(i); |
||
| 137 | document.getElementById("readmsg_to").textContent = ae.GetExtMsgEnvTo(i); |
||
| 138 | document.getElementById("readmsg_body").innerHTML = ae.GetExtMsgBody(i); |
||
| 139 | document.getElementById("readmsg_headers").textContent = ae.GetExtMsgHeaders(i); |
||
| 140 | |||
| 141 | document.getElementById("readmsg_from").className = ""; |
||
| 142 | document.getElementById("readmsg_to").className = (ae.GetExtMsgEnvTo(i).length === 16) ? "mono" : ""; |
||
| 143 | }; |
||
| 144 | |||
| 145 | View Code Duplication | cellDel.children[0].onchange = function() { |
|
| 146 | if (!cellDel.children[0].checked) { |
||
| 147 | const checkboxes = tbl.getElementsByTagName("input"); |
||
| 148 | let checked = false; |
||
| 149 | |||
| 150 | for (let j = 0; j < checkboxes.length; j++) { |
||
| 151 | if (checkboxes[j].checked) { |
||
| 152 | checked = true; |
||
| 153 | break; |
||
| 154 | } |
||
| 155 | } |
||
| 156 | |||
| 157 | if (!checked) { |
||
| 158 | document.getElementById("btn_msgdel").hidden = true; |
||
| 159 | return; |
||
| 160 | } |
||
| 161 | } |
||
| 162 | |||
| 163 | document.getElementById("btn_msgdel").hidden = false; |
||
| 164 | }; |
||
| 165 | } |
||
| 166 | |||
| 167 | function addIntMessage(i) { |
||
| 168 | const tbl = document.getElementById("tbd_inbox"); |
||
| 169 | |||
| 170 | const row = tbl.insertRow(-1); |
||
| 171 | const cellTime = row.insertCell(-1); |
||
| 172 | const cellSubj = row.insertCell(-1); |
||
| 173 | row.insertCell(-1); // cellFrom1: empty |
||
| 174 | const cellFrom2 = row.insertCell(-1); |
||
| 175 | const cellTo = row.insertCell(-1); |
||
| 176 | const cellDel = row.insertCell(-1); |
||
| 177 | |||
| 178 | const ts = ae.GetIntMsgTime(i); |
||
| 179 | cellTime.setAttribute("data-ts", ts); |
||
| 180 | cellTime.textContent = new Date(ts * 1000).toISOString().slice(0, 16).replace("T", " "); |
||
| 181 | cellTime.className = "mono"; |
||
| 182 | |||
| 183 | cellSubj.textContent = ae.GetIntMsgTitle(i); |
||
| 184 | |||
| 185 | cellFrom2.textContent = ae.GetIntMsgFrom(i); |
||
| 186 | cellTo.textContent = ae.GetIntMsgTo(i); |
||
| 187 | |||
| 188 | cellTo.className = (ae.GetIntMsgTo(i).length === 16) ? "mono" : ""; |
||
| 189 | cellFrom2.className = (ae.GetIntMsgFrom(i).length === 16) ? "mono" : ""; |
||
| 190 | |||
| 191 | cellDel.innerHTML = "<input class=\"delMsg\" type=\"checkbox\" data-id=\"" + ae.GetIntMsgIdHex(i) + "\">"; |
||
| 192 | |||
| 193 | cellSubj.onclick = function() { |
||
| 194 | navMenu(-1); |
||
| 195 | document.getElementById("div_readmsg").hidden = false; |
||
| 196 | document.getElementById("readmsg_head").hidden = false; |
||
| 197 | document.getElementById("readmsg_levelinfo").hidden = false; |
||
| 198 | document.getElementById("readmsg_extmsg").hidden = true; |
||
| 199 | |||
| 200 | document.getElementById("readmsg_title").textContent = ae.GetIntMsgTitle(i); |
||
| 201 | document.getElementById("readmsg_from").textContent = ae.GetIntMsgFrom(i); |
||
| 202 | document.getElementById("readmsg_to").textContent = ae.GetIntMsgTo(i); |
||
| 203 | document.getElementById("readmsg_body").textContent = ae.GetIntMsgBody(i); |
||
| 204 | document.getElementById("readmsg_level").textContent = ae.GetIntMsgLevel(i); |
||
| 205 | |||
| 206 | document.getElementById("readmsg_from").className = (ae.GetIntMsgFrom(i).length === 16) ? "mono" : ""; |
||
| 207 | document.getElementById("readmsg_to").className = (ae.GetIntMsgTo(i).length === 16) ? "mono" : ""; |
||
| 208 | }; |
||
| 209 | |||
| 210 | View Code Duplication | cellDel.children[0].onchange = function() { |
|
| 211 | if (!cellDel.children[0].checked) { |
||
| 212 | const checkboxes = tbl.getElementsByTagName("input"); |
||
| 213 | let checked = false; |
||
| 214 | |||
| 215 | for (let j = 0; j < checkboxes.length; j++) { |
||
| 216 | if (checkboxes[j].checked) { |
||
| 217 | checked = true; |
||
| 218 | break; |
||
| 219 | } |
||
| 220 | } |
||
| 221 | |||
| 222 | if (!checked) { |
||
| 223 | document.getElementById("btn_msgdel").hidden = true; |
||
| 224 | return; |
||
| 225 | } |
||
| 226 | } |
||
| 227 | |||
| 228 | document.getElementById("btn_msgdel").hidden = false; |
||
| 229 | }; |
||
| 230 | } |
||
| 231 | |||
| 232 | function addFile(num) { |
||
| 233 | const table = document.getElementById("tbody_files"); |
||
| 234 | const row = table.insertRow(-1); |
||
| 235 | |||
| 236 | let cell = row.insertCell(-1); |
||
| 237 | cell.textContent = new Date(ae.GetUplMsgTime(num) * 1000).toISOString().slice(0, 10) |
||
| 238 | |||
| 239 | cell = row.insertCell(-1); |
||
| 240 | cell.textContent = ae.GetUplMsgBytes(num) / 1024; |
||
| 241 | |||
| 242 | cell = row.insertCell(-1); |
||
| 243 | cell.textContent = ae.GetUplMsgTitle(num); |
||
| 244 | |||
| 245 | cell = row.insertCell(-1); |
||
| 246 | cell.innerHTML = "<button type=\"button\">D</button>"; |
||
| 247 | cell.children[0].onclick = function() { |
||
| 248 | const a = document.createElement("a"); |
||
| 249 | a.href = URL.createObjectURL(new Blob([ae.GetUplMsgBody(num).buffer])); |
||
| 250 | a.download = ae.GetUplMsgTitle(num); |
||
| 251 | a.click(); |
||
| 252 | |||
| 253 | URL.revokeObjectURL(a.href); |
||
| 254 | a.href = ""; |
||
| 255 | a.download = ""; |
||
| 256 | }; |
||
| 257 | |||
| 258 | cell = row.insertCell(-1); |
||
| 259 | cell.innerHTML = "<button type=\"button\">X</button>"; |
||
| 260 | cell.children[0].onclick = function() { |
||
| 261 | ae.Message_Delete([ae.GetUplMsgIdHex(num)], function(error) { |
||
| 262 | if (error === 0) { |
||
| 263 | tr.remove(); |
||
| 264 | } else { |
||
| 265 | console.log("Failed deleting file"); |
||
| 266 | } |
||
| 267 | }); |
||
| 268 | }; |
||
| 269 | } |
||
| 270 | |||
| 271 | function destroyAccount(upk_hex) { |
||
| 272 | const tbl = document.getElementById("tbody_admin"); |
||
| 273 | |||
| 274 | let rowid = -1; |
||
| 275 | |||
| 276 | for (let i = 0; i < tbl.rows.length; i++) { |
||
| 277 | if (upk_hex === tbl.rows[i].cells[0].textContent) { |
||
| 278 | rowid = i; |
||
| 279 | break; |
||
| 280 | } |
||
| 281 | } |
||
| 282 | |||
| 283 | if (rowid === -1) return; |
||
| 284 | |||
| 285 | ae.Account_Delete(upk_hex, function(success) { |
||
| 286 | if (success) { |
||
| 287 | tbl.deleteRow(rowid); |
||
| 288 | } else { |
||
| 289 | console.log("Failed to destroy account"); |
||
| 290 | } |
||
| 291 | }); |
||
| 292 | } |
||
| 293 | |||
| 294 | function setAccountLevel(upk_hex, level) { |
||
| 295 | const tbl = document.getElementById("tbody_admin"); |
||
| 296 | |||
| 297 | let rowid = -1; |
||
| 298 | |||
| 299 | for (let i = 0; i < tbl.rows.length; i++) { |
||
| 300 | if (tbl.rows[i].cells[0].textContent === upk_hex) { |
||
| 301 | rowid = i; |
||
| 302 | break; |
||
| 303 | } |
||
| 304 | } |
||
| 305 | |||
| 306 | if (rowid === -1) return; |
||
| 307 | |||
| 308 | ae.Account_Update(upk_hex, level, function(success) { |
||
| 309 | if (!success) { |
||
| 310 | console.log("Failed to set account level"); |
||
| 311 | return; |
||
| 312 | } |
||
| 313 | |||
| 314 | tbl.rows[rowid].cells[4].textContent = level; |
||
| 315 | |||
| 316 | if (level === 0) { |
||
| 317 | tbl.rows[rowid].cells[5].children[0].disabled = false; |
||
| 318 | tbl.rows[rowid].cells[6].children[0].disabled = true; |
||
| 319 | } else if (level === ae.GetLevelMax()) { |
||
| 320 | tbl.rows[rowid].cells[5].children[0].disabled = true; |
||
| 321 | tbl.rows[rowid].cells[6].children[0].disabled = false; |
||
| 322 | } else { |
||
| 323 | tbl.rows[rowid].cells[5].children[0].disabled = false; |
||
| 324 | tbl.rows[rowid].cells[6].children[0].disabled = false; |
||
| 325 | } |
||
| 326 | |||
| 327 | const pkHex = ae.Admin_GetUserPkHex(rowid); |
||
| 328 | const currentLevel = ae.Admin_GetUserLevel(rowid); |
||
| 329 | tbl.rows[rowid].cells[5].children[0].onclick = function() {setAccountLevel(pkHex, currentLevel + 1);}; |
||
| 330 | tbl.rows[rowid].cells[6].children[0].onclick = function() {setAccountLevel(pkHex, currentLevel - 1);}; |
||
| 331 | }); |
||
| 332 | } |
||
| 333 | |||
| 334 | function deleteAddress(addr) { |
||
| 335 | let btns = document.getElementById("tbody_opt_addr").getElementsByTagName("button"); |
||
| 336 | for (let i = 0; i < btns.length; i++) btns[i].disabled = true; |
||
| 337 | |||
| 338 | let addressToDelete = -1; |
||
| 339 | |||
| 340 | for (let i = 0; i < ae.GetAddressCount(); i++) { |
||
| 341 | if (addr === ae.GetAddress(i)) { |
||
| 342 | addressToDelete = i; |
||
| 343 | break; |
||
| 344 | } |
||
| 345 | } |
||
| 346 | |||
| 347 | if (addressToDelete === -1) return; |
||
| 348 | |||
| 349 | ae.Address_Delete(addressToDelete, function(error) { |
||
| 350 | if (error !== 0) { |
||
| 351 | console.log("Failed to delete address"); |
||
| 352 | return; |
||
| 353 | } |
||
| 354 | |||
| 355 | document.getElementById("tbody_opt_addr").deleteRow(addressToDelete); |
||
| 356 | document.getElementById("send_from").remove(addressToDelete); |
||
| 357 | |||
| 358 | document.getElementById("addr_use_normal").textContent = ae.GetAddressCountNormal(); |
||
| 359 | document.getElementById("addr_use_shield").textContent = ae.GetAddressCountShield(); |
||
| 360 | |||
| 361 | if (ae.GetAddressCountNormal() < ae.GetLimitNormalA(ae.GetUserLevel())) document.getElementById("btn_newaddress").disabled = false; |
||
| 362 | if (ae.GetAddressCountShield() < ae.GetLimitShieldA(ae.GetUserLevel())) document.getElementById("btn_newshieldaddress").disabled = false; |
||
| 363 | |||
| 364 | ae.Private_Update(function(error2) { |
||
| 365 | if (!error2 !== 0) console.log("Failed to update the Private field"); |
||
| 366 | |||
| 367 | btns = document.getElementById("tbody_opt_addr").getElementsByTagName("button"); |
||
| 368 | for (let i = 0; i < btns.length; i++) btns[i].disabled = false; |
||
| 369 | }); |
||
| 370 | }); |
||
| 371 | } |
||
| 372 | |||
| 373 | function shieldMix(addr) { |
||
| 374 | let newAddr = ""; |
||
| 375 | |||
| 376 | for (let i = 0; i < 16; i++) { |
||
| 377 | switch (addr.charAt(i)) { |
||
| 378 | case '1': |
||
| 379 | newAddr += "1iIlL".charAt(Math.floor(Math.random() * 5)); |
||
| 380 | break; |
||
| 381 | case '0': |
||
| 382 | newAddr += "0oO".charAt(Math.floor(Math.random() * 3)); |
||
| 383 | break; |
||
| 384 | case 'w': |
||
| 385 | newAddr += "VvWw".charAt(Math.floor(Math.random() * 4)); |
||
| 386 | break; |
||
| 387 | default: |
||
| 388 | newAddr += (Math.random() > 0.5) ? addr.charAt(i) : addr.charAt(i).toUpperCase(); |
||
| 389 | } |
||
| 390 | } |
||
| 391 | |||
| 392 | return newAddr; |
||
| 393 | } |
||
| 394 | |||
| 395 | function addAddress(num) { |
||
| 396 | const addrTable = document.getElementById("tbody_opt_addr"); |
||
| 397 | const row = addrTable.insertRow(-1); |
||
| 398 | |||
| 399 | let cell = row.insertCell(-1); |
||
| 400 | cell.textContent = ae.GetAddress(num); |
||
| 401 | if (cell.textContent.length === 16) cell.className = "mono"; |
||
| 402 | cell.onclick = function() { |
||
| 403 | if (cell.textContent.length === 16) |
||
| 404 | navigator.clipboard.writeText(shieldMix(cell.textContent) + "@" + ae.GetDomainEml()); |
||
| 405 | else |
||
| 406 | navigator.clipboard.writeText(cell.textContent + "@" + ae.GetDomainEml()); |
||
| 407 | }; |
||
| 408 | |||
| 409 | cell = row.insertCell(-1); |
||
| 410 | cell.innerHTML = ae.GetAddressAccExt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">"; |
||
| 411 | |||
| 412 | cell = row.insertCell(-1); |
||
| 413 | cell.innerHTML = ae.GetAddressAccInt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">"; |
||
| 414 | |||
| 415 | cell = row.insertCell(-1); |
||
| 416 | cell.innerHTML = "<button type=\"button\">X</button>"; |
||
| 417 | cell.children[0].onclick = function() {deleteAddress(ae.GetAddress(num));}; |
||
| 418 | |||
| 419 | const opt = document.createElement("option"); |
||
| 420 | opt.value = ae.GetAddress(num); |
||
| 421 | opt.textContent = ae.GetAddress(num) + "@" + ae.GetDomainEml(); |
||
| 422 | document.getElementById("send_from").appendChild(opt); |
||
| 423 | } |
||
| 424 | |||
| 425 | function clearMessages() { |
||
| 426 | document.getElementById("tbd_inbox").innerHTML = ""; |
||
| 427 | document.getElementById("tbd_snbox").innerHTML = ""; |
||
| 428 | document.getElementById("tbody_files").innerHTML = ""; |
||
| 429 | } |
||
| 430 | |||
| 431 | function delMsgs(tblName, btnName) { |
||
| 432 | const cbs = document.getElementsByClassName("delMsg"); |
||
| 433 | const ids = []; |
||
| 434 | |||
| 435 | for (let i = 0; i < cbs.length; i++) { |
||
| 436 | if (cbs[i].checked) ids.push(cbs[i].getAttribute("data-id")); |
||
| 437 | } |
||
| 438 | |||
| 439 | if (ids.length > 0) ae.Message_Delete(ids, function(success) { |
||
| 440 | if (success) { |
||
| 441 | clearMessages(); |
||
| 442 | addMessages(); |
||
| 443 | document.getElementById(btnName).hidden = true; |
||
| 444 | } else { |
||
| 445 | console.log("Failed to delete messages"); |
||
| 446 | } |
||
| 447 | }); |
||
| 448 | } |
||
| 449 | |||
| 450 | function deleteContact(email) { |
||
| 451 | const tbl = document.getElementById("tbody_notes_contact"); |
||
| 452 | const rows = tbl.rows; |
||
| 453 | |||
| 454 | for (let i = 0; i < rows.length; i++) { |
||
| 455 | if (email === rows[i].cells[0].textContent) { |
||
| 456 | ae.DeleteContact(i); |
||
| 457 | tbl.deleteRow(i); |
||
| 458 | break; |
||
| 459 | } |
||
| 460 | } |
||
| 461 | |||
| 462 | document.getElementById("btn_savenotes").hidden = false; |
||
| 463 | } |
||
| 464 | |||
| 465 | function addContactToTable(mail, name, note) { |
||
| 466 | const contactTable = document.getElementById("tbody_notes_contact"); |
||
| 467 | const row = contactTable.insertRow(-1); |
||
| 468 | const cellMail = row.insertCell(-1); |
||
| 469 | const cellName = row.insertCell(-1); |
||
| 470 | const cellNote = row.insertCell(-1); |
||
| 471 | const cellBtnD = row.insertCell(-1); |
||
| 472 | |||
| 473 | cellMail.className = "left"; |
||
| 474 | cellName.className = "left"; |
||
| 475 | cellNote.className = "left"; |
||
| 476 | |||
| 477 | cellMail.textContent = mail; |
||
| 478 | cellName.textContent = name; |
||
| 479 | cellNote.textContent = note; |
||
| 480 | cellBtnD.innerHTML = "<button type=\"button\">X</button>"; |
||
| 481 | |||
| 482 | cellBtnD.onclick = function() {deleteContact(mail);}; |
||
| 483 | } |
||
| 484 | |||
| 485 | function addRowAdmin(num) { |
||
| 486 | const table = document.getElementById("tbody_admin"); |
||
| 487 | |||
| 488 | const row = table.insertRow(-1); |
||
| 489 | const cellPk = row.insertCell(-1); |
||
| 490 | const cellMb = row.insertCell(-1); |
||
| 491 | const cellNa = row.insertCell(-1); |
||
| 492 | const cellSa = row.insertCell(-1); |
||
| 493 | const cellLv = row.insertCell(-1); |
||
| 494 | const cellBtnPl = row.insertCell(-1); |
||
| 495 | const cellBtnMn = row.insertCell(-1); |
||
| 496 | const cellBtnDe = row.insertCell(-1); |
||
| 497 | |||
| 498 | cellPk.textContent = ae.Admin_GetUserPkHex(num); |
||
| 499 | cellMb.textContent = ae.Admin_GetUserSpace(num); |
||
| 500 | cellNa.textContent = ae.Admin_GetUserNAddr(num); |
||
| 501 | cellSa.textContent = ae.Admin_GetUserSAddr(num); |
||
| 502 | cellLv.textContent = ae.Admin_GetUserLevel(num); |
||
| 503 | cellBtnPl.innerHTML = "<button type=\"button\">+</button>"; |
||
| 504 | cellBtnMn.innerHTML = "<button type=\"button\">-</button>"; |
||
| 505 | cellBtnDe.innerHTML = "<button type=\"button\">X</button>"; |
||
| 506 | |||
| 507 | cellPk.className = "mono"; |
||
| 508 | if (ae.Admin_GetUserLevel(num) === ae.GetLevelMax()) cellBtnPl.children[0].disabled = true; |
||
| 509 | if (ae.Admin_GetUserLevel(num) === 0) cellBtnMn.children[0].disabled = true; |
||
| 510 | |||
| 511 | const pkHex = ae.Admin_GetUserPkHex(num); |
||
| 512 | const currentLevel = ae.Admin_GetUserLevel(num); |
||
| 513 | cellBtnPl.children[0].onclick = function() {setAccountLevel(pkHex, currentLevel + 1);}; |
||
| 514 | cellBtnMn.children[0].onclick = function() {setAccountLevel(pkHex, currentLevel - 1);}; |
||
| 515 | cellBtnDe.children[0].onclick = function() {destroyAccount(pkHex);}; |
||
| 516 | } |
||
| 517 | |||
| 518 | function addOpt(select, val) { |
||
| 519 | const opt = document.createElement("option"); |
||
| 520 | opt.value = val; |
||
| 521 | opt.textContent = val; |
||
| 522 | select.appendChild(opt); |
||
| 523 | } |
||
| 524 | |||
| 525 | function reloadInterface() { |
||
| 526 | if (!ae.IsUserAdmin()) document.getElementById("btn_toadmin").hidden = true; |
||
| 527 | document.getElementById("div_begin").hidden = true; |
||
| 528 | document.getElementById("div_allears").hidden = false; |
||
| 529 | |||
| 530 | clearMessages(); |
||
| 531 | document.getElementById("tbody_admin").innerHTML = ""; |
||
| 532 | document.getElementById("tbody_files").innerHTML = ""; |
||
| 533 | document.getElementById("tbody_notes_contact").innerHTML = ""; |
||
| 534 | document.getElementById("tbody_opt_addr").innerHTML = ""; |
||
| 535 | |||
| 536 | // Contacts |
||
| 537 | for (let i = 0; i < ae.GetContactCount(); i++) { |
||
| 538 | addContactToTable( |
||
| 539 | ae.GetContactMail(i), |
||
| 540 | ae.GetContactName(i), |
||
| 541 | ae.GetContactNote(i) |
||
| 542 | ); |
||
| 543 | } |
||
| 544 | |||
| 545 | // Addresses |
||
| 546 | for (let i = 0; i < ae.GetAddressCount(); i++) { |
||
| 547 | addAddress(i); |
||
| 548 | } |
||
| 549 | |||
| 550 | document.getElementById("addr_use_normal").textContent = ae.GetAddressCountNormal(); |
||
| 551 | document.getElementById("addr_use_shield").textContent = ae.GetAddressCountShield(); |
||
| 552 | document.getElementById("addr_max_normal").textContent = ae.GetLimitNormalA(ae.GetUserLevel()); |
||
| 553 | document.getElementById("addr_max_shield").textContent = ae.GetLimitShieldA(ae.GetUserLevel()); |
||
| 554 | |||
| 555 | if (ae.GetAddressCountNormal() >= ae.GetLimitNormalA(ae.GetUserLevel())) document.getElementById("btn_newaddress").disabled = true; |
||
| 556 | if (ae.GetAddressCountShield() >= ae.GetLimitShieldA(ae.GetUserLevel())) document.getElementById("btn_newshieldaddress").disabled = true; |
||
| 557 | |||
| 558 | if (ae.IsUserAdmin()) { |
||
| 559 | const tblLimits = document.getElementById("tbl_limits"); |
||
| 560 | for (let i = 0; i < 4; i++) { |
||
| 561 | tblLimits.rows[i].cells[1].children[0].value = ae.GetStorageLimit(i); |
||
| 562 | tblLimits.rows[i].cells[2].children[0].value = ae.GetLimitNormalA(i); |
||
| 563 | tblLimits.rows[i].cells[3].children[0].value = ae.GetLimitShieldA(i); |
||
| 564 | } |
||
| 565 | |||
| 566 | document.getElementById("btn_admin_savelimits").onclick = function() { |
||
| 567 | const storageLimit = []; |
||
| 568 | const addrNrmLimit = []; |
||
| 569 | const addrShdLimit = []; |
||
| 570 | |||
| 571 | for (let i = 0; i < 4; i++) { |
||
| 572 | storageLimit[i] = tblLimits.rows[i].cells[1].children[0].value; |
||
| 573 | addrNrmLimit[i] = tblLimits.rows[i].cells[2].children[0].value; |
||
| 574 | addrShdLimit[i] = tblLimits.rows[i].cells[3].children[0].value; |
||
| 575 | } |
||
| 576 | |||
| 577 | ae.SetLimits(storageLimit, addrNrmLimit, addrShdLimit, function(success) { |
||
| 578 | if (!success) { |
||
| 579 | console.log("Failed to update limits"); |
||
| 580 | } |
||
| 581 | }); |
||
| 582 | }; |
||
| 583 | |||
| 584 | for (let i = 0; i < ae.Admin_GetUserCount(); i++) { |
||
| 585 | addRowAdmin(i); |
||
| 586 | } |
||
| 587 | } |
||
| 588 | } |
||
| 589 | |||
| 590 | document.getElementById("btn_inbox_prev").onclick = function() { |
||
| 591 | if (page > 0) { |
||
| 592 | page--; |
||
| 593 | clearMessages(); |
||
| 594 | addMessages(); |
||
| 595 | this.disabled = (page === 0); |
||
| 596 | } |
||
| 597 | }; |
||
| 598 | |||
| 599 | document.getElementById("btn_inbox_next").onclick = function() { |
||
| 600 | // TODO: Check if page too high |
||
| 601 | // if (page > 0) { |
||
| 602 | page++; |
||
| 603 | clearMessages(); |
||
| 604 | addMessages(); |
||
| 605 | document.getElementById("btn_inbox_prev").disabled = false; |
||
| 606 | // } |
||
| 607 | }; |
||
| 608 | |||
| 609 | document.getElementById("btn_enter").onclick = function() { |
||
| 610 | const txtSkey = document.getElementById("txt_skey"); |
||
| 611 | if (!txtSkey.reportValidity()) return; |
||
| 612 | |||
| 613 | const btn = this; |
||
| 614 | btn.disabled = true; |
||
| 615 | |||
| 616 | ae.SetKeys(txtSkey.value, function(successSetKeys) { |
||
| 617 | if (!successSetKeys) { |
||
| 618 | console.log("Invalid format for key"); |
||
| 619 | btn.disabled = false; |
||
| 620 | return; |
||
| 621 | } |
||
| 622 | |||
| 623 | ae.Message_Browse(false, true, function(statusBrowse) { |
||
| 624 | if (statusBrowse !== 0) { |
||
| 625 | console.log("Failed to enter"); |
||
| 626 | btn.disabled = false; |
||
| 627 | return; |
||
| 628 | } |
||
| 629 | |||
| 630 | txtSkey.value = ""; |
||
| 631 | reloadInterface(); |
||
| 632 | document.getElementById("btn_refresh").click(); |
||
| 633 | }); |
||
| 634 | }); |
||
| 635 | }; |
||
| 636 | |||
| 637 | document.getElementById("btn_refresh").onclick = function() { |
||
| 638 | const btn = this; |
||
| 639 | btn.disabled = true; |
||
| 640 | |||
| 641 | ae.Message_Browse(true, false, function(successBrowse) { |
||
| 642 | if (successBrowse === 0) { |
||
| 643 | clearMessages(); |
||
| 644 | addMessages(); |
||
| 645 | for (let i = ae.GetUplMsgCount() - 1; i >= 0; i--) {addFile(i);} |
||
| 646 | } else { |
||
| 647 | console.log("Failed to refresh"); |
||
| 648 | } |
||
| 649 | |||
| 650 | btn.disabled = false; |
||
| 651 | }); |
||
| 652 | }; |
||
| 653 | |||
| 654 | document.getElementById("btn_contact_add").onclick = function() { |
||
| 655 | const txtMail = document.getElementById("txt_newcontact_mail"); |
||
| 656 | const txtName = document.getElementById("txt_newcontact_name"); |
||
| 657 | const txtNote = document.getElementById("txt_newcontact_note"); |
||
| 658 | |||
| 659 | addContactToTable(txtMail.value, txtName.value, txtNote.value); |
||
| 660 | ae.AddContact(txtMail.value, txtName.value, txtNote.value); |
||
| 661 | |||
| 662 | txtMail.value = ""; |
||
| 663 | txtName.value = ""; |
||
| 664 | txtNote.value = ""; |
||
| 665 | |||
| 666 | document.getElementById("btn_savenotes").hidden = false; |
||
| 667 | }; |
||
| 668 | |||
| 669 | document.getElementById("btn_savenotes").onclick = function() { |
||
| 670 | ae.Private_Update(function(success) { |
||
| 671 | if (success) { |
||
| 672 | document.getElementById("btn_savenotes").hidden = true; |
||
| 673 | } else { |
||
| 674 | console.log("Failed to save note data"); |
||
| 675 | } |
||
| 676 | }); |
||
| 677 | }; |
||
| 678 | |||
| 679 | document.getElementById("btn_msgdel").onclick = function() { |
||
| 680 | delMsgs("tbody_inbox", "btn_msgdel"); |
||
| 681 | }; |
||
| 682 | |||
| 683 | document.getElementById("btn_sentdel").onclick = function() { |
||
| 684 | delMsgs("tbody_sentbox", "btn_sentdel"); |
||
| 685 | }; |
||
| 686 | |||
| 687 | document.getElementById("btn_send").onclick = function() { |
||
| 688 | const btn = this; |
||
| 689 | btn.disabled = true; |
||
| 690 | |||
| 691 | const sfrom = document.getElementById("send_from"); |
||
| 692 | const stitle = document.getElementById("send_title"); |
||
| 693 | const sto = document.getElementById("send_to"); |
||
| 694 | const sbody = document.getElementById("send_body"); |
||
| 695 | |||
| 696 | if (!stitle.reportValidity() || !sto.reportValidity() || !sbody.reportValidity()) return; |
||
| 697 | |||
| 698 | ae.Address_Lookup(sto.value, function(to_pubkey) { |
||
| 699 | if (to_pubkey) { |
||
| 700 | console.log("Lookup ok, trying to send"); |
||
| 701 | |||
| 702 | ae.Message_Create(stitle.value, sbody.value, sfrom.value, sto.value, to_pubkey, function(success) { |
||
| 703 | if (success) { |
||
| 704 | stitle.value = ""; |
||
| 705 | sto.value = ""; |
||
| 706 | sbody.value = ""; |
||
| 707 | } else { |
||
| 708 | console.log("Failed sending message"); |
||
| 709 | } |
||
| 710 | |||
| 711 | btn.disabled = false; |
||
| 712 | }); |
||
| 713 | } else { |
||
| 714 | console.log("Failed looking up address"); |
||
| 715 | btn.disabled = false; |
||
| 716 | } |
||
| 717 | }); |
||
| 718 | }; |
||
| 719 | |||
| 720 | document.getElementById("btn_newaddress").onclick = function() { |
||
| 721 | if (ae.GetAddressCountNormal() >= ae.GetLimitNormalA(ae.GetUserLevel())) return; |
||
| 722 | |||
| 723 | const txtNewAddr = document.getElementById("txt_newaddress"); |
||
| 724 | if (!txtNewAddr.reportValidity()) return; |
||
| 725 | |||
| 726 | const btnN = document.getElementById("btn_newaddress"); |
||
| 727 | const btnS = document.getElementById("btn_newshieldaddress"); |
||
| 728 | btnN.disabled = true; |
||
| 729 | btnS.disabled = true; |
||
| 730 | |||
| 731 | ae.Address_Create(txtNewAddr.value, function(error1) { |
||
| 732 | if (error1 === 0) { |
||
| 733 | ae.Private_Update(function(error2) { |
||
| 734 | document.getElementById("addr_use_normal").textContent = ae.GetAddressCountNormal(); |
||
| 735 | addAddress(ae.GetAddressCount() - 1); |
||
| 736 | txtNewAddr.value = ""; |
||
| 737 | |||
| 738 | if (error2 !== 0) console.log("Failed to update the Private field"); |
||
| 739 | if (ae.GetAddressCountNormal() < ae.GetLimitNormalA(ae.GetUserLevel())) btnN.disabled = false; |
||
| 740 | if (ae.GetAddressCountShield() < ae.GetLimitShieldA(ae.GetUserLevel())) btnS.disabled = false; |
||
| 741 | }); |
||
| 742 | } else { |
||
| 743 | console.log("Failed to add address"); |
||
| 744 | if (ae.GetAddressCountNormal() < ae.GetLimitNormalA(ae.GetUserLevel())) btnN.disabled = false; |
||
| 745 | if (ae.GetAddressCountShield() < ae.GetLimitShieldA(ae.GetUserLevel())) btnS.disabled = false; |
||
| 746 | } |
||
| 747 | }); |
||
| 748 | }; |
||
| 749 | |||
| 750 | document.getElementById("btn_newshieldaddress").onclick = function() { |
||
| 751 | if (ae.GetLimitShieldA() >= ae.GetLimitShieldA(ae.GetUserLevel())) return; |
||
| 752 | |||
| 753 | const btnN = document.getElementById("btn_newaddress"); |
||
| 754 | const btnS = document.getElementById("btn_newshieldaddress"); |
||
| 755 | btnN.disabled = true; |
||
| 756 | btnS.disabled = true; |
||
| 757 | |||
| 758 | ae.Address_Create("SHIELD", function(error1) { |
||
| 759 | if (error1 !== 0) { |
||
| 760 | console.log("Failed to add Shield address"); |
||
| 761 | if (ae.GetAddressCountNormal() < ae.GetLimitNormalA(ae.GetUserLevel())) btnN.disabled = false; |
||
| 762 | if (ae.GetAddressCountShield() < ae.GetLimitShieldA(ae.GetUserLevel())) btnS.disabled = false; |
||
| 763 | return; |
||
| 764 | } |
||
| 765 | |||
| 766 | ae.Private_Update(function(error2) { |
||
| 767 | document.getElementById("addr_use_shield").textContent = ae.GetAddressCountShield(); |
||
| 768 | addAddress(ae.GetAddressCount() - 1); |
||
| 769 | |||
| 770 | if (error2 !== 0) console.log("Failed to update the Private field"); |
||
| 771 | if (ae.GetAddressCountNormal() < ae.GetLimitNormalA(ae.GetUserLevel())) btnN.disabled = false; |
||
| 772 | if (ae.GetAddressCountShield() < ae.GetLimitShieldA(ae.GetUserLevel())) btnS.disabled = false; |
||
| 773 | }); |
||
| 774 | }); |
||
| 775 | }; |
||
| 776 | |||
| 777 | document.getElementById("btn_saveaddrdata").onclick = function() { |
||
| 778 | const tbl = document.getElementById("tbody_opt_addr"); |
||
| 779 | |||
| 780 | for (let i = 0; i < tbl.rows.length; i++) { |
||
| 781 | ae.SetAddressAccExt(i, tbl.rows[i].cells[1].firstChild.checked); |
||
| 782 | ae.SetAddressAccInt(i, tbl.rows[i].cells[2].firstChild.checked); |
||
| 783 | } |
||
| 784 | |||
| 785 | ae.Address_Update(function(success) { |
||
| 786 | if (success) { |
||
| 787 | document.getElementById("btn_saveaddrdata").hidden = true; |
||
| 788 | } else { |
||
| 789 | console.log("Failed to save address data"); |
||
| 790 | } |
||
| 791 | }); |
||
| 792 | }; |
||
| 793 | |||
| 794 | document.getElementById("btn_admin_addaccount").onclick = function() { |
||
| 795 | const txtPkey = document.getElementById("txt_newacc_pkey"); |
||
| 796 | |||
| 797 | if (!txtPkey.reportValidity()) return; |
||
| 798 | |||
| 799 | const btn = document.getElementById("btn_admin_addaccount"); |
||
| 800 | btn.disabled = true; |
||
| 801 | |||
| 802 | ae.Account_Create(txtPkey.value, function(success) { |
||
| 803 | if (success) { |
||
| 804 | addRowAdmin(ae.Admin_GetUserCount() - 1); |
||
| 805 | txtPkey.value = ""; |
||
| 806 | } else { |
||
| 807 | console.log("Failed to add account"); |
||
| 808 | } |
||
| 809 | }); |
||
| 810 | |||
| 811 | btn.disabled = false; |
||
| 812 | }; |
||
| 813 | |||
| 814 | document.getElementById("btn_uploadfile").onclick = function() { |
||
| 815 | const fileSelector = document.getElementById("upfile"); |
||
| 816 | const f = fileSelector.files[0]; |
||
| 817 | |||
| 818 | if (f.name.length + f.size > 8138) { |
||
| 819 | console.log("Too large"); |
||
| 820 | fileSelector.value = null; |
||
| 821 | return; |
||
| 822 | } |
||
| 823 | |||
| 824 | const btn = this; |
||
| 825 | btn.disabled = true; |
||
| 826 | |||
| 827 | const reader = new FileReader(); |
||
| 828 | reader.onload = function(e) { |
||
| 829 | const u8data = new Uint8Array(reader.result); |
||
| 830 | |||
| 831 | ae.Message_Assign(true, f.name, u8data, function(success) { |
||
| 832 | if (success) { |
||
| 833 | addFile(ae.GetFileCount() - 1); |
||
| 834 | fileSelector.value = null; |
||
| 835 | } else { |
||
| 836 | console.log("Failed to upload file"); |
||
| 837 | } |
||
| 838 | |||
| 839 | btn.disabled = false; |
||
| 840 | }); |
||
| 841 | }; |
||
| 842 | |||
| 843 | reader.readAsArrayBuffer(f); |
||
| 844 | }; |
||
| 845 | |||
| 846 | function navNotesMenu(num) { |
||
| 847 | for (let i = 0; i < 3; i++) { |
||
| 848 | if (i === num) { |
||
| 849 | document.getElementById("div_notes").children[0].children[i].disabled = true; |
||
| 850 | document.getElementById("div_notes").children[1 + i].hidden = false; |
||
| 851 | } else { |
||
| 852 | document.getElementById("div_notes").children[0].children[i].disabled = false; |
||
| 853 | document.getElementById("div_notes").children[1 + i].hidden = true; |
||
| 854 | } |
||
| 855 | } |
||
| 856 | } |
||
| 857 | |||
| 858 | let btns = document.getElementsByTagName("nav")[0].getElementsByTagName("button"); |
||
| 859 | btns[0].onclick = function() {navMenu(0);}; |
||
| 860 | btns[1].onclick = function() {navMenu(1);}; |
||
| 861 | btns[2].onclick = function() {navMenu(2);}; |
||
| 862 | btns[3].onclick = function() {navMenu(3);}; |
||
| 863 | btns[4].onclick = function() {navMenu(4);}; |
||
| 864 | |||
| 865 | btns = document.getElementById("div_notes").getElementsByTagName("button"); |
||
| 866 | btns[0].onclick = function() {navNotesMenu(0);}; |
||
| 867 | btns[1].onclick = function() {navNotesMenu(1);}; |
||
| 868 | btns[2].onclick = function() {navNotesMenu(2);}; |
||
| 869 | btns[3].onclick = function() {navNotesMenu(3);}; |
||
| 870 | |||
| 871 | document.getElementById("txt_skey").onkeyup = function(e) { |
||
| 872 | if (e.key === "Enter") document.getElementById("btn_enter").click(); |
||
| 873 | }; |
||
| 874 | |||
| 875 | navMenu(0); |
||
| 876 | |||
| 877 | }); |
||
| 878 |