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 < Number ( e . id ) ) startmsg = Number ( e . id ) ;
$ . post ( "pubkey.php" , { user : e . user } ) . done ( function ( pk ) {
var res = JSON . parse ( pk ) ;
var key = openpgp . key . readArmored ( res ) ;
if ( ! res || key . err ) {
setTimeout ( get , 10000 ) ;
return error ( "key of receiver not found" , true ) ;
}
var message = openpgp . message . readArmored ( e . msg ) ;
var privkey = privateKey ( ) . keys [ 0 ] ;
if ( privkey . decrypt ( password ) )
openpgp . decryptAndVerifyMessage ( privkey , key . keys , message )
. then ( function ( msg ) {
var message = JSON . parse ( msg . text ) ;
$ ( "#msgs" ) // todo: check msg.signatures[0].valid
. prepend ( '<div id="id' + ( e . id ) + '" class="msg ' +
( e . user == userid ( ) ? "me" : "other" ) +
'"><div class="header">' +
'<span class="date">' +
( new Date ( 1000 * Number ( e . time ) ) ) . toLocaleString ( ) +
'</span><span class="sender">' +
'<a href="javascript:void(0)" onclick="setreceiver(this.innerHTML)">' +
e . user +
'</a></span></div>' +
'<div class="text">' +
message . text +
'</div></div><div class="clear"/>' ) ;
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 ( '<form>' +
' <input placeholder="password for ' + userid ( ) +
'" id="pwd" oninput="setpw(this.value)" type="password" />' +
'</form>' ) ;
}
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 ) ;