11package org .codeoverflow .chatoverflow .connector .actor
22
33import java .io .{File , PrintWriter }
4- import java .nio .file .{ Files , Paths }
4+ import java .nio .file .Files
55
66import akka .actor .Actor
77import org .codeoverflow .chatoverflow .connector .actor .FileSystemActor ._
88
9+ import scala .annotation .tailrec
910import scala .io .Source
1011
1112/**
@@ -30,20 +31,20 @@ class FileSystemActor extends Actor {
3031 override def receive : Receive = {
3132 case LoadFile (pathInResources) =>
3233 try {
33- sender ! Some (Source .fromFile(new File (dataFolder, pathInResources)).mkString)
34+ sender ! Some (Source .fromFile(s " $dataFilePath${fixPath( pathInResources)} " ).mkString)
3435 } catch {
3536 case _ : Exception => None
3637 }
3738 case LoadBinaryFile (pathInResources) =>
3839 try {
39- sender ! Some (Files .readAllBytes(new File (dataFolder, pathInResources).toPath))
40+ sender ! Some (Files .readAllBytes(fixPath( pathInResources).toPath))
4041 } catch {
4142 case e : Exception => e.printStackTrace()
4243 None
4344 }
4445 case SaveFile (pathInResources, content) =>
4546 try {
46- val writer = new PrintWriter (new File (dataFolder, pathInResources))
47+ val writer = new PrintWriter (fixPath( pathInResources))
4748 writer.write(content)
4849 writer.close()
4950 sender ! true
@@ -52,18 +53,36 @@ class FileSystemActor extends Actor {
5253 }
5354 case SaveBinaryFile (pathInResources, content) =>
5455 try {
55- Files .write(new File (dataFolder, pathInResources).toPath, content)
56+ Files .write(fixPath( pathInResources).toPath, content)
5657 sender ! true
5758 } catch {
5859 case _ : Exception => sender ! false
5960 }
6061 case CreateDirectory (folderName) =>
6162 try {
62- sender ! new File (dataFolder, folderName).mkdir()
63+ sender ! fixPath( folderName).mkdir()
6364 } catch {
6465 case _ : Exception => sender ! false
6566 }
6667 }
68+
69+ private def fixPath (path : String ): File = {
70+ val fixedPath = new File (dataFolder, path).getCanonicalFile
71+ val dataCanonical = dataFolder.getCanonicalFile
72+ @ tailrec def insideDataFolder (path : File ): Boolean = {
73+ val parent = Option (path.getParentFile)
74+ if (parent.isEmpty) {
75+ false
76+ } else if (parent.get.equals(dataCanonical)) {
77+ true
78+ } else {
79+ insideDataFolder(parent.get)
80+ }
81+ }
82+ if (! insideDataFolder(fixedPath))
83+ throw new SecurityException (s " file access is restricted to resource folder ( ${dataFolder.getCanonicalPath}) " )
84+ fixedPath
85+ }
6786}
6887
6988object FileSystemActor {
0 commit comments