1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/jappix_ynh.git synced 2024-09-03 19:26:19 +02:00
jappix_ynh/source/app/javascripts/connection.js
titoko@titoko.fr 979b376609 update 1.0.1
2014-03-12 14:52:47 +01:00

926 lines
No EOL
28 KiB
JavaScript

/*
Jappix - An open social platform
These are the connection JS script for Jappix
-------------------------------------------------
License: AGPL
Authors: Valérian Saliou, Maranda
*/
// Bundle
var Connection = (function () {
/**
* Alias of this
* @private
*/
var self = {};
/* Variables */
self.current_session = false;
self.desktop_hash = null;
self.connected = false;
self.reconnect_try = 0;
self.reconnect_timer = 0;
self.resume = false;
/**
* Does the user login
* @public
* @param {string} lNick
* @param {string} lServer
* @param {string} lPass
* @param {string} lResource
* @param {number} lPriority
* @param {boolean} lRemember
* @param {object} loginOpts
* @return {boolean}
*/
self.doLogin = function(lNick, lServer, lPass, lResource, lPriority, lRemember, loginOpts) {
try {
// get optionnal conn handlers
oExtend = loginOpts || {};
// We remove the not completed class to avoid problems
$('#home .loginer input').removeClass('please-complete');
// We add the login wait div
Interface.showGeneralWait();
if(Common.hasWebSocket()) {
// WebSocket supported & configured
con = new JSJaCWebSocketConnection({
httpbase: HOST_WEBSOCKET
});
} else {
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
// Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection
con = new JSJaCHttpBindingConnection({
httpbase: httpbase
});
}
// And we handle everything that happen
self.setupCon(con, oExtend);
// Generate a resource
var random_resource = DataStore.getDB(self.desktop_hash, 'session', 'resource');
if(!random_resource) {
random_resource = lResource + ' (' + (new Date()).getTime() + ')';
}
// We retrieve what the user typed in the login inputs
oArgs = {};
oArgs.domain = $.trim(lServer);
oArgs.username = $.trim(lNick);
oArgs.resource = random_resource;
oArgs.pass = lPass;
oArgs.secure = true;
oArgs.xmllang = XML_LANG;
self.desktop_hash = 'jd.' + hex_md5(oArgs.username + '@' + oArgs.domain);
// Store the resource (for reconnection)
DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource);
// Store session XML in temporary database
self.storeSession(lNick, lServer, lPass, lResource, lPriority, lRemember);
// We store the infos of the user into the data-base
DataStore.setDB(self.desktop_hash, 'priority', 1, lPriority);
// We connect !
con.connect(oArgs);
// Change the page title
Interface.title('wait');
Console.info('Jappix is connecting...');
} catch(e) {
Console.error('Connection.doLogin', e);
// Reset Jappix
Talk.destroy();
// Open an unknown error
Board.openThisError(2);
} finally {
return false;
}
};
/**
* Handles the user registration
* @public
* @return {undefined}
*/
self.handleRegistered = function() {
try {
Console.info('A new account has been registered.');
// We remove the waiting image
Interface.removeGeneralWait();
// Reset the title
Interface.title('home');
// We show the success information
$('#home .registerer .success').fadeIn('fast');
// We quit the session
if(Common.isConnected()) {
self.logout();
}
} catch(e) {
Console.error('Connection.handleRegistered', e);
}
};
/**
* Does the user registration
* @public
* @param {string} username
* @param {string} domain
* @param {string} pass
* @param {string} captcha
* @return {boolean}
*/
self.doRegister = function(username, domain, pass, captcha) {
try {
Console.info('Trying to register an account...');
// We change the registered information text
$('#home .homediv.registerer').append(
'<div class="info success">' +
Common._e("You have been registered, here is your XMPP address:") + ' <b>' + username.htmlEnc() + '@' + domain.htmlEnc() + '</b> - <a href="#">' + Common._e("Login") + '</a>' +
'</div>'
);
// Login link
$('#home .homediv.registerer .success a').click(function() {
return self.doLogin(username, domain, pass, '', '10', false);
});
if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) {
// Show the waiting image
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
// Send request
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
// Error registering
Interface.removeGeneralWait();
Interface.title('home');
// In all case, update CAPTCHA
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
$('#home input.captcha').val('');
// Registration okay
if($(data).find('query status').text() == '1') {
self.handleRegistered();
} else {
// Show error message
var error_message = '';
switch($(data).find('query message').text()) {
case 'CAPTCHA Not Matching':
error_message = Common._e("The security code you entered is invalid. Please retry with another one.");
$('#home input.captcha').focus();
break;
case 'Username Unavailable':
error_message = Common._e("The username you picked is not available. Please try another one.");
$('#home input.nick').focus();
break;
default:
error_message = Common._e("There was an error registering your account. Please retry.");
break;
}
if(error_message)
Errors.show('', error_message, '');
}
});
} else {
try {
oArgs = {};
if(Common.hasWebSocket()) {
// WebSocket supported & configured
con = new JSJaCWebSocketConnection({
httpbase: HOST_WEBSOCKET
});
} else {
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
// Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection
con = new JSJaCHttpBindingConnection({
httpbase: httpbase
});
}
// We setup the connection !
con.registerHandler('onconnect', self.handleRegistered);
con.registerHandler('onerror', Errors.handle);
// We retrieve what the user typed in the register inputs
oArgs = {};
oArgs.domain = $.trim(domain);
oArgs.username = $.trim(username);
oArgs.resource = JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')';
oArgs.pass = pass;
oArgs.register = true;
oArgs.secure = true;
oArgs.xmllang = XML_LANG;
con.connect(oArgs);
// Show the waiting image
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
}
catch(e) {
// Logs errors
Console.error('doRegister', e);
}
}
} catch(e) {
Console.error('Connection.doRegister', e);
} finally {
return false;
}
};
/**
* Does the user anonymous login
* @public
* @return {boolean}
*/
self.doAnonymous = function() {
try {
Console.info('Trying to login anonymously...');
var aPath = '#home .anonymouser ';
var room = $(aPath + '.room').val();
var nick = $(aPath + '.nick').val();
// If the form is correctly completed
if(room && nick) {
// We remove the not completed class to avoid problems
$('#home .anonymouser input').removeClass('please-complete');
// Redirect the user to the anonymous room
window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick;
}
// We check if the form is entirely completed
else {
$(aPath + 'input[type="text"]').each(function() {
var select = $(this);
if(!select.val())
$(document).oneTime(10, function() {
select.addClass('please-complete').focus();
});
else
select.removeClass('please-complete');
});
}
} catch(e) {
Console.error('Connection.doAnonymous', e);
} finally {
return false;
}
};
/**
* Handles the user connected event
* @public
* @return {undefined}
*/
self.handleConnected = function() {
try {
Console.info('Jappix is now connected.');
// Connection markers
self.connected = true;
self.reconnect_try = 0;
self.reconnect_timer = 0;
// We hide the home page
$('#home').hide();
// Any suggest to do before triggering connected event?
Groupchat.suggestCheck();
// Remove the waiting item
Interface.removeGeneralWait();
// Init Jingle
Jingle.init();
} catch(e) {
Console.error('Connection.handleConnected', e);
}
};
/**
* Triggers the connected state
* @public
* @return {undefined}
*/
self.triggerConnected = function() {
try {
// Not resumed?
if(!self.resume) {
// Remember the session?
if(DataStore.getDB(self.desktop_hash, 'remember', 'session'))
DataStore.setPersistent('global', 'session', 1, self.current_session);
// We show the chatting app.
Talk.create();
// We reset the homepage
Home.change('default');
// We get all the other things
self.getEverything();
// Set last activity stamp
DateUtils.last_activity = DateUtils.getTimeStamp();
}
// Resumed
else {
// Send our presence
Presence.sendActions();
// Change the title
Interface.updateTitle();
}
} catch(e) {
Console.error('Connection.triggerConnected', e);
}
};
/**
* Handles the user disconnected event
* @public
* @return {undefined}
*/
self.handleDisconnected = function() {
try {
Console.info('Jappix is now disconnected.');
// Normal disconnection
if(!self.current_session && !self.connected) {
Talk.destroy();
self.desktop_hash = null;
}
} catch(e) {
Console.error('Connection.handleDisconnected', e);
}
};
/**
* Setups the normal connection
* @public
* @param {object} con
* @param {object} oExtend
* @return {undefined}
*/
self.setupCon = function(con, oExtend) {
try {
// Setup connection handlers
con.registerHandler('message', Message.handle);
con.registerHandler('presence', Presence.handle);
con.registerHandler('iq', IQ.handle);
con.registerHandler('onconnect', self.handleConnected);
con.registerHandler('onerror', Errors.handle);
con.registerHandler('ondisconnect', self.handleDisconnected);
// Extended handlers
oExtend = oExtend || {};
jQuery.each(oExtend, function(keywd,funct) {
con.registerHandler(keywd, funct);
});
} catch(e) {
Console.error('Connection.setupCon', e);
}
};
/**
* Logouts from the server
* @public
* @return {boolean}
*/
self.logout = function() {
logout_done = false;
try {
if(Common.isConnected()) {
Console.info('Jappix is disconnecting...');
// Disconnect from the XMPP server
con.disconnect();
logout_done = true;
}
} catch(e) {
Console.error('Connection.logout', e);
} finally {
return logout_done;
}
};
/**
* Terminates the user session
* @public
* @return {undefined}
*/
self.terminate = function() {
try {
if(Common.isConnected()) {
// Clear temporary session storage
self.resetConMarkers();
// Show the waiting item (useful if BOSH is sloooow)
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
// Disconnect from the XMPP server
self.logout();
}
} catch(e) {
Console.error('Connection.terminate', e);
}
};
/**
* Quits a session
* @public
* @param {type} name
* @return {undefined}
*/
self.quit = function() {
try {
if(!Common.isConnected()) {
return;
}
// We show the waiting image
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
// We disconnect from the XMPP server
self.logout();
} catch(e) {
Console.error('Connection.quit', e);
}
};
/**
* Creates the reconnect pane
* @public
* @param {string} mode
* @return {undefined}
*/
self.createReconnect = function(mode) {
try {
Console.error('This is not a normal disconnection, show the reconnect pane...');
// Reconnect pane not yet displayed?
if(!Common.exists('#reconnect')) {
// Blur the focused input/textarea/select
$('input, select, textarea').blur();
// Create the HTML code
var html = '<div id="reconnect" class="lock">' +
'<div class="pane">' +
Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
// Can we cancel reconnection?
if(mode == 'normal')
html += '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>';
html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
'</div></div>';
// Append the code
$('body').append(html);
// Click events
if(mode == 'normal')
$('#reconnect a.finish.cancel').click(function() {
return self.cancelReconnect();
});
$('#reconnect a.finish.reconnect').click(function() {
return self.acceptReconnect(mode);
});
// Try to reconnect automatically after a while
if(self.reconnect_try < 5)
self.reconnect_timer = 5 + (5 * self.reconnect_try);
else
self.reconnect_timer = 120;
// Change the try number
self.reconnect_try++;
// Fire the event!
$('#reconnect a.finish.reconnect').everyTime('1s', function() {
// We can reconnect!
if(self.reconnect_timer === 0)
return self.acceptReconnect(mode);
// Button text
if(self.reconnect_timer <= 10)
$(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')');
// Remove 1 second
self.reconnect_timer--;
});
// Page title
Interface.updateTitle();
}
} catch(e) {
Console.error('Connection.createReconnect', e);
}
};
/**
* Reconnects the user if he was disconnected (network issue)
* @public
* @param {string} mode
* @return {boolean}
*/
self.acceptReconnect = function(mode) {
try {
Console.info('Trying to reconnect the user...');
// Resume marker
self.resume = true;
// Show waiting item
Interface.showGeneralWait();
// Reset some various stuffs
var groupchats = '#page-engine .page-engine-chan[data-type="groupchat"]';
$(groupchats + ' .list .role').hide();
$(groupchats + ' .one-group, ' + groupchats + ' .list .user').remove();
$(groupchats).attr('data-initial', 'false');
// Stop the timer
$('#reconnect a.finish.reconnect').stopTime();
// Remove the reconnect pane
$('#reconnect').remove();
// Try to login again
if(mode == 'normal')
self.loginFromSession(Common.XMLFromString(self.current_session));
else if(mode == 'anonymous')
Anonymous.login(HOST_ANONYMOUS);
} catch(e) {
Console.error('Connection.acceptReconnect', e);
} finally {
return false;
}
};
/**
* Cancel the reconnection of user account (network issue)
* @public
* @return {boolean}
*/
self.cancelReconnect = function() {
try {
Console.info('User has canceled automatic reconnection...');
// Stop the timer
$('#reconnect a.finish.reconnect').stopTime();
// Remove the reconnect pane
$('#reconnect').remove();
// Destroy the talk page
Talk.destroy();
// Renitialize the previous session parameters
self.resetConMarkers();
} catch(e) {
Console.error('Connection.cancelReconnect', e);
} finally {
return false;
}
};
/**
* Clears session reminder database
* @public
* @return {undefined}
*/
self.clearLastSession = function() {
try {
// Clear temporary storage
self.resetConMarkers();
// Clear persistent storage
if($(Common.XMLFromString(DataStore.getPersistent('global', 'session', 1))).find('stored').text() == 'true') {
DataStore.removePersistent('global', 'session', 1);
}
} catch(e) {
Console.error('Connection.clearLastSession', e);
}
};
/**
* Resets the connection markers
* @public
* @return {undefined}
*/
self.resetConMarkers = function() {
try {
self.current_session = false;
self.connected = false;
self.resume = false;
self.reconnect_try = 0;
self.reconnect_timer = 0;
} catch(e) {
Console.error('Connection.resetConMarkers', e);
}
};
/**
* Logins from a saved session
* @public
* @param {string} data
* @return {undefined}
*/
self.loginFromSession = function(data) {
try {
// Select the data
var session = $(data);
// Fire the login event
self.doLogin(
session.find('username').text(),
session.find('domain').text(),
session.find('password').text(),
session.find('resource').text(),
session.find('priority').text(),
false
);
} catch(e) {
Console.error('Connection.loginFromSession', e);
}
};
/**
* Quits a session normally
* @public
* @return {boolean}
*/
self.normalQuit = function() {
try {
// Reset our database
self.clearLastSession();
// We quit the current session
self.quit();
// We show an info
Board.openThisInfo(3);
} catch(e) {
Console.error('Connection.normalQuit', e);
} finally {
return false;
}
};
/**
* Gets all the users stuff
* @public
* @return {undefined}
*/
self.getEverything = function() {
try {
Features.get();
Roster.get();
Privacy.list();
Storage.get(NS_ROSTERNOTES);
} catch(e) {
Console.error('Connection.getEverything', e);
}
};
/**
* Generates session data to store
* @public
* @param {string} lNick
* @param {string} lServer
* @param {string} lPass
* @param {string} lResource
* @param {number} lPriority
* @param {boolean} lRemember
* @return {undefined}
*/
self.storeSession = function(lNick, lServer, lPass, lResource, lPriority, lRemember) {
try {
// Generate a session XML to be stored
session_xml = '<session><stored>true</stored><domain>' + lServer.htmlEnc() + '</domain><username>' + lNick.htmlEnc() + '</username><resource>' + lResource.htmlEnc() + '</resource><password>' + lPass.htmlEnc() + '</password><priority>' + lPriority.htmlEnc() + '</priority></session>';
// Save the session parameters (for reconnect if network issue)
self.current_session = session_xml;
// Remember me?
if(lRemember) {
DataStore.setDB(self.desktop_hash, 'remember', 'session', 1);
}
return session_xml;
} catch(e) {
Console.error('Connection.storeSession', e);
}
};
/**
* Plugin launcher
* @public
* @return {undefined}
*/
self.launch = function() {
try {
$(document).ready(function() {
// Logouts when Jappix is closed
$(window).bind('beforeunload', Connection.terminate);
// Nothing to do when anonymous!
if(Utils.isAnonymous())
return;
// Connection params submitted in URL?
if(XMPPLinks.links_var.u && XMPPLinks.links_var.q) {
// Generate login data
var login_xid = Common.bareXID(Common.generateXID(XMPPLinks.links_var.u, 'chat'));
var login_nick = Common.getXIDNick(login_xid);
var login_server = Common.getXIDHost(login_xid);
var login_pwd = XMPPLinks.links_var.q;
var login_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')';
var login_priority = '10';
var login_remember = 1;
// Must store session?
if(XMPPLinks.links_var.h && (XMPPLinks.links_var.h === '1')) {
// Store session
var session_xml = self.storeSession(login_nick, login_server, login_pwd, login_resource, login_priority, true);
DataStore.setPersistent('global', 'session', 1, session_xml);
// Redirect to a clean URL
document.location.href = './';
} else {
// Hide the homepage
$('#home').hide();
// Show the waiting icon
Interface.showGeneralWait();
// Proceed login
self.doLogin(login_nick, login_server, login_pwd, login_resource, login_priority, login_remember);
}
return;
}
// Try to resume a stored session, if not anonymous
var session = Common.XMLFromString(
DataStore.getPersistent('global', 'session', 1)
);
if($(session).find('stored').text() == 'true') {
// Hide the homepage
$('#home').hide();
// Show the waiting icon
Interface.showGeneralWait();
// Login!
self.loginFromSession(session);
Console.info('Saved session found, resuming it...');
}
// Not connected, maybe a XMPP link is submitted?
else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
Home.change('loginer');
Console.info('A XMPP link is set, switch to login page.');
}
});
} catch(e) {
Console.error('Connection.launch', e);
}
};
/**
* Return class scope
*/
return self;
})();
Connection.launch();