var password = null; // password, only stored temporary, until reload var username = null; // username, only used during registration var filecontent = new Array(); // temporary storage for attachments function error(data, stay) { $("#status").fadeOut("slow", function() { $("#status").addClass("error") $("#status").removeClass("notice") $("#status").removeClass("success") if (data) { if (typeof data == 'string') { $("#status").html(data); console.log("error: "+data); } else { $("#status").html('error'); console.log("error: "+JSON.stringify(data)); } } else { $("#status").html('error'); console.log("error"); } $("#status").fadeIn("slow"); if (!stay) setTimeout(start, 5000); }); } function notice(text) { $("#status").fadeOut("slow", function() { $("#status").addClass("notice") $("#status").removeClass("error") $("#status").removeClass("success") if (text) { $("#status").html(text); console.log("notice: "+text); } else { $("#status").html(''); console.log("notice"); } $("#status").fadeIn("slow"); }); } function success(text) { $("#status").fadeOut("slow", function() { $("#status").addClass("success") $("#status").removeClass("error") $("#status").removeClass("notice") if (text) { $("#status").html(text); console.log("success: "+text); } else { $("#status").html(''); console.log("success"); } $("#status").fadeIn("slow"); }); } function status(text, msg) { $("#main").fadeOut("slow", function() { $("#main").html(text); success(msg); $("#main").fadeIn("slow", function() { $("form input:first-child").focus(); }) }); } function checkuser(user) { $("#register").submit(function(event) { return false; }); $.post("checknewuser.php", {user: user}) .done(function(res) { username=JSON.parse(res); if (!username||username.length<1) username=null; $("#createuser").prop("disabled", !(username && password)); if (username) { if (password) success("user is ready to be created"); else notice("user name is available, please set password"); } else notice("user name is not available"); }).fail(function(res) { username=null; $("#createuser").prop("disabled", !(username && password)); error(res); }); } function checkpwd(pwd, pwd2) { $("#register").submit(function(event) { return false; }); if (pwd==pwd2) password=pwd; else password=null; if (!password||password.length<1) password=null; $("#createuser").prop("disabled", !(username && password)); if (password) { if (username) success("user is ready to be created"); else notice("password matches, please chose a valid user name"); } else notice("passwords don't match"); } function checkpartner(user) { $("#chat").submit(function(event) { return false; }); $.post("checknewuser.php", {user: user}) .done(function(res) { if (JSON.parse(res)) { notice("receiver does not exist"); $("#send").prop("disabled", true); return; } $("#send").prop("disabled", false); success("receiver exists"); }).fail(function(res) { notice("cannot connect to server: "+res); $("#send").prop("disabled", true); }); } function createNewUser(user, pwd) { status("generate keys"); openpgp.generateKeyPair({ numBits: 1024, userId: user, passphrase: pwd }).then(function(keyPair) { success("keys generated"); localStorage.pubKey = keyPair.publicKeyArmored; localStorage.privKey = keyPair.privateKeyArmored; login(); }).catch(function(e) { error(e); }); } function publicKey() { if (typeof localStorage.pubKey == 'undefined') return null; return openpgp.key.readArmored(localStorage.pubKey); } function privateKey() { if (typeof localStorage.privKey == 'undefined') return null; return openpgp.key.readArmored(localStorage.privKey); } function userid() { if (!publicKey() || publicKey().keys.length < 1 || publicKey().keys[0].getUserIds().length < 1) return null return publicKey().keys[0].getUserIds()[0]; } function clearmessage() { filecontent = new Array(); $('#preview').empty(); $("#msg").val(""); notice("message cleared"); } function attachments(files, id) { if (files) files.forEach(function(file) { //if (file.content.length<1000000) { var img = document.createElement('img'); img.src = 'data:'+file.type+';base64,' + file.content; $(id).append(img); //} }); } function fileupload(evt) { if (!window.FileReader) return error("your browser dows not support file upload", true); for (var i=0, f; f=evt.target.files[i]; ++i) { var file = f; var reader = new FileReader(); reader.onload = function(evt) { if (evt.target.error) return error("error reading file", true); if (evt.target.readyState==0) return notice("waiting for data ..."); if (evt.target.readyState==1) return notice("loading data ..."); var base64 = btoa(evt.target.result); filecontent.push({type: file.type, content: base64}); if (file.type.match('^image/')) { var img = document.createElement('img'); img.src = 'data:'+file.type+';base64,' + base64; $("#preview").append(img); success('image of type '+file.type+' is ready to be sent'); } else { success('file of type '+file.type+' is ready to be sent'); } } reader.readAsBinaryString(file); } } function setreceiver(name) { $("#recv").val(name); checkpartner(name); $("#msg").focus(); } var startmsg = 0; // number of last downloaded message function get() { var beeped = false; $.post("get.php", {start: startmsg}).done(function(res) { var msgs = JSON.parse(res); if (msgs) { msgs.forEach(function(e) { if (startmsg
'+ ''+ (new Date(1000*Number(e.time))).toLocaleString()+ ''+ ''+ e.user+ '
'+ '
'+ message.text+ '
'); attachments(message.files, '#id'+e.id+' .text'); $('#id'+e.id).emoticonize(); if (!beeped) (new Audio("A-Tone-His_Self-1266414414.mp3")) .play(); beeped = true; }) .catch(function(e) { // not for me }); }).fail(function(e) { error("get sender's key from server failed", true); }); }); } }).fail(function(e) { error("get messages failed") }); setTimeout(get, 10000); } function sendmessage(recv, txt) { notice("1/3 preparing message ..."); $("#message").fadeOut("slow"); $.post("pubkey.php", {user: recv}).done(function(pk) { var res=JSON.parse(pk); var key=openpgp.key.readArmored(res); if (!res||key.err) { $("#message").fadeIn("slow"); error("key of receiver not found", true); return; } var privkey = privateKey().keys[0]; privkey.decrypt(password); var message = JSON.stringify({text: txt, files: filecontent}); notice("2/3 encrypting message ..."); openpgp.signAndEncryptMessage(key.keys.concat(publicKey().keys), privkey, message) .then(function(msg) { notice("3/3 sending message ..."); $.post("send.php", {user: userid(), msg: msg}) .done(function(res) { if (JSON.parse(res)) { $("#message").fadeIn("slow"); clearmessage(); success("message sent"); } else { $("#message").fadeIn("slow"); error("error sending message", true); } }) .fail(error); }) .catch(function(e) { $("#message").fadeIn("slow"); error("encryption of message failed", true); }); }).fail(function(e) { $("#message").fadeIn("slow"); error("get receiver's key from server failed", true); }); $("#message").fadeIn("slow"); } function setpw(pwd) { if (privateKey().keys[0].decrypt(pwd)) { password = pwd; chat(); } } function getpwd() { status('
'+ ' '+ '
'); } function chat() { if (!password) return getpwd(); $.ajax({url: "chat.html", success: function(res) { status(res); setTimeout(get, 2000); }}).fail(error); } function login() { status("login ..."); $.post("login.php", {user: userid(), pubkey: localStorage.pubKey}, function(res) { if (JSON.parse(res)) { status("logged in ...", "successfully logged in"); chat(); } else { error("login failed"); } }).fail(function(e) { error(e); }); } function newuser() { status("new user ..."); $.ajax({url: "newuser.html", success: function(res) { status(res); }}).fail(error); } function start() { try { status("Starting up ..."); if (!userid()) { newuser(); } else { login(); } } catch (m) { error(m); } } $(start);