2012-04-13 17:05:16 +02:00
function jappixmini _addon _xor ( str1 , str2 ) {
if ( str1 . length != str2 . length ) throw "not same length" ;
encoded = "" ;
for ( i = 0 ; i < str1 . length ; i ++ ) {
var a = str1 . charCodeAt ( i ) ;
var b = str2 . charCodeAt ( i ) ;
var c = a ^ b ;
encoded += String . fromCharCode ( c ) ;
}
return encoded ;
}
function jappixmini _addon _set _client _secret ( password ) {
2012-04-14 18:23:42 +02:00
if ( ! password ) return ;
salt1 = "h8doCRekWto0njyQohKpdx6BN0UTyC6N" ;
salt2 = "jdX8OwFC1kWAq3s9uOyAcE8g3UNNO5t3" ;
client _secret1 = str _sha1 ( salt1 + password ) ;
client _secret2 = str _sha1 ( salt2 + password ) ;
client _secret = client _secret1 + client _secret2 ;
2012-04-15 23:19:37 +02:00
setPersistent ( 'jappix-mini' , 'client-secret' , client _secret ) ;
2012-04-14 18:23:42 +02:00
console . log ( "client secret set" ) ;
2012-04-13 17:05:16 +02:00
}
2012-04-15 22:57:25 +02:00
function jappixmini _addon _get _client _secret ( callback ) {
2012-04-15 23:19:37 +02:00
client _secret = getPersistent ( 'jappix-mini' , 'client-secret' ) ;
2012-04-13 17:05:16 +02:00
if ( client _secret === null ) {
2012-04-15 22:57:25 +02:00
div = document . getElementById ( "#jappixmini-password-query-div" ) ;
if ( ! div ) {
div = $ ( '<div id="jappixmini-password-query-div" style="position:fixed;padding:1em;background-color:#F00;color:#fff;top:50px;left:50px;">Retype your Friendica password for chatting:<br></div>' ) ;
input = $ ( '<input type="password" id="jappixmini-password-query-input">' )
div . append ( input ) ;
button = $ ( '<input type="button" value="OK" id="jappixmini-password-query-button">' ) ;
div . append ( button ) ;
$ ( "body" ) . append ( div ) ;
}
2012-04-13 17:05:16 +02:00
button . click ( function ( ) {
2012-04-15 22:57:25 +02:00
password = $ ( "#jappixmini-password-query-input" ) . val ( ) ;
2012-04-13 17:05:16 +02:00
jappixmini _addon _set _client _secret ( password ) ;
div . remove ( ) ;
2012-04-15 22:57:25 +02:00
2012-04-15 23:19:37 +02:00
client _secret = getPersistent ( 'jappix-mini' , 'client-secret' ) ;
2012-04-15 22:57:25 +02:00
callback ( client _secret ) ;
2012-04-13 17:05:16 +02:00
} ) ;
}
2012-04-15 22:57:25 +02:00
else {
callback ( client _secret ) ;
}
2012-04-13 17:05:16 +02:00
}
2012-04-15 22:57:25 +02:00
function jappixmini _addon _encrypt _password ( password , callback ) {
jappixmini _addon _get _client _secret ( function ( client _secret ) {
// add \0 to password until it has the same length as secret
if ( password . length > client _secret . length - 1 ) throw "password too long" ;
while ( password . length < client _secret . length ) {
password += "\0" ;
}
2012-04-13 17:05:16 +02:00
2012-04-15 22:57:25 +02:00
// xor password with secret
encrypted _password = jappixmini _addon _xor ( client _secret , password ) ;
2012-04-13 17:05:16 +02:00
2012-04-15 22:57:25 +02:00
encrypted _password = encodeURI ( encrypted _password )
callback ( encrypted _password ) ;
} ) ;
2012-04-13 17:05:16 +02:00
}
2012-04-15 22:57:25 +02:00
function jappixmini _addon _decrypt _password ( encrypted _password , callback ) {
2012-04-13 17:05:16 +02:00
encrypted _password = decodeURI ( encrypted _password ) ;
2012-04-15 22:57:25 +02:00
jappixmini _addon _get _client _secret ( function ( client _secret ) {
// xor password with secret
password = jappixmini _addon _xor ( client _secret , encrypted _password ) ;
2012-04-13 17:05:16 +02:00
2012-04-15 22:57:25 +02:00
// remove \0
first _null = password . indexOf ( "\0" )
2012-04-16 23:39:21 +02:00
if ( first _null == - 1 ) throw "Decrypted password does not contain \\0" ;
2012-04-15 22:57:25 +02:00
password = password . substr ( 0 , first _null ) ;
2012-04-13 17:05:16 +02:00
2012-04-15 22:57:25 +02:00
callback ( password ) ;
} ) ;
2012-04-13 17:05:16 +02:00
}
function jappixmini _manage _roster ( contacts , autoapprove , autosubscribe ) {
// listen for subscriptions
con . registerHandler ( 'presence' , function ( presence ) {
var type = presence . getType ( ) ;
if ( type != "subscribe" ) return ;
var from = fullXID ( getStanzaFrom ( presence ) ) ;
var xid = bareXID ( from ) ;
approve = true ;
2012-04-14 18:23:42 +02:00
if ( ( ! autoapprove ) || contacts [ xid ] === undefined )
2012-04-13 17:05:16 +02:00
approve = confirm ( "Accept " + xid + " for chat?" ) ;
if ( approve ) {
2012-04-14 18:23:42 +02:00
acceptSubscribe ( xid , contacts [ xid ] ) ;
console . log ( "Accepted " + xid + " for chat." ) ;
2012-04-13 17:05:16 +02:00
}
} ) ;
// autosubscribe
2012-04-16 01:04:45 +02:00
if ( ! autosubscribe ) return ;
var get _roster = new JSJaCIQ ( ) ;
get _roster . setType ( 'get' ) ;
get _roster . setQuery ( NS _ROSTER ) ;
con . send ( get _roster , function ( iq ) {
var handleXML = iq . getQuery ( ) ;
// filter out contacts that are already in the roster
$ ( handleXML ) . find ( 'item' ) . each ( function ( ) {
xid = $ ( this ) . attr ( "jid" ) ;
name = $ ( this ) . attr ( "name" ) ;
subscription = $ ( this ) . attr ( "subscription" ) ;
console . log ( xid + " " + subscription ) ;
// ignore accounts not in the list
if ( contacts [ xid ] === undefined ) return ;
// TODO: add to Friendica group
// TODO: unblock and authorize if necessary
// remove from list
delete contacts [ xid ] ;
} ) ;
// go through remaining contacts
for ( var xid in contacts ) { if ( ! contacts . hasOwnProperty ( xid ) ) continue ;
// subscribe
var presence = new JSJaCPresence ( ) ;
presence . setTo ( xid ) ;
presence . setType ( "subscribe" ) ;
con . send ( presence ) ;
console . log ( "subscribed to " + xid ) ;
// add to roster
var iq = new JSJaCIQ ( ) ;
iq . setType ( 'set' ) ;
var iqQuery = iq . setQuery ( NS _ROSTER ) ;
var item = iqQuery . appendChild ( iq . buildNode ( 'item' , { 'xmlns' : NS _ROSTER , 'jid' : xid } ) ) ;
item . setAttribute ( 'name' , contacts [ xid ] ) ;
item . appendChild ( iq . buildNode ( 'group' , { 'xmlns' : NS _ROSTER } , "Friendica" ) ) ;
con . send ( iq ) ;
console . log ( "added to roster " + xid ) ;
2012-04-13 17:05:16 +02:00
}
2012-04-16 01:04:45 +02:00
} ) ;
2012-04-13 17:05:16 +02:00
}
2012-04-15 12:20:53 +02:00
function jappixmini _addon _subscribe ( ) {
if ( ! window . con ) {
alert ( "Not connected." ) ;
return ;
}
xid = prompt ( "Jabber address" ) ;
sendSubscribe ( xid , "subscribe" ) ;
}
2012-04-16 21:16:24 +02:00
function jappixmini _addon _start ( server , username , proxy , bosh , encrypted , password , nickname , contacts , autoapprove , autosubscribe ) {
2012-04-15 22:57:25 +02:00
handler = function ( password ) {
// check if settings have changed, reinitialize jappix mini if this is the case
settings _identifier = str _sha1 ( server ) ;
settings _identifier += str _sha1 ( username ) ;
settings _identifier += str _sha1 ( bosh ) ;
settings _identifier += str _sha1 ( password ) ;
settings _identifier += str _sha1 ( nickname ) ;
saved _identifier = getDB ( "jappix-mini" , "settings_identifier" ) ;
if ( saved _identifier != settings _identifier ) removeDB ( 'jappix-mini' , 'dom' ) ;
setDB ( "jappix-mini" , "settings_identifier" , settings _identifier ) ;
2012-04-16 21:16:24 +02:00
// set HOST_BOSH
if ( proxy )
HOST _BOSH = proxy + "?host_bosh=" + encodeURI ( bosh ) ;
else
HOST _BOSH = bosh ;
2012-04-15 22:57:25 +02:00
// start jappix mini
MINI _NICKNAME = nickname ;
2012-04-16 21:16:24 +02:00
LOCK _HOST = "off" ;
2012-04-15 23:13:37 +02:00
console . log ( "launchMini" ) ;
2012-04-15 22:57:25 +02:00
launchMini ( true , false , server , username , password ) ;
2012-04-16 23:38:00 +02:00
// increase priority over other Jabber clients
priority = 101 ;
sendPresence ( null , null , priority ) ;
2012-04-16 21:16:24 +02:00
jappixmini _manage _roster ( contacts , autoapprove , autosubscribe )
2012-04-15 22:57:25 +02:00
}
// decrypt password if necessary
2012-04-15 12:20:53 +02:00
if ( encrypted )
2012-04-15 22:57:25 +02:00
jappixmini _addon _decrypt _password ( password , handler ) ;
else
handler ( password ) ;
2012-04-13 17:05:16 +02:00
}