diff --git a/node/handler/PadMessageHandler.js b/node/handler/PadMessageHandler.js index d86528498..588d3118d 100644 --- a/node/handler/PadMessageHandler.js +++ b/node/handler/PadMessageHandler.js @@ -1,6 +1,6 @@ /** - * The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions - */ + * The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions + */ /* * Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd) @@ -61,18 +61,18 @@ var socketio; exports.setSocketIO = function(socket_io) { socketio=socket_io; -} +}; /** * Handles the connection of a new user * @param client the new client */ exports.handleConnect = function(client) -{ +{ //Initalize session2pad and sessioninfos for this new session - session2pad[client.id]=null; + session2pad[client.id]=null; sessioninfos[client.id]={}; -} +}; /** * Kicks all sessions from a pad @@ -89,27 +89,27 @@ exports.kickSessionsFromPad = function(padID) { socketio.sockets.sockets[pad2sessions[padID][i]].json.send({disconnect:"deleted"}); } -} +}; /** * Handles the disconnection of a user * @param client the client that leaves */ exports.handleDisconnect = function(client) -{ +{ //save the padname of this session var sessionPad=session2pad[client.id]; - + //if this connection was already etablished with a handshake, send a disconnect message to the others if(sessioninfos[client.id] && sessioninfos[client.id].author) { var author = sessioninfos[client.id].author; - + //get the author color out of the db authorManager.getAuthorColorId(author, function(err, color) { ERR(err); - + //prepare the notification for the other users on the pad, that this user left var messageToTheOtherUsers = { "type": "COLLABROOM", @@ -123,29 +123,29 @@ exports.handleDisconnect = function(client) } } }; - + //Go trough all user that are still on the pad, and send them the USER_LEAVE message - for(i in pad2sessions[sessionPad]) + for(var i in pad2sessions[sessionPad]) { socketio.sockets.sockets[pad2sessions[sessionPad][i]].json.send(messageToTheOtherUsers); } - }); + }); } - + //Go trough all sessions of this pad, search and destroy the entry of this client - for(i in pad2sessions[sessionPad]) + for(var i in pad2sessions[sessionPad]) { if(pad2sessions[sessionPad][i] == client.id) { - pad2sessions[sessionPad].splice(i, 1); + pad2sessions[sessionPad].splice(i, 1); break; } } - + //Delete the session2pad and sessioninfos entrys of this session - delete session2pad[client.id]; - delete sessioninfos[client.id]; -} + delete session2pad[client.id]; + delete sessioninfos[client.id]; +}; /** * Handles a message from a user @@ -153,8 +153,8 @@ exports.handleDisconnect = function(client) * @param message the message from the client */ exports.handleMessage = function(client, message) -{ - if(message == null) +{ + if(!message) { messageLogger.warn("Message is null!"); return; @@ -164,28 +164,28 @@ exports.handleMessage = function(client, message) messageLogger.warn("Message has no type attribute!"); return; } - + //Check what type of message we get and delegate to the other methodes if(message.type == "CLIENT_READY") { handleClientReady(client, message); } - else if(message.type == "COLLABROOM" && + else if(message.type == "COLLABROOM" && message.data.type == "USER_CHANGES") { handleUserChanges(client, message); } - else if(message.type == "COLLABROOM" && + else if(message.type == "COLLABROOM" && message.data.type == "USERINFO_UPDATE") { handleUserInfoUpdate(client, message); } - else if(message.type == "COLLABROOM" && + else if(message.type == "COLLABROOM" && message.data.type == "CHAT_MESSAGE") { handleChatMessage(client, message); } - else if(message.type == "COLLABROOM" && + else if(message.type == "COLLABROOM" && message.data.type == "CLIENT_MESSAGE" && message.data.payload.type == "suggestUserName") { @@ -196,7 +196,7 @@ exports.handleMessage = function(client, message) { messageLogger.warn("Dropped message, unknown Message Type " + message.type); } -} +}; /** * Handles a Chat Message @@ -209,10 +209,10 @@ function handleChatMessage(client, message) var userId = sessioninfos[client.id].author; var text = message.data.text; var padId = session2pad[client.id]; - + var pad; var userName; - + async.series([ //get the pad function(callback) @@ -238,7 +238,7 @@ function handleChatMessage(client, message) { //save the chat message pad.appendChatMessage(text, userId, time); - + var msg = { type: "COLLABROOM", data: { @@ -249,13 +249,13 @@ function handleChatMessage(client, message) text: text } }; - + //broadcast the chat message to everyone on the pad for(var i in pad2sessions[padId]) { socketio.sockets.sockets[pad2sessions[padId][i]].json.send(msg); } - + callback(); } ], function(err) @@ -273,19 +273,19 @@ function handleChatMessage(client, message) function handleSuggestUserName(client, message) { //check if all ok - if(message.data.payload.newName == null) + if(!message.data.payload.newName) { messageLogger.warn("Dropped message, suggestUserName Message has no newName!"); return; } - if(message.data.payload.unnamedId == null) + if(!message.data.payload.unnamedId) { messageLogger.warn("Dropped message, suggestUserName Message has no unnamedId!"); return; } - + var padId = session2pad[client.id]; - + //search the author and send him this message for(var i in pad2sessions[padId]) { @@ -305,30 +305,30 @@ function handleSuggestUserName(client, message) function handleUserInfoUpdate(client, message) { //check if all ok - if(message.data.userInfo.colorId == null) + if(!message.data.userInfo.colorId) { messageLogger.warn("Dropped message, USERINFO_UPDATE Message has no colorId!"); return; } - + //Find out the author name of this session var author = sessioninfos[client.id].author; - + //Tell the authorManager about the new attributes authorManager.setAuthorColorId(author, message.data.userInfo.colorId); authorManager.setAuthorName(author, message.data.userInfo.name); - + var padId = session2pad[client.id]; - + //set a null name, when there is no name set. cause the client wants it null - if(message.data.userInfo.name == null) + if(!message.data.userInfo.name) { message.data.userInfo.name = null; } - + //The Client don't know about a USERINFO_UPDATE, it can handle only new user_newinfo, so change the message type message.data.type = "USER_NEWINFO"; - + //Send the other clients on the pad the update message for(var i in pad2sessions[padId]) { @@ -349,29 +349,29 @@ function handleUserInfoUpdate(client, message) function handleUserChanges(client, message) { //check if all ok - if(message.data.baseRev == null) + if(message.data.baseRev === null || message.data.baseRev === undefined) { messageLogger.warn("Dropped message, USER_CHANGES Message has no baseRev!"); return; } - if(message.data.apool == null) + if(!message.data.apool) { messageLogger.warn("Dropped message, USER_CHANGES Message has no apool!"); return; } - if(message.data.changeset == null) + if(!message.data.changeset) { messageLogger.warn("Dropped message, USER_CHANGES Message has no changeset!"); return; } - + //get all Vars we need var baseRev = message.data.baseRev; var wireApool = (AttributePoolFactory.createAttributePool()).fromJsonable(message.data.apool); var changeset = message.data.changeset; - + var r, apool, pad; - + async.series([ //get the pad function(callback) @@ -387,13 +387,13 @@ function handleUserChanges(client, message) function(callback) { //ex. _checkChangesetAndPool - + //Copied from Etherpad, don't know what it does exactly try { //this looks like a changeset check, it throws errors sometimes Changeset.checkRep(changeset); - + Changeset.eachAttribNumber(changeset, function(n) { if (! wireApool.getAttrib(n)) { throw "Attribute pool is missing attribute "+n+" for changeset "+changeset; @@ -407,27 +407,27 @@ function handleUserChanges(client, message) client.json.send({disconnect:"badChangeset"}); return; } - + //ex. adoptChangesetAttribs - + //Afaik, it copies the new attributes from the changeset, to the global Attribute Pool changeset = Changeset.moveOpsToNewPool(changeset, wireApool, pad.pool); - + //ex. applyUserChanges apool = pad.pool; r = baseRev; - + //https://github.com/caolan/async#whilst async.whilst( function() { return r < pad.getHeadRevisionNumber(); }, function(callback) { r++; - + pad.getRevisionChangeset(r, function(err, c) { if(ERR(err, callback)) return; - + changeset = Changeset.follow(c, changeset, false, apool); callback(null); }); @@ -440,29 +440,29 @@ function handleUserChanges(client, message) function (callback) { var prevText = pad.text(); - - if (Changeset.oldLen(changeset) != prevText.length) + + if (Changeset.oldLen(changeset) != prevText.length) { console.warn("Can't apply USER_CHANGES "+changeset+" with oldLen " + Changeset.oldLen(changeset) + " to document of length " + prevText.length); client.json.send({disconnect:"badChangeset"}); callback(); return; } - + var thisAuthor = sessioninfos[client.id].author; - + pad.appendRevision(changeset, thisAuthor); - + var correctionChangeset = _correctMarkersInPad(pad.atext, pad.pool); if (correctionChangeset) { pad.appendRevision(correctionChangeset); } - + if (pad.text().lastIndexOf("\n\n") != pad.text().length-2) { var nlChangeset = Changeset.makeSplice(pad.text(), pad.text().length-1, 0, "\n"); pad.appendRevision(nlChangeset); } - + exports.updatePadClients(pad, callback); } ], function(err) @@ -472,29 +472,29 @@ function handleUserChanges(client, message) } exports.updatePadClients = function(pad, callback) -{ +{ //skip this step if noone is on this pad if(!pad2sessions[pad.id]) { callback(); return; } - + //go trough all sessions on this pad async.forEach(pad2sessions[pad.id], function(session, callback) { var lastRev = sessioninfos[session].rev; - + //https://github.com/caolan/async#whilst //send them all new changesets async.whilst( - function (){ return lastRev < pad.getHeadRevisionNumber()}, + function (){ return lastRev < pad.getHeadRevisionNumber(); }, function(callback) { var author, revChangeset; - + var r = ++lastRev; - + async.parallel([ function (callback) { @@ -517,7 +517,7 @@ exports.updatePadClients = function(pad, callback) ], function(err) { if(ERR(err, callback)) return; - + if(author == sessioninfos[session].author) { socketio.sockets.sockets[session].json.send({"type":"COLLABROOM","data":{type:"ACCEPT_COMMIT", newRev:r}}); @@ -528,20 +528,20 @@ exports.updatePadClients = function(pad, callback) var wireMsg = {"type":"COLLABROOM","data":{type:"NEW_CHANGES", newRev:r, changeset: forWire.translated, apool: forWire.pool, - author: author}}; - + author: author}}; + socketio.sockets.sockets[session].json.send(wireMsg); } - + callback(null); }); }, callback ); - + sessioninfos[session].rev = pad.getHeadRevisionNumber(); - },callback); -} + },callback); +}; /** * Copied from the Etherpad Source Code. Don't know what this methode does excatly... @@ -570,7 +570,7 @@ function _correctMarkersInPad(atext, apool) { } } - if (badMarkers.length == 0) { + if (badMarkers.length === 0) { return null; } @@ -586,7 +586,7 @@ function _correctMarkersInPad(atext, apool) { } /** - * Handles a CLIENT_READY. A CLIENT_READY is the first message from the client to the server. The Client sends his token + * Handles a CLIENT_READY. A CLIENT_READY is the first message from the client to the server. The Client sends his token * and the pad it wants to enter. The Server answers with the inital values (clientVars) of the pad * @param client the client that send this message * @param message the message from the client @@ -630,7 +630,7 @@ function handleClientReady(client, message) securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject) { if(ERR(err, callback)) return; - + //access was granted if(statusObject.accessStatus == "grant") { @@ -640,10 +640,10 @@ function handleClientReady(client, message) //no access, send the client a message that tell him why else { - client.json.send({accessStatus: statusObject.accessStatus}) + client.json.send({accessStatus: statusObject.accessStatus}); } }); - }, + }, //get all authordata of this new user function(callback) { @@ -692,7 +692,7 @@ function handleClientReady(client, message) function(callback) { var authors = pad.getAllAuthors(); - + async.parallel([ //get all author data out of the database function(callback) @@ -719,8 +719,8 @@ function handleClientReady(client, message) }); } ], callback); - - + + }, function(callback) { @@ -735,33 +735,33 @@ function handleClientReady(client, message) } } } - + //Save in session2pad that this session belonges to this pad var sessionId=String(client.id); session2pad[sessionId] = message.padId; - + //check if there is already a pad2sessions entry, if not, create one if(!pad2sessions[message.padId]) { pad2sessions[message.padId] = []; } - + //Saves in pad2sessions that this session belongs to this pad pad2sessions[message.padId].push(sessionId); - + //prepare all values for the wire var atext = Changeset.cloneAText(pad.atext); var attribsForWire = Changeset.prepareForWire(atext.attribs, pad.pool); var apool = attribsForWire.pool.toJsonable(); atext.attribs = attribsForWire.translated; - + //check if abiword is avaiable - var abiwordAvailable = settings.abiword != null ? "yes" : "no"; - if(settings.abiword != null && os.type().indexOf("Windows") != -1) + var abiwordAvailable = settings.abiword = null ? "yes" : "no"; + if(settings.abiword && os.type().indexOf("Windows") != -1) { abiwordAvailable = "withoutPDF"; } - + var clientVars = { "accountPrivs": { "maxRevisions": 100 @@ -798,20 +798,20 @@ function handleClientReady(client, message) "fullWidth": false, "hideSidebar": false }, - "abiwordAvailable": abiwordAvailable, + "abiwordAvailable": abiwordAvailable, "hooks": {} - } - + }; + //Add a username to the clientVars if one avaiable - if(authorName != null) + if(authorName) { clientVars.userName = authorName; } - + if(sessioninfos[client.id] !== undefined) { //This is a reconnect, so we don't have to send the client the ClientVars again - if(message.reconnect == true) + if(message.reconnect) { //Save the revision in sessioninfos, we take the revision from the info the client send to us sessioninfos[client.id].rev = message.client_rev; @@ -824,11 +824,11 @@ function handleClientReady(client, message) //Save the revision in sessioninfos sessioninfos[client.id].rev = pad.getHeadRevisionNumber(); } - + //Save the revision and the author id in sessioninfos sessioninfos[client.id].author = author; } - + //prepare the notification for the other users on the pad, that this user joined var messageToTheOtherUsers = { "type": "COLLABROOM", @@ -842,18 +842,18 @@ function handleClientReady(client, message) } } }; - + //Add the authorname of this new User, if avaiable - if(authorName != null) + if(authorName) { messageToTheOtherUsers.data.userInfo.name = authorName; } - + //Run trough all sessions of this pad async.forEach(pad2sessions[message.padId], function(sessionID, callback) { var sessionAuthorName, sessionAuthorColorId; - + async.series([ //get the authorname & colorId function(callback) @@ -866,7 +866,7 @@ function handleClientReady(client, message) if(ERR(err, callback)) return; sessionAuthorColorId = value; callback(); - }) + }); }, function(callback) { @@ -875,10 +875,10 @@ function handleClientReady(client, message) if(ERR(err, callback)) return; sessionAuthorName = value; callback(); - }) + }); } ],callback); - }, + }, function (callback) { //Jump over, if this session is the connection session @@ -886,7 +886,7 @@ function handleClientReady(client, message) { //Send this Session the Notification about the new user socketio.sockets.sockets[sessionID].json.send(messageToTheOtherUsers); - + //Send the new User a Notification about this other user var messageToNotifyTheClientAboutTheOthers = { "type": "COLLABROOM", @@ -904,7 +904,7 @@ function handleClientReady(client, message) client.json.send(messageToNotifyTheClientAboutTheOthers); } } - ], callback); + ], callback); }, callback); } ],function(err)