100 lines
3.3 KiB
JavaScript
Executable File
100 lines
3.3 KiB
JavaScript
Executable File
$(document).ready(function () {
|
|
var nextCtl = $('#vars').attr('nextCtl');
|
|
var c = $('button.accordion-button[data-bs-target="#ctl' + nextCtl + '"]');
|
|
$(c).click();
|
|
|
|
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(function(el) {
|
|
new bootstrap.Tooltip(el);
|
|
});
|
|
|
|
$('.cal-grid-cell').click(function() {
|
|
var ctl = $(this).data('ctl');
|
|
var btn = $('button.accordion-button[data-bs-target="#ctl' + ctl + '"]');
|
|
if (btn.hasClass('collapsed')) {
|
|
btn.click();
|
|
}
|
|
btn.closest('.accordion-item')[0].scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
});
|
|
$('button[action]').click(function() {
|
|
var action = $(this).attr('action');
|
|
var url = null;
|
|
var target = action;
|
|
if ( action == 'jitsi' ) {
|
|
url = 'https://meet.homelabbrisbane.com.au/hlb';
|
|
}
|
|
if ( action == 'map' ) {
|
|
url = 'https://www.google.com/maps/place/' + $(this).attr('coordinates');
|
|
}
|
|
if ( action == 'copy' ) {
|
|
navigator.clipboard.writeText( $(this).attr('value') );
|
|
}
|
|
if ( url != null ) {
|
|
window.open( url, target );
|
|
}
|
|
});
|
|
|
|
$('.unlock-pin').click(async function() {
|
|
const btn = $(this);
|
|
const pinDisplay = btn.siblings('.pin-display');
|
|
const ciphertext = btn.data('ciphertext');
|
|
const iv = btn.data('iv');
|
|
const salt = btn.data('salt');
|
|
const tag = btn.data('tag');
|
|
|
|
const password = prompt("Enter the members password to unlock the PIN:");
|
|
if (!password) return;
|
|
|
|
try {
|
|
const decrypted = await decryptPin(ciphertext, iv, salt, tag, password);
|
|
pinDisplay.val(decrypted);
|
|
btn.text('Copy').removeClass('unlock-pin').attr('action', 'copy').attr('value', decrypted);
|
|
// Re-bind the click event for the new copy action (or use delegation)
|
|
btn.off('click').click(function() {
|
|
navigator.clipboard.writeText($(this).attr('value'));
|
|
alert('PIN copied to clipboard!');
|
|
});
|
|
} catch (e) {
|
|
alert(e.message);
|
|
}
|
|
});
|
|
|
|
async function decryptPin(ciphertextBase64, ivBase64, saltBase64, tagBase64, password) {
|
|
const encoder = new TextEncoder();
|
|
const passwordKey = await crypto.subtle.importKey(
|
|
"raw", encoder.encode(password), "PBKDF2", false, ["deriveKey"]
|
|
);
|
|
const salt = Uint8Array.from(atob(saltBase64), c => c.charCodeAt(0));
|
|
const iv = Uint8Array.from(atob(ivBase64), c => c.charCodeAt(0));
|
|
const tag = Uint8Array.from(atob(tagBase64), c => c.charCodeAt(0));
|
|
const ciphertext = Uint8Array.from(atob(ciphertextBase64), c => c.charCodeAt(0));
|
|
|
|
const data = new Uint8Array(ciphertext.length + tag.length);
|
|
data.set(ciphertext);
|
|
data.set(tag, ciphertext.length);
|
|
|
|
const key = await crypto.subtle.deriveKey(
|
|
{ name: "PBKDF2", salt, iterations: 100000, hash: "SHA-256" },
|
|
passwordKey,
|
|
{ name: "AES-GCM", length: 256 },
|
|
false,
|
|
["decrypt"]
|
|
);
|
|
|
|
try {
|
|
const decrypted = await crypto.subtle.decrypt(
|
|
{ name: "AES-GCM", iv, tagLength: 128 },
|
|
key,
|
|
data
|
|
);
|
|
return new TextDecoder().decode(decrypted);
|
|
} catch (e) {
|
|
throw new Error("Decryption failed. Probably wrong password.");
|
|
}
|
|
}
|
|
|
|
var isPhone = /Mobi|Android|iPhone|iPod/i.test(navigator.userAgent) || window.innerWidth <= 768;
|
|
if (isPhone) {
|
|
$("body").addClass("phone");
|
|
}
|
|
});
|