Path = require("path")
fs = require("fs")
Settings = require("settings-sharelatex")
logger = require("logger-sharelatex")
url = require "url"

module.exports = ForbidSymlinks = (staticFn, root, options) ->
	expressStatic = staticFn root, options
	basePath = Path.resolve(root)
	return (req, res, next) ->
		path = url.parse(req.url)?.pathname
		# check that the path is of the form /project_id_or_name/path/to/file.log
		if result = path.match(/^\/?([a-zA-Z0-9_-]+)\/(.*)/)
			project_id = result[1]
			file = result[2]
		else
			logger.warn path: path, "unrecognized file request"
			return res.sendStatus(404)
		# check that the file does not use a relative path
		for dir in file.split('/')
			if dir == '..'
				logger.warn path: path, "attempt to use a relative path"
				return res.sendStatus(404)
		# check that the requested path is normalized
		requestedFsPath = "#{basePath}/#{project_id}/#{file}"
		if requestedFsPath != Path.normalize(requestedFsPath)
				logger.error path: requestedFsPath, "requestedFsPath is not normalized"
				return res.sendStatus(404)
		# check that the requested path is not a symlink
		fs.realpath requestedFsPath, (err, realFsPath)->
			if err?
				if err.code == 'ENOENT'
					return res.sendStatus(404)
				else
					logger.error err:err, requestedFsPath:requestedFsPath, realFsPath:realFsPath, path: req.params[0], project_id: req.params.project_id, "error checking file access"
					return res.sendStatus(500)
			else if requestedFsPath != realFsPath
				logger.warn requestedFsPath:requestedFsPath, realFsPath:realFsPath, path: req.params[0], project_id: req.params.project_id, "trying to access a different file (symlink), aborting"
				return res.sendStatus(404)
			else
				expressStatic(req, res, next)