Просмотр исходного кода

Merge pull request #48 from sharelatex/bg-check-incoming-hash

check incoming hash when present
Brian Gough 7 лет назад
Родитель
Сommit
68e7b9c4e9
1 измененных файлов с 13 добавлено и 1 удалено
  1. 13 1
      services/document-updater/app/coffee/ShareJsUpdateManager.coffee

+ 13 - 1
services/document-updater/app/coffee/ShareJsUpdateManager.coffee

@@ -6,6 +6,7 @@ Keys = require "./UpdateKeys"
 {EventEmitter} = require "events"
 {EventEmitter} = require "events"
 util = require "util"
 util = require "util"
 RealTimeRedisManager = require "./RealTimeRedisManager"
 RealTimeRedisManager = require "./RealTimeRedisManager"
+crypto = require "crypto"
 
 
 ShareJsModel:: = {}
 ShareJsModel:: = {}
 util.inherits ShareJsModel, EventEmitter
 util.inherits ShareJsModel, EventEmitter
@@ -22,7 +23,8 @@ module.exports = ShareJsUpdateManager =
 	applyUpdate: (project_id, doc_id, update, lines, version, callback = (error, updatedDocLines) ->) ->
 	applyUpdate: (project_id, doc_id, update, lines, version, callback = (error, updatedDocLines) ->) ->
 		logger.log project_id: project_id, doc_id: doc_id, update: update, "applying sharejs updates"
 		logger.log project_id: project_id, doc_id: doc_id, update: update, "applying sharejs updates"
 		jobs = []
 		jobs = []
-
+		# record the update version before it is modified
+		incomingUpdateVersion = update.version
 		# We could use a global model for all docs, but we're hitting issues with the
 		# We could use a global model for all docs, but we're hitting issues with the
 		# internal state of ShareJS not being accessible for clearing caches, and
 		# internal state of ShareJS not being accessible for clearing caches, and
 		# getting stuck due to queued callbacks (line 260 of sharejs/server/model.coffee)
 		# getting stuck due to queued callbacks (line 260 of sharejs/server/model.coffee)
@@ -42,6 +44,10 @@ module.exports = ShareJsUpdateManager =
 			logger.log project_id: project_id, doc_id: doc_id, error: error, "applied update"
 			logger.log project_id: project_id, doc_id: doc_id, error: error, "applied update"
 			model.getSnapshot doc_key, (error, data) =>
 			model.getSnapshot doc_key, (error, data) =>
 				return callback(error) if error?
 				return callback(error) if error?
+				# only check hash when present and no other updates have been applied 
+				if update.hash? and incomingUpdateVersion == version
+					ourHash = ShareJsUpdateManager._computeHash(data.snapshot)
+					return callback(new Error("Invalid hash")) if ourHash != update.hash
 				docLines = data.snapshot.split(/\r\n|\n|\r/)
 				docLines = data.snapshot.split(/\r\n|\n|\r/)
 				callback(null, docLines, data.v, model.db.appliedOps[doc_key] or [])
 				callback(null, docLines, data.v, model.db.appliedOps[doc_key] or [])
 
 
@@ -53,3 +59,9 @@ module.exports = ShareJsUpdateManager =
 	_sendOp: (project_id, doc_id, op) ->
 	_sendOp: (project_id, doc_id, op) ->
 		RealTimeRedisManager.sendData {project_id, doc_id, op}
 		RealTimeRedisManager.sendData {project_id, doc_id, op}
 
 
+	_computeHash: (content) ->
+		return crypto.createHash('sha1')
+			.update("blob " + content.length + "\x00")
+			.update(content, 'utf8')
+			.digest('hex')
+