+'use strict';
+
+/* Following function by 80B <wtf@idk.lol>; last updated 2021-08-13 */
+const L = (tag, props = {}, ...kids) => {
+ const el = Object.assign(document.createElement(tag), props);
+ typeof(props.style) === 'object' && Object.assign(el.style, props.style);
+ el.append(...kids);
+ return el;
+};
+
+/* The rest of the file:
+
+ Copyright 2021 Michael D. Lowis <mike@mdlowis.com>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ Local Storage Interface
+*/
+const Data = {
+ get: (k) => JSON.parse(localStorage.getItem(k)),
+ put: (k, v) => localStorage.setItem(k, JSON.stringify(v)),
+ len: () => localStorage.length,
+ key: (i) => localStorage.key(i),
+ clr: () => localStorage.clear(),
+};
+
/*
Chat Client Interface
*/
-const Client = ((state = {keys: {}})=>({
+const Client = ((state = {keys: {}, logs: {}})=>({
init: ()=>{
+ /* scan storage for all keys and logs */
+ for (var i = 0; i < Data.len(); i++) {
+ const name = Data.key(i);
+ const key = name.match(/(.*)\/key$/)
+ const log = name.match(/(.*)\/log\/(\d)$/)
+ if (key) {
+ state.keys[key[1]] = Client.loadKey(key[1], Data.get(name));
+ } else if (log) {
+ state.logs[log[1]] ||= [];
+ state.logs[log[1]][Number(log[2])] = Data.get(name);
+ }
+ }
+
/* connect using keys from storage */
- if (localStorage.privKey && localStorage.pubKey) {
- Client.privKey(localStorage.privKey);
- Client.pubKey(localStorage.pubKey);
+ if (Data.get('keys/priv') && Data.get('keys/pub'))
+ {
+ Client.privKey(Data.get('keys/priv'));
+ Client.pubKey(Data.get('keys/pub'));
Client.connect();
}
- /* load chat logs and contacts */
- // TODO
+
+ // TODO: Populate HTML with active contact's log
},
log: (msg)=>{
},
loadKey: (name, key)=>{
- localStorage[name] = key;
+ Data.put(name, key);
const crypt = new JSEncrypt();
crypt.setKey(key);
return crypt;
},
privKey: (key)=>{
- state.keys.private = Client.loadKey('privKey', key);
+ state.keys.private = Client.loadKey('keys/priv', key);
},
pubKey: (key)=>{
- state.keys.public = Client.loadKey('pubKey', key);
+ state.keys.public = Client.loadKey('keys/pub', key);
},
keysValid: ()=> state.keys.private.decrypt(state.keys.public.encrypt("test")),
return resp.text();
}),
- addContact: (name, cbfn = ()=>{})=>{
+ addContact: (name)=>{
Client.getFile('./keys/' + name).then((key)=>{
state.keys[name] = Client.loadKey(name, key);
- cbfn();
+ contact.appendChild(L('OPTION', { value: name }, name));
});
},
state.conn.onclose = ()=>{
Client.log('DISCONNECT');
- dialog.classList.add("visible");
+// dialog.classList.add("visible");
};
state.conn.onmessage = (event)=>{
Client.getMessage(event.data);
};
- }
+ },
+
+ state: ()=> state
}))();
/*
}
};
-connect.onclick = ()=>{
- public_key.files[0].text()
- .then(key =>{
- Client.pubKey(key);
- return private_key.files[0].text()
- })
- .then(key => {
- Client.privKey(key);
- if (Client.keysValid())
- {
- Client.connect();
- dialog.classList.remove("visible");
- }
- })
+connect.onclick = async ()=>{
+ let pubKey = await public_key.files[0].text();
+ let privKey = await private_key.files[0].text();
+ Client.pubKey(pubKey);
+ Client.privKey(privKey);
+ if (Client.keysValid())
+ {
+ dialog.classList.remove("visible");
+ Client.connect();
+ }
}
addContact.onclick = ()=>{
const name = prompt("Enter name:", "");
- Client.addContact(name, ()=>{
- const el = document.createElement('OPTION');
- el.value = name;
- el.textContent = name;
- contact.appendChild(el);
- });
-}
+ Client.addContact(name);
+};
// Try connecting based on local storage
-(()=>{
- Client.init();
-// Client.addContact("clientA");
-// Client.getMessage("0");
-})();
+(()=>{ Client.init(); })();