2024-06-22 14:57:09 +01:00
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
2024-07-30 11:23:22 +01:00
let secretKey = localStorage . getItem ( "PRIVATE-secretKey" )
let password = localStorage . getItem ( "PRIVATE-cryptoKey" )
2024-08-07 17:48:43 +01:00
let fontSize = Number ( localStorage . getItem ( "SETTING-fontsize" ) )
2024-07-30 11:23:22 +01:00
let remote = localStorage . getItem ( "SETTING-homeServer" )
if ( secretKey === null || password === null ) {
2024-04-28 23:48:03 +01:00
window . location . replace ( "/login" )
2024-03-12 18:34:05 +00:00
document . body . innerHTML = "Redirecting..."
throw new Error ( ) ;
2024-07-30 11:23:22 +01:00
} else if ( fontSize === null ) {
localStorage . setItem ( "SETTING-fontsize" , "16" )
fontSize = 16
2024-03-12 18:34:05 +00:00
}
if ( remote == null ) {
2024-08-07 17:01:58 +01:00
localStorage . setItem ( "SETTING-homeServer" , "https://notes.hectabit.org" )
remote = "https://notes.hectabit.org"
2024-03-12 18:34:05 +00:00
}
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
function formatBytes ( a , b = 2 ) {
if ( ! + a ) return "0 Bytes" ; const c = 0 > b ? 0 : b , d = Math . floor ( Math . log ( a ) / Math . log ( 1000 ) ) ;
return ` ${ parseFloat ( ( a / Math . pow ( 1000 , d ) ) . toFixed ( c ) ) } ${ [ "Bytes" , "KB" , "MB" , "GB" , "TB" , "PB" , "EB" , "ZB" , "YB" ] [ d ] } `
}
2024-03-12 18:34:05 +00:00
2024-07-30 11:03:05 +01:00
let offlineMode = false
2024-05-20 20:24:43 +01:00
let backButton = document . getElementById ( "backButton" )
2024-03-12 18:34:05 +00:00
let usernameBox = document . getElementById ( "usernameBox" )
let optionsCoverDiv = document . getElementById ( "optionsCoverDiv" )
let optionsDiv = document . getElementById ( "optionsDiv" )
let errorDiv = document . getElementById ( "errorDiv" )
2024-07-05 22:46:53 +01:00
let uploadThing = document . getElementById ( "uploadThing" )
let browseButton = document . getElementById ( "browseButton" )
2024-03-12 18:34:05 +00:00
let errorMessageThing = document . getElementById ( "errorMessageThing" )
let closeErrorButton = document . getElementById ( "closeErrorButton" )
let cancelErrorButton = document . getElementById ( "cancelErrorButton" )
let errorInput = document . getElementById ( "errorInput" )
let exitThing = document . getElementById ( "exitThing" )
2024-06-27 17:57:05 +01:00
let exitImportThing = document . getElementById ( "exitImportThing" )
2024-03-12 18:34:05 +00:00
let exitSessionsThing = document . getElementById ( "exitSessionsThing" )
let sessionManagerButton = document . getElementById ( "sessionManagerButton" )
2024-05-20 20:24:43 +01:00
let importNotesButton = document . getElementById ( "importNotesButton" )
2024-03-12 18:34:05 +00:00
let sessionManagerDiv = document . getElementById ( "sessionManagerDiv" )
2024-05-20 20:24:43 +01:00
let importNotesDiv = document . getElementById ( "importDiv" )
2024-03-12 18:34:05 +00:00
let sessionDiv = document . getElementById ( "sessionDiv" )
let deleteMyAccountButton = document . getElementById ( "deleteMyAccountButton" )
2024-06-27 17:57:05 +01:00
let changePasswordButton = document . getElementById ( "changePasswordButton" )
2024-03-12 18:34:05 +00:00
let storageThing = document . getElementById ( "storageThing" )
let storageProgressThing = document . getElementById ( "storageProgressThing" )
let usernameThing = document . getElementById ( "usernameThing" )
let logOutButton = document . getElementById ( "logOutButton" )
let notesBar = document . getElementById ( "notesBar" )
2024-06-25 19:43:24 +01:00
let topBar = document . getElementById ( "topBar" )
2024-03-12 18:34:05 +00:00
let notesDiv = document . getElementById ( "notesDiv" )
let newNote = document . getElementById ( "newNote" )
2024-05-20 20:24:43 +01:00
let noteBoxDiv = document . getElementById ( "noteBoxDiv" )
2024-07-02 18:13:28 +01:00
let pellAttacher = document . getElementById ( "noteBox" )
2024-03-12 18:34:05 +00:00
let loadingStuff = document . getElementById ( "loadingStuff" )
let exportNotesButton = document . getElementById ( "exportNotesButton" )
2024-04-28 23:48:03 +01:00
let textSizeBox = document . getElementById ( 'textSizeBox' ) ;
let textPlusBox = document . getElementById ( 'textPlusBox' ) ;
let textMinusBox = document . getElementById ( 'textMinusBox' ) ;
let wordCountBox = document . getElementById ( 'wordCountBox' ) ;
let removeBox = document . getElementById ( "removeBox" )
2024-07-05 22:46:53 +01:00
let importFileConfirm = document . getElementById ( "importFileConfirm" )
2024-03-12 18:34:05 +00:00
let selectedNote = 0
let timer
let waitTime = 400
2024-05-20 20:24:43 +01:00
let indiv = false
let mobile = false
2024-06-23 15:49:01 +01:00
let selectLatestNote = false
2024-03-12 18:34:05 +00:00
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
function arrayBufferToBase64 ( buffer ) {
const uint8Array = new Uint8Array ( buffer ) ;
return btoa ( String . fromCharCode . apply ( null , uint8Array ) )
}
function base64ToArrayBuffer ( base64 ) {
const binaryString = atob ( base64 ) ;
const length = binaryString . length ;
const buffer = new ArrayBuffer ( length ) ;
const uint8Array = new Uint8Array ( buffer ) ;
for ( let i = 0 ; i < length ; i ++ ) {
uint8Array [ i ] = binaryString . charCodeAt ( i ) ;
}
return buffer ;
}
2024-07-06 16:02:20 +01:00
async function getKey ( ) {
let salt = new TextEncoder ( ) . encode ( "I love Burgernotes!" )
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
let cryptoKey = await window . crypto . subtle . importKey ( "raw" , new TextEncoder ( ) . encode ( password ) , "PBKDF2" , false , [ "deriveBits" , "deriveKey" ] )
2024-07-06 16:02:20 +01:00
return await window . crypto . subtle . deriveKey ( {
name : "PBKDF2" ,
salt ,
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
iterations : 1 ,
2024-07-06 16:02:20 +01:00
hash : "SHA-512"
} , cryptoKey , { name : "AES-GCM" , length : 256 } , true , [ "encrypt" , "decrypt" ] )
}
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
async function encrypt ( text ) {
let cryptoKey = await getKey ( )
let iv = window . crypto . getRandomValues ( new Uint8Array ( 12 ) )
let encrypted = await window . crypto . subtle . encrypt ( {
name : "AES-GCM" ,
iv : iv
} , cryptoKey , new TextEncoder ( ) . encode ( text ) )
return btoa ( JSON . stringify ( {
encrypted : arrayBufferToBase64 ( encrypted ) ,
iv : arrayBufferToBase64 ( iv )
} ) )
2024-07-06 16:02:20 +01:00
}
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
async function decrypt ( encrypted ) {
if ( encrypted === "" ) {
return ""
} else {
let cryptoKey = await getKey ( )
let jsonData = JSON . parse ( atob ( encrypted ) )
let encryptedData = base64ToArrayBuffer ( jsonData . encrypted )
let iv = base64ToArrayBuffer ( jsonData . iv )
let decrypted = await window . crypto . subtle . decrypt ( {
name : "AES-GCM" ,
iv : iv
} , cryptoKey , encryptedData )
return new TextDecoder ( ) . decode ( decrypted )
}
2024-07-06 16:02:20 +01:00
}
2024-07-02 18:25:23 +01:00
function handleGesture ( ) {
if ( indiv ) {
indiv = false
notesBar . style . width = "100%" ;
noteBoxDiv . style . width = "0px"
if ( selectedNote !== 0 ) {
noteBoxDiv . readOnly = true
}
notesDiv . classList . remove ( "hidden" )
noteBoxDiv . classList . add ( "hidden" )
backButton . classList . add ( "hidden" )
newNote . classList . remove ( "hidden" )
} else {
indiv = true
noteBoxDiv . style . width = "100%" ;
notesBar . style . width = "0px"
if ( selectedNote !== 0 ) {
noteBoxDiv . readOnly = false
}
notesDiv . classList . add ( "hidden" )
noteBoxDiv . classList . remove ( "hidden" )
backButton . classList . remove ( "hidden" )
newNote . classList . add ( "hidden" )
}
}
2024-07-02 18:13:28 +01:00
// Init the note box
2024-07-30 11:03:05 +01:00
document . addEventListener ( "DOMContentLoaded" , async function ( ) {
2024-07-02 18:13:28 +01:00
pell . init ( {
element : pellAttacher ,
2024-07-30 11:03:05 +01:00
onChange : function ( html ) {
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
// Having a nice day? This does nothing.
} ,
2024-07-02 18:13:28 +01:00
defaultParagraphSeparator : 'br' ,
styleWithCSS : false ,
classes : {
actionbar : 'pell-actionbar' ,
button : 'pell-button' ,
content : 'pell-content' ,
selected : 'pell-button-selected'
2024-07-02 19:04:13 +01:00
} ,
actions : [
"bold" ,
"italic" ,
"underline" ,
"strikethrough" ,
"heading1" ,
"heading2" ,
"paragraph" ,
"quote" ,
"olist" ,
"ulist" ,
"code" ,
"line" ,
"link" ,
{
name : 'uploadimage' ,
icon : '📁' ,
title : 'Upload image' ,
2024-07-30 11:03:05 +01:00
result : async function result ( ) {
browseButton . classList . remove ( "hidden" )
displayError ( "Select an image to upload:" )
await waitForConfirm ( )
browseButton . classList . add ( "hidden" )
let file = uploadThing . files [ 0 ]
if ( file ) {
let reader = new FileReader ( )
reader . readAsDataURL ( file )
uploadThing . files = null
reader . onload = function ( ) {
pell . exec ( 'insertImage' , reader . result ) ;
2024-07-02 19:04:13 +01:00
}
}
}
} ,
"image" ,
] ,
2024-07-02 18:13:28 +01:00
} )
let noteBox = document . getElementsByClassName ( "pell-content" ) [ 0 ]
if ( /Android|iPhone|iPod/i . test ( navigator . userAgent ) ) {
mobile = true
noteBoxDiv . classList . add ( "mobile" )
noteBoxDiv . style . width = "0px" ;
notesBar . style . width = "100%"
topBar . style . width = "100%"
noteBoxDiv . readOnly = true
2024-06-25 19:43:24 +01:00
noteBoxDiv . classList . add ( "hidden" )
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
let touchstartX , touchstartY , touchendX , touchendY
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
notesBar . addEventListener ( "touchstart" , function ( event ) {
touchstartX = event . changedTouches [ 0 ] . screenX ;
touchstartY = event . changedTouches [ 0 ] . screenY ;
} , false ) ;
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
notesBar . addEventListener ( "touchend" , function ( event ) {
touchendX = event . changedTouches [ 0 ] . screenX ;
touchendY = event . changedTouches [ 0 ] . screenY ;
if ( touchendX < touchstartX - 75 ) {
handleGesture ( ) ;
}
} , false ) ;
noteBox . addEventListener ( "touchstart" , function ( event ) {
touchstartX = event . changedTouches [ 0 ] . screenX ;
touchstartY = event . changedTouches [ 0 ] . screenY ;
} , false ) ;
noteBox . addEventListener ( "touchend" , function ( event ) {
touchendX = event . changedTouches [ 0 ] . screenX ;
touchendY = event . changedTouches [ 0 ] . screenY ;
if ( touchendX > touchstartX + 75 ) {
handleGesture ( ) ;
}
} , false ) ;
2024-04-25 22:34:18 +01:00
}
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
noteBox . innerText = ""
noteBox . readOnly = true
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
let noteCount = 0
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
function displayError ( message ) {
errorDiv . classList . remove ( "hidden" )
optionsCoverDiv . classList . remove ( "hidden" )
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
errorMessageThing . innerHTML = message
2024-03-12 18:34:05 +00:00
}
2024-07-02 18:13:28 +01:00
closeErrorButton . addEventListener ( "click" , ( ) => {
errorDiv . classList . add ( "hidden" )
optionsCoverDiv . classList . add ( "hidden" )
} ) ;
closeErrorButton . addEventListener ( "click" , ( ) => {
errorDiv . classList . add ( "hidden" )
optionsCoverDiv . classList . add ( "hidden" )
errorInput . classList . add ( "hidden" )
cancelErrorButton . classList . add ( "hidden" )
} ) ;
function updateFont ( ) {
2024-07-30 11:23:22 +01:00
noteBox . style . fontSize = fontSize + "px"
textSizeBox . innerText = fontSize + "px"
2024-07-02 18:13:28 +01:00
}
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
async function checknetwork ( ) {
2024-07-30 11:23:22 +01:00
fetch ( remote + "/api/loggedin" , {
2024-07-02 18:13:28 +01:00
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey
2024-07-02 18:13:28 +01:00
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
. catch ( ( ) => {
2024-07-30 11:03:05 +01:00
offlineMode = true
2024-07-02 18:13:28 +01:00
noteBox . contentEditable = false
noteBox . innerHTML = "<h1>You are currently offline.</h1>"
displayError ( "Failed to connect to the server.\nPlease check your internet connection." )
} )
. then ( ( response ) => response )
. then ( ( response ) => {
2024-07-30 11:03:05 +01:00
if ( response . status === 400 || response . status === 401 ) {
offlineMode = true
2024-05-24 19:48:24 +01:00
displayError ( "Something went wrong! Signing you out..." )
2024-03-12 18:34:05 +00:00
closeErrorButton . classList . add ( "hidden" )
setTimeout ( function ( ) {
2024-04-28 23:48:03 +01:00
window . location . replace ( "/logout" )
2024-03-12 18:34:05 +00:00
} , 2500 ) ;
2024-07-02 18:13:28 +01:00
} else if ( response . status === 200 ) {
updateUserInfo ( )
2024-03-12 18:34:05 +00:00
} else {
2024-07-30 11:03:05 +01:00
offlineMode = true
2024-07-02 18:13:28 +01:00
noteBox . readOnly = true
noteBox . innerHTML = "<h1>You are currently offline.</h1>"
displayError ( "Failed to connect to the server.\nPlease check your internet connection." )
2024-03-12 18:34:05 +00:00
}
2024-07-02 18:13:28 +01:00
} ) ;
}
2024-07-30 11:23:22 +01:00
updateFont ( )
2024-07-02 18:13:28 +01:00
textPlusBox . addEventListener ( "click" , ( ) => {
2024-08-07 17:48:43 +01:00
fontSize += 1
localStorage . setItem ( "SETTING-fontsize" , String ( fontSize ) )
2024-07-02 18:13:28 +01:00
updateFont ( )
} ) ;
textMinusBox . addEventListener ( "click" , ( ) => {
2024-08-07 17:48:43 +01:00
fontSize -= 1
localStorage . setItem ( "SETTING-fontsize" , String ( fontSize ) )
2024-07-02 18:13:28 +01:00
updateFont ( )
} ) ;
function truncateString ( str , num ) {
if ( str . length > num ) {
return str . slice ( 0 , num ) + ".." ;
} else {
return str ;
}
}
function updateUserInfo ( ) {
fetch ( remote + "/api/userinfo" , {
2024-03-12 18:34:05 +00:00
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey
2024-03-12 18:34:05 +00:00
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
2024-07-30 11:03:05 +01:00
. then ( async ( response ) => {
if ( response . status === 500 || response . status === 401 ) {
displayError ( "Something went wrong! Signing you out..." )
closeErrorButton . classList . add ( "hidden" )
setTimeout ( function ( ) {
window . location . replace ( "/logout" )
} , 2500 ) ;
} else {
let responseData = await response . json ( )
usernameThing . innerText = "Username: " + responseData [ "username" ]
storageThing . innerText = "You've used " + formatBytes ( responseData [ "storageused" ] ) + " out of " + formatBytes ( responseData [ "storagemax" ] )
storageProgressThing . value = responseData [ "storageused" ]
storageProgressThing . max = responseData [ "storagemax" ]
noteCount = responseData [ "notecount" ]
2024-03-12 18:34:05 +00:00
}
2024-07-02 18:13:28 +01:00
} ) ;
2024-06-27 17:57:05 +01:00
}
2024-07-02 18:13:28 +01:00
usernameBox . addEventListener ( "click" , ( ) => {
optionsCoverDiv . classList . remove ( "hidden" )
optionsDiv . classList . remove ( "hidden" )
updateUserInfo ( )
} ) ;
logOutButton . addEventListener ( "click" , ( ) => {
window . location . replace ( "/logout" )
} ) ;
exitThing . addEventListener ( "click" , ( ) => {
optionsDiv . classList . add ( "hidden" )
optionsCoverDiv . classList . add ( "hidden" )
} ) ;
deleteMyAccountButton . addEventListener ( "click" , ( ) => {
if ( confirm ( "Are you REALLY sure that you want to delete your account? There's no going back!" ) === true ) {
fetch ( remote + "/api/deleteaccount" , {
2024-06-27 17:57:05 +01:00
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey
2024-06-27 17:57:05 +01:00
} ) ,
headers : {
2024-07-02 18:13:28 +01:00
"Content-Type" : "application/json; charset=UTF-8"
2024-06-27 17:57:05 +01:00
}
} )
2024-07-02 18:13:28 +01:00
. then ( ( response ) => {
if ( response . status === 200 ) {
window . location . href = "/logout"
} else {
displayError ( "Failed to delete account (HTTP error code " + response . status + ")" )
}
} )
2024-06-27 17:57:05 +01:00
}
2024-07-02 18:13:28 +01:00
} ) ;
async function waitForConfirm ( ) {
let resolvePromise ;
const promise = new Promise ( resolve => resolvePromise = resolve ) ;
closeErrorButton . addEventListener ( "click" , ( ) => {
resolvePromise ( ) ;
} ) ;
await promise ;
}
async function hashpass ( pass ) {
2024-07-21 09:09:48 +01:00
return await hashwasm . argon2id ( {
password : pass ,
salt : new TextEncoder ( ) . encode ( "I munch Burgers!!" ) ,
parallelism : 1 ,
iterations : 32 ,
memorySize : 19264 ,
hashLength : 32 ,
outputType : "hex"
} )
2024-07-02 18:13:28 +01:00
}
2024-07-30 11:03:05 +01:00
changePasswordButton . addEventListener ( "click" , async ( ) => {
2024-07-02 18:13:28 +01:00
optionsDiv . classList . add ( "hidden" )
2024-07-30 11:03:05 +01:00
async function fatalError ( notes , passwordBackup ) {
displayError ( "Something went wrong! Your password change has failed. Attempting to revert changes..." )
password = passwordBackup
2024-07-30 11:23:22 +01:00
localStorage . setItem ( "PRIVATE-cryptoKey" , password )
2024-07-30 11:03:05 +01:00
let changePasswordBackResponse = await fetch ( remote + "/api/changepassword" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey ,
2024-07-30 11:03:05 +01:00
newPassword : await hashpass ( oldPass ) ,
migration : false
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8" ,
"X-Burgernotes-Version" : "200"
}
} )
if ( changePasswordBackResponse . status === 200 ) {
let responseStatus = await importNotes ( notes )
if ( responseStatus === 500 ) {
closeErrorButton . classList . remove ( "hidden" )
2024-07-02 18:13:28 +01:00
displayError ( "Failed to revert changes. Please delete this user account and sign-up again, then re-import the notes. Click Ok to download the notes to import later." )
2024-07-30 11:03:05 +01:00
await waitForConfirm ( )
2024-07-02 18:13:28 +01:00
downloadObjectAsJson ( notes , "data" )
2024-07-30 11:03:05 +01:00
} else {
closeErrorButton . classList . remove ( "hidden" )
displayError ( "Password change failed! Changes have been reverted." )
updateNotes ( )
2024-06-27 17:57:05 +01:00
}
2024-07-30 11:03:05 +01:00
} else {
displayError ( "Failed to revert changes. Please delete this user account and sign-up again, then re-import the notes. Click Ok to download the notes to import later." )
downloadObjectAsJson ( notes , "data" )
2024-06-27 17:57:05 +01:00
}
2024-07-30 11:03:05 +01:00
}
2024-03-12 18:34:05 +00:00
2024-07-30 11:03:05 +01:00
displayError ( "Confirm your current password to change it" )
errorInput . type = "password"
errorInput . classList . remove ( "hidden" )
await waitForConfirm ( )
const oldPass = errorInput . value
errorInput . classList . add ( "hidden" )
if ( await hashwasm . argon2id ( {
password : password ,
salt : new TextEncoder ( ) . encode ( "I love Burgernotes!" ) ,
parallelism : 1 ,
iterations : 32 ,
memorySize : 19264 ,
hashLength : 32 ,
outputType : "hex"
} ) !== password ) {
displayError ( "Incorrect password!" )
} else {
errorInput . value = ""
displayError ( "Enter your new password" )
2024-07-02 18:13:28 +01:00
errorInput . classList . remove ( "hidden" )
await waitForConfirm ( )
errorInput . classList . add ( "hidden" )
2024-07-30 11:03:05 +01:00
const newPass = errorInput . value
errorInput . type = "text"
errorInput . value = ""
if ( newPass . length < 8 ) {
displayError ( "Password must be at least 8 characters!" )
2024-07-02 18:13:28 +01:00
} else {
2024-07-30 11:03:05 +01:00
displayError ( "Changing your password. This process may take up to 5 minutes. Do NOT close the tab!" )
closeErrorButton . classList . add ( "hidden" )
const response = await fetch ( remote + "/api/changepassword" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey ,
2024-07-30 11:03:05 +01:00
newPassword : await hashpass ( newPass )
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8" ,
"X-Burgernotes-Version" : "200"
}
} )
if ( response . status === 200 ) {
let notes = await exportNotes ( )
let passwordBackup = password
password = await hashwasm . argon2id ( {
password : password ,
salt : new TextEncoder ( ) . encode ( "I love Burgernotes!" ) ,
parallelism : 1 ,
iterations : 32 ,
memorySize : 19264 ,
hashLength : 32 ,
outputType : "hex"
} )
2024-07-30 11:23:22 +01:00
localStorage . setItem ( "PRIVATE-cryptoKey" , password )
2024-07-30 11:03:05 +01:00
let purgeNotes = await fetch ( remote + "/api/purgenotes" , {
2024-07-02 18:13:28 +01:00
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey
2024-07-02 18:13:28 +01:00
} ) ,
headers : {
2024-07-30 11:03:05 +01:00
"Content-Type" : "application/json; charset=UTF-8"
2024-07-02 18:13:28 +01:00
}
} )
2024-07-30 11:03:05 +01:00
if ( purgeNotes . status !== 200 ) {
2024-08-07 17:48:43 +01:00
await fatalError ( notes , passwordBackup )
2024-07-30 11:03:05 +01:00
} else {
let responseStatus = await importNotes ( notes )
errorDiv . classList . add ( "hidden" )
if ( responseStatus !== 200 ) {
2024-08-07 17:48:43 +01:00
await fatalError ( notes , passwordBackup )
2024-07-02 18:13:28 +01:00
} else {
2024-07-30 11:03:05 +01:00
closeErrorButton . classList . remove ( "hidden" )
displayError ( "Password changed!" )
updateNotes ( )
2024-07-02 18:13:28 +01:00
}
}
2024-07-30 11:03:05 +01:00
} else {
closeErrorButton . classList . remove ( "hidden" )
const data = await response . json ( )
displayError ( data [ "error" ] )
2024-03-12 18:34:05 +00:00
}
}
}
2024-07-02 18:13:28 +01:00
} )
importNotesButton . addEventListener ( "click" , ( ) => {
optionsDiv . classList . add ( "hidden" )
importNotesDiv . classList . remove ( "hidden" )
} ) ;
sessionManagerButton . addEventListener ( "click" , ( ) => {
optionsDiv . classList . add ( "hidden" )
sessionManagerDiv . classList . remove ( "hidden" )
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
fetch ( remote + "/api/sessions/list" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey
2024-07-02 18:13:28 +01:00
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
2024-07-30 11:03:05 +01:00
. then ( async ( response ) => {
let responseData = await response . json ( )
document . querySelectorAll ( ".burgerSession" ) . forEach ( ( el ) => el . remove ( ) ) ;
let ua ;
for ( let i in responseData ) {
let sessionElement = document . createElement ( "div" )
let sessionText = document . createElement ( "p" )
let sessionImage = document . createElement ( "img" )
let sessionRemoveButton = document . createElement ( "button" )
sessionText . classList . add ( "w300" )
if ( responseData [ i ] [ "thisSession" ] === true ) {
sessionText . innerText = "(current) " + responseData [ i ] [ "device" ]
} else {
sessionText . innerText = responseData [ i ] [ "device" ]
}
sessionText . title = responseData [ i ] [ "device" ]
sessionRemoveButton . innerText = "x"
2024-06-23 15:49:01 +01:00
2024-07-30 11:03:05 +01:00
sessionImage . src = "/static/svg/device_other.svg"
2024-06-23 15:49:01 +01:00
2024-07-30 11:03:05 +01:00
ua = responseData [ i ] [ "device" ]
2024-06-23 15:49:01 +01:00
2024-07-30 11:03:05 +01:00
if ( ua . includes ( "NT" ) || ua . includes ( "Linux" ) ) {
sessionImage . src = "/static/svg/device_computer.svg"
}
if ( ua . includes ( "iPhone" || ua . includes ( "Android" ) || ua . includes ( "iPod" ) ) ) {
sessionImage . src = "/static/svg/device_smartphone.svg"
}
2024-03-12 18:34:05 +00:00
2024-07-30 11:03:05 +01:00
sessionRemoveButton . addEventListener ( "click" , ( ) => {
fetch ( remote + "/api/sessions/remove" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey ,
2024-07-30 11:03:05 +01:00
sessionId : responseData [ i ] [ "id" ]
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
. then ( ( ) => {
if ( responseData [ i ] [ "thisSession" ] === true ) {
window . location . replace ( "/logout" )
2024-03-12 18:34:05 +00:00
}
2024-07-30 11:03:05 +01:00
} ) ;
sessionElement . remove ( )
} ) ;
2024-03-12 18:34:05 +00:00
2024-07-30 11:03:05 +01:00
sessionElement . append ( sessionImage )
sessionElement . append ( sessionText )
sessionElement . append ( sessionRemoveButton )
2024-03-12 18:34:05 +00:00
2024-07-30 11:03:05 +01:00
sessionElement . classList . add ( "burgerSession" )
2024-06-23 15:49:01 +01:00
2024-07-30 11:03:05 +01:00
sessionDiv . append ( sessionElement )
2024-07-02 18:13:28 +01:00
}
} ) ;
} ) ;
exitImportThing . addEventListener ( "click" , ( ) => {
optionsDiv . classList . remove ( "hidden" )
importNotesDiv . classList . add ( "hidden" )
} ) ;
exitSessionsThing . addEventListener ( "click" , ( ) => {
optionsDiv . classList . remove ( "hidden" )
sessionManagerDiv . classList . add ( "hidden" )
} ) ;
2024-06-23 15:49:01 +01:00
2024-07-02 18:13:28 +01:00
function updateWordCount ( ) {
let wordCount = noteBox . innerText . split ( " " ) . length
if ( wordCount === 1 ) {
wordCount = 0
}
wordCountBox . innerText = wordCount + " words"
}
2024-06-23 15:49:01 +01:00
2024-07-02 18:13:28 +01:00
function selectNote ( nameithink ) {
document . querySelectorAll ( ".noteButton" ) . forEach ( ( el ) => el . classList . remove ( "selected" ) ) ;
let thingArray = Array . from ( document . querySelectorAll ( ".noteButton" ) ) . find ( el => String ( nameithink ) === String ( el . id ) ) ;
thingArray . classList . add ( "selected" )
2024-06-27 17:57:05 +01:00
2024-07-02 18:13:28 +01:00
fetch ( remote + "/api/readnote" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey ,
2024-07-02 18:13:28 +01:00
noteId : nameithink ,
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
. catch ( ( ) => {
noteBox . contentEditable = false
noteBox . innerHTML = ""
displayError ( "Something went wrong... Please try again later!" )
} )
2024-07-30 11:03:05 +01:00
. then ( async ( response ) => {
2024-07-02 18:13:28 +01:00
selectedNote = nameithink
if ( mobile ) {
handleGesture ( )
2024-06-23 15:49:01 +01:00
}
2024-07-02 18:13:28 +01:00
noteBox . contentEditable = true
noteBox . click ( )
2024-06-23 15:49:01 +01:00
2024-07-30 11:03:05 +01:00
let responseData = await response . json ( )
2024-06-23 15:49:01 +01:00
2024-07-30 11:03:05 +01:00
let htmlNote
try {
htmlNote = await decrypt ( responseData [ "content" ] )
} catch ( e ) {
console . log ( e )
console . log ( responseData )
}
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
2024-07-30 11:03:05 +01:00
console . log ( htmlNote )
let cleanedHTML = htmlNote . replace ( /<(?!\/?(h1|h2|br|img|blockquote|ol|li|b|i|u|strike|p|pre|ul|hr|a)\b)[^>]*>/gi , '(potential XSS tag was here)' )
noteBox . innerHTML = cleanedHTML . replaceAll ( "\n" , "<br>" )
2024-03-12 18:34:05 +00:00
2024-07-30 11:03:05 +01:00
updateWordCount ( )
2024-03-12 18:34:05 +00:00
2024-07-30 11:03:05 +01:00
noteBox . addEventListener ( "input" , ( ) => {
updateWordCount ( )
clearTimeout ( timer ) ;
timer = setTimeout ( async ( ) => {
let preEncryptedTitle = "New note"
2024-06-23 15:49:01 +01:00
2024-07-30 11:03:05 +01:00
if ( noteBox . innerText !== "" ) {
preEncryptedTitle = new RegExp ( '(.+?)(?=\n)|[\s\S]*?(\S+)(?=\n)' ) . exec ( noteBox . innerText ) [ 0 ]
}
2024-03-12 18:34:05 +00:00
2024-07-30 11:03:05 +01:00
preEncryptedTitle = truncateString ( preEncryptedTitle , 15 )
document . getElementById ( nameithink ) . innerText = preEncryptedTitle
2024-07-02 18:13:28 +01:00
2024-07-30 11:03:05 +01:00
console . log ( noteBox . innerHTML )
let encryptedText = await encrypt ( noteBox . innerHTML )
let encryptedTitle = await encrypt ( preEncryptedTitle )
2024-07-02 18:13:28 +01:00
2024-07-30 11:03:05 +01:00
if ( selectedNote === nameithink ) {
fetch ( remote + "/api/editnote" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey ,
2024-07-30 11:03:05 +01:00
noteId : nameithink ,
content : encryptedText ,
title : encryptedTitle
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
. then ( ( response ) => {
if ( response . status === 418 ) {
displayError ( "You've ran out of storage... Changes will not be saved until you free up storage!" )
2024-07-02 18:13:28 +01:00
}
2024-03-12 18:34:05 +00:00
} )
2024-07-30 11:03:05 +01:00
. catch ( ( ) => {
displayError ( "Failed to save changes, please try again later..." )
} )
}
} , waitTime ) ;
} ) ;
2024-07-02 18:13:28 +01:00
} ) ;
}
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
function updateNotes ( ) {
2024-07-30 11:03:05 +01:00
if ( ! offlineMode ) {
fetch ( remote + "/api/listnotes" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey
2024-07-30 11:03:05 +01:00
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
. then ( async ( response ) => {
2024-07-02 18:13:28 +01:00
noteBox . contentEditable = false
selectedNote = 0
noteBox . innerHTML = ""
clearTimeout ( timer )
updateWordCount ( )
let responseData = await response . json ( )
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
let decryptedResponseData = [ ]
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
let highestID = 0
let noteData ;
for ( let i in responseData ) {
noteData = responseData [ i ]
2024-03-12 18:34:05 +00:00
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
try {
noteData [ "title" ] = await decrypt ( noteData [ "title" ] )
} catch ( e ) {
2024-07-30 11:03:05 +01:00
if ( ! offlineMode ) {
location . href = "/migrate"
}
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
}
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
if ( noteData [ "id" ] > highestID ) {
highestID = noteData [ "id" ]
}
2024-05-20 20:24:43 +01:00
2024-07-02 18:13:28 +01:00
decryptedResponseData . push ( noteData )
}
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
document . querySelectorAll ( ".noteButton" ) . forEach ( ( el ) => el . remove ( ) ) ;
for ( let i in decryptedResponseData ) {
let noteData = decryptedResponseData [ i ]
2024-03-12 18:34:05 +00:00
2024-07-02 18:13:28 +01:00
let noteButton = document . createElement ( "button" ) ;
noteButton . classList . add ( "noteButton" )
notesDiv . append ( noteButton )
2024-04-24 20:25:23 +01:00
2024-07-02 18:13:28 +01:00
if ( noteData [ "title" ] === "" ) {
noteData [ "title" ] = "New note"
}
2024-05-20 20:24:43 +01:00
2024-07-02 18:13:28 +01:00
noteButton . id = noteData [ "id" ]
noteButton . innerText = truncateString ( noteData [ "title" ] , 15 )
noteButton . addEventListener ( "click" , ( event ) => {
if ( event . ctrlKey ) {
fetch ( remote + "/api/removenote" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey ,
2024-07-02 18:13:28 +01:00
noteId : noteData [ "id" ]
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
. then ( ( ) => {
updateNotes ( )
} )
. catch ( ( ) => {
displayError ( "Something went wrong! Please try again later..." )
} )
} else {
selectNote ( noteData [ "id" ] )
}
} ) ;
2024-06-27 17:57:05 +01:00
}
2024-07-02 18:13:28 +01:00
document . querySelectorAll ( ".loadingStuff" ) . forEach ( ( el ) => el . remove ( ) ) ;
2024-05-20 20:24:43 +01:00
2024-07-02 18:13:28 +01:00
if ( selectLatestNote === true ) {
selectNote ( highestID )
selectLatestNote = false
}
2024-07-30 11:03:05 +01:00
} ) ;
} else {
console . log ( "Currently offline, refusing to update notes." )
}
2024-07-02 18:13:28 +01:00
}
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
newNote . addEventListener ( "click" , async ( ) => {
2024-07-02 18:13:28 +01:00
let noteName = "New note"
2024-06-23 15:49:01 +01:00
selectLatestNote = true
2024-07-02 18:13:28 +01:00
// create fake item
document . querySelectorAll ( ".noteButton" ) . forEach ( ( el ) => el . classList . remove ( "selected" ) ) ;
let noteButton = document . createElement ( "button" ) ;
noteButton . classList . add ( "noteButton" )
notesDiv . append ( noteButton )
noteButton . innerText = "New note"
noteButton . style . order = "-1"
noteButton . classList . add ( "selected" )
noteBox . click ( )
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
let encryptedName
encryptedName = await encrypt ( noteName )
2024-07-02 18:13:28 +01:00
fetch ( remote + "/api/newnote" , {
2024-03-12 18:34:05 +00:00
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey ,
2024-07-02 18:13:28 +01:00
noteName : encryptedName ,
2024-03-12 18:34:05 +00:00
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
2024-04-28 23:48:03 +01:00
. catch ( ( ) => {
2024-07-02 18:13:28 +01:00
displayError ( "Failed to create new note, please try again later..." )
2024-03-12 18:34:05 +00:00
} )
2024-07-02 18:13:28 +01:00
. then ( ( response ) => {
if ( response . status !== 200 ) {
updateNotes ( )
displayError ( "Failed to create new note (HTTP error code " + response . status + ")" )
} else {
updateNotes ( )
}
} ) ;
} ) ;
function downloadObjectAsJson ( exportObj , exportName ) {
let dataStr = "data:text/json;charset=utf-8," + JSON . stringify ( exportObj ) ;
let downloadAnchorNode = document . createElement ( "a" ) ;
downloadAnchorNode . setAttribute ( "href" , dataStr ) ;
downloadAnchorNode . setAttribute ( "download" , exportName + ".json" ) ;
document . body . appendChild ( downloadAnchorNode ) ;
downloadAnchorNode . click ( ) ;
downloadAnchorNode . remove ( ) ;
2024-03-12 18:34:05 +00:00
}
2024-07-02 18:13:28 +01:00
async function exportNotes ( ) {
2024-07-30 11:03:05 +01:00
if ( ! offlineMode ) {
let exportNotesFetch = await fetch ( remote + "/api/exportnotes" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey
2024-07-30 11:03:05 +01:00
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
let responseData = await exportNotesFetch . json ( )
for ( let i in responseData ) {
exportNotes . innerText = "Decrypting " + i + "/" + noteCount
try {
responseData [ i ] [ "title" ] = await decrypt ( responseData [ i ] [ "title" ] )
responseData [ i ] [ "content" ] = await decrypt ( responseData [ i ] [ "content" ] )
} catch ( e ) {
location . href = "/migrate"
}
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
}
2024-07-30 11:03:05 +01:00
return responseData
} else {
displayError ( "You can't export notes while offline!" )
2024-07-02 18:13:28 +01:00
}
}
async function importNotes ( plaintextNotes ) {
for ( let i in plaintextNotes ) {
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
plaintextNotes [ i ] [ "title" ] = await encrypt ( plaintextNotes [ i ] [ "title" ] )
plaintextNotes [ i ] [ "content" ] = await encrypt ( plaintextNotes [ i ] [ "content" ] )
2024-07-02 18:13:28 +01:00
}
let importNotesFetch = await fetch ( remote + "/api/importnotes" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
"secretKey" : secretKey ,
2024-07-02 18:13:28 +01:00
"notes" : JSON . stringify ( plaintextNotes )
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
return importNotesFetch . status
}
function firstNewVersion ( ) {
2024-07-30 11:23:22 +01:00
if ( localStorage . getItem ( "SETTING-newVersion" ) === "2.0" ) {
2024-07-02 18:13:28 +01:00
return false ;
} else {
2024-07-30 11:23:22 +01:00
localStorage . setItem ( "SETTING-newVersion" , "2.0" )
2024-07-02 18:13:28 +01:00
return true ;
}
}
2024-06-22 14:57:09 +01:00
2024-07-02 18:13:28 +01:00
exportNotesButton . addEventListener ( "click" , ( ) => {
let responseData = exportNotes ( )
downloadObjectAsJson ( responseData , "data" )
optionsDiv . classList . add ( "hidden" )
displayError ( "Exported notes!" )
} ) ;
2024-07-05 22:46:53 +01:00
importFileConfirm . addEventListener ( 'click' , function ( ) {
2024-07-02 18:13:28 +01:00
let fileread = new FileReader ( )
fileread . addEventListener (
"load" ,
( ) => {
let decrypted = JSON . parse ( fileread . result . toString ( ) )
importNotes ( decrypted )
. then ( ( responseStatus ) => {
if ( responseStatus === 500 ) {
optionsDiv . classList . add ( "hidden" )
importNotesDiv . classList . add ( "hidden" )
displayError ( "Something went wrong! Perhaps your note file was invalid?" )
} else {
optionsDiv . classList . add ( "hidden" )
importNotesDiv . classList . add ( "hidden" )
displayError ( "Notes uploaded!" )
updateNotes ( )
}
} )
} ,
false ,
) ;
2024-07-05 22:46:53 +01:00
fileread . readAsText ( uploadThing . files [ 0 ] )
2024-07-02 18:13:28 +01:00
} )
removeBox . addEventListener ( "click" , ( ) => {
if ( selectedNote === 0 ) {
displayError ( "You need to select a note first!" )
} else {
selectLatestNote = true
fetch ( remote + "/api/removenote" , {
method : "POST" ,
body : JSON . stringify ( {
2024-07-30 11:23:22 +01:00
secretKey : secretKey ,
2024-07-02 18:13:28 +01:00
noteId : selectedNote
} ) ,
headers : {
"Content-Type" : "application/json; charset=UTF-8"
}
} )
. then ( ( ) => {
updateNotes ( )
} )
. catch ( ( ) => {
displayError ( "Something went wrong! Please try again later..." )
} )
}
} ) ;
if ( firstNewVersion ( ) ) {
Fixed the labels not being hidden in inoutdivs, made inoutdivs use a flexbox or table to avoid the use of a calc() and a transform(), updated to AES-256 GCM Native crypto from CryptoJS, added a migration page to migrate from CryptoJS, remove the Argon2 Compatibility thing, remove all backwards-compatibility measures, updated the changelog to be accurate, made NoScript cancel-able, made the inoutdiv dynamically scale, told people what a homeserver is, switched to argon2id from sha-3 and sha-512, add a PoW captcha using WASM, make a really long commit message.
If you are still reading this, I admire your dedication. I spent 8 hours and 33 minutes on this commit alone.
2024-07-20 17:12:25 +01:00
displayError ( "What's new in Burgernotes 2.0?\nRestyled client\nAdded changing passwords\nAdded importing notes\nChange the use of CryptoJS to Native AES GCM\nUse Argon2ID for hashing rather than the SHA family\nAdded a Proof-Of-Work CAPTCHA during signup\nMade the signup and login statuses more descriptive\nFixed various bugs and issues\nAdded markdown notes\nAdded support for uploading photos\nImproved privacy policy to be clearer about what is and isn't added\nRemoved some useless uses of cookies and replaced with localStorage\nFixed the privacy policy not redirecting correctly\nAdded a list of native clients\nMade the client support LibreJS and therefore GNU Icecat" )
2024-07-02 18:13:28 +01:00
}
2024-07-30 11:03:05 +01:00
await checknetwork ( )
updateNotes ( )
2024-07-02 18:13:28 +01:00
} )
2024-06-25 19:43:24 +01:00
// @license-end