/** * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS-IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import("comet"); import("ejs"); import("etherpad.collab.ace.easysync2.{AttribPool,Changeset}"); import("etherpad.log"); import("etherpad.pad.activepads"); import("etherpad.pad.model"); import("etherpad.pad.padutils"); import("etherpad.pad.padevents"); import("etherpad.pro.pro_padmeta"); import("fastJSON"); import("fileutils.readFile"); import("jsutils.eachProperty"); import("etherpad.collab.server_utils.*"); import("etherpad.collab.collabroom_server"); jimport("java.util.concurrent.ConcurrentHashMap"); jimport("java.lang.System.out.println"); var PADVIEW_ROOMTYPE = 'padview'; var _serverDebug = println;//function(x) {}; // "view id" is either a padId or an ro.id function _viewIdToRoom(padId) { return "padview/"+padId; } function _roomToViewId(roomName) { return roomName.substring(roomName.indexOf("/")+1); } function getRoomCallbacks(roomName, emptyCallbacks) { var callbacks = emptyCallbacks; var viewId = _roomToViewId(roomName); callbacks.handleConnect = function(data) { if (data.userInfo && data.userInfo.userId) { return data.userInfo; } return null; }; callbacks.clientReady = function(newConnection, data) { newConnection.data.lastRev = data.lastRev; collabroom_server.updateRoomConnectionData(newConnection.connectionId, newConnection.data); }; return callbacks; } function updatePadClients(pad) { var padId = pad.getId(); var roId = padIdToReadonly(padId); function update(connection) { updateClient(pad, connection.connectionId); } collabroom_server.getRoomConnections(_viewIdToRoom(padId)).forEach(update); collabroom_server.getRoomConnections(_viewIdToRoom(roId)).forEach(update); } // Get arrays of text lines and attribute lines for a revision // of a pad. function _getPadLines(pad, revNum) { var atext; if (revNum >= 0) { atext = pad.getInternalRevisionAText(revNum); } else { atext = Changeset.makeAText("\n"); } var result = {}; result.textlines = Changeset.splitTextLines(atext.text); result.alines = Changeset.splitAttributionLines(atext.attribs, atext.text); return result; } function updateClient(pad, connectionId) { var conn = collabroom_server.getConnection(connectionId); if (! conn) { return; } var lastRev = conn.data.lastRev; while (lastRev < pad.getHeadRevisionNumber()) { var r = ++lastRev; var author = pad.getRevisionAuthor(r); var lines = _getPadLines(pad, r-1); var wirePool = new AttribPool(); var forwards = pad.getRevisionChangeset(r); var backwards = Changeset.inverse(forwards, lines.textlines, lines.alines, pad.pool()); var forwards2 = Changeset.moveOpsToNewPool(forwards, pad.pool(), wirePool); var backwards2 = Changeset.moveOpsToNewPool(backwards, pad.pool(), wirePool); function revTime(r) { var date = pad.getRevisionDate(r); var s = Math.floor((+date)/1000); //java.lang.System.out.println("time "+r+": "+s); return s; } var msg = {type:"NEW_CHANGES", newRev:r, changeset: forwards2, changesetBack: backwards2, apool: wirePool.toJsonable(), author: author, timeDelta: revTime(r) - revTime(r-1) }; collabroom_server.sendMessage(connectionId, msg); } conn.data.lastRev = pad.getHeadRevisionNumber(); collabroom_server.updateRoomConnectionData(connectionId, conn.data); } function sendMessageToPadConnections(pad, msg) { var padId = pad.getId(); var roId = padIdToReadonly(padId); function update(connection) { collabroom_server.sendMessage(connection.connectionId, msg); } collabroom_server.getRoomConnections(_viewIdToRoom(padId)).forEach(update); collabroom_server.getRoomConnections(_viewIdToRoom(roId)).forEach(update); } function updateUserInfo(pad, userInfo) { var msg = { type:"NEW_AUTHORDATA", author: userInfo.userId, data: {} }; var hasData = false; if ((typeof (userInfo.colorId)) == "number") { msg.data.colorId = userInfo.colorId; hasData = true; } if (userInfo.name) { msg.data.name = userInfo.name; hasData = true; } if (hasData) { sendMessageToPadConnections(pad, msg); } } function broadcastNewRevision(pad, revObj) { var msg = { type:"NEW_SAVEDREV", savedRev: revObj }; delete revObj.ip; // we try not to share info like IP addresses on slider sendMessageToPadConnections(pad, msg); }