Implementing the Path

This commit is contained in:
Denis-Cosmin Nutiu 2017-10-29 18:59:03 +02:00
parent 9ce435af85
commit 143430ff5f
4 changed files with 188 additions and 6 deletions

View file

@ -10,15 +10,11 @@ import (
"strings" "strings"
) )
// PATH is the constant which should contain the fixed path where the simpleFTP server will run
// This will act like a root cage.
const PATH = "/Users/denis/GoglandProjects/golangBook/GoRoutines/"
// GetFile sends the file to the client and returns true if it succeeds and false otherwise. // GetFile sends the file to the client and returns true if it succeeds and false otherwise.
func GetFile(c net.Conn, path string) (int, error) { func GetFile(c net.Conn, path string) (int, error) {
fileName := sanitizeFilePath(path) fileName := sanitizeFilePath(path)
file, err := os.Open(PATH + fileName) file, err := os.Open(BasePath + fileName)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return 0, err return 0, err
@ -66,7 +62,7 @@ func sanitizeFilePath(path string) string {
// ListFiles list the files from path and sends them to the connection // ListFiles list the files from path and sends them to the connection
func ListFiles(c net.Conn) error { func ListFiles(c net.Conn) error {
files, err := ioutil.ReadDir(PATH) files, err := ioutil.ReadDir(BasePath)
if err != nil { if err != nil {
return err return err
} }

View file

@ -37,3 +37,10 @@ var (
StackOverflowError = StackError{"StackOverflowError", errors.New("stack capacity exceeded")} StackOverflowError = StackError{"StackOverflowError", errors.New("stack capacity exceeded")}
StackUnderflowError = StackError{"StackUnderflowError", errors.New("stack is empty")} StackUnderflowError = StackError{"StackUnderflowError", errors.New("stack is empty")}
) )
// PathErrors
var (
ErrInvalidDirectoryName = errors.New("names should not contain / character")
ErrNotADirectory = errors.New("file name is not a valid directory")
ErrAlreadyAtBaseDirectory = errors.New("can't go past beyond root directory")
)

85
server/server/path.go Normal file
View file

@ -0,0 +1,85 @@
package server
// The Path module should work with the stack by providing functions that update the stack
// with information that helps keeping track of the directories that the clients use.
import (
"bytes"
"os"
)
func containsSlash(dir string) bool {
for _, c := range dir {
if c == '/' {
return true
}
}
return false
}
// PATH is the constant which should contain the fixed path where the simpleFTP server will run
// This will act like a root cage.
var BasePath = "/Users/denis/GoglandProjects/golangBook/"
// GetPath will return the complete path
func GetPath(stack *StringStack) string {
if stack.IsEmpty() {
return BasePath
}
return BasePath
}
// MakePathFromStringStack gets a StringStack and makes a path.
func MakePathFromStringStack(stack *StringStack) string {
var buffer bytes.Buffer
buffer.WriteString(BasePath)
if BasePath[len(BasePath)-1] != '/' {
buffer.WriteString("/")
}
for i := 0; i < stack.Size(); i++ {
buffer.WriteString(stack.Items()[i] + "/")
}
return buffer.String()
}
// ChangeDirectory changes the current working directory with respect to BasePath
func ChangeDirectory(stack *StringStack, directory string) error {
if containsSlash(directory) == true {
return ErrInvalidDirectoryName
}
stack.Push(directory)
path := MakePathFromStringStack(stack)
fileInfo, err := os.Stat(path)
if err != nil {
return err
}
if fileInfo.IsDir() == false {
return ErrNotADirectory
}
// The last 9 bits represent the Unix perms format rwxrwxrwx
perms := fileInfo.Mode().Perm()
// The user has permission to view the directory
if (perms&1 != 0) && (perms&(1<<2) != 0) || (perms&(1<<6) != 0) && (perms&(1<<8) != 0) {
return nil
}
stack.Pop()
return os.ErrPermission
}
// ChangeDirectoryToPrevious changes the current working directory to the previous one,
// doesn't go past the BasePath
func ChangeDirectoryToPrevious(stack *StringStack) error {
if stack.IsEmpty() {
return ErrAlreadyAtBaseDirectory
}
stack.Pop()
return nil
}

View file

@ -0,0 +1,94 @@
package server
import (
"fmt"
"math/rand"
"os"
"testing"
)
func TestGetPath_StackIsEmpty(t *testing.T) {
st := MakeStringStack(1)
path := GetPath(st)
if path != BasePath {
t.Errorf("TestGetPath: Base path is not returned when stack is empty.")
}
}
func TestMakePathFromStringStack(t *testing.T) {
st := MakeStringStack(5)
st.Push("first")
st.Push("folder two")
st.Push("trinity")
path := MakePathFromStringStack(st)
expected := fmt.Sprintf("%s/%s/%s/%s/", BasePath, "first", "folder two", "trinity")
if path != expected {
t.Errorf("TestMakePathFromStringStack: Returned an invalid path! Want %s Got %s", expected, path)
}
}
func TestMakePathFromStringStack_StackIsEmpty(t *testing.T) {
st := MakeStringStack(1)
path := MakePathFromStringStack(st)
expected := BasePath
if BasePath[len(BasePath)-1] != '/' {
expected += "/"
}
if path != expected {
t.Errorf("TestMakePathFromStringStack: Returned an invalid path!")
}
}
func TestChangeDirectory(t *testing.T) {
st := MakeStringStack(1)
err := os.Chdir(BasePath)
if err != nil {
t.Errorf("TestChangeDirectory: Step1: %s", err.Error())
}
dirName := string(rand.Intn(10000))
err = os.Mkdir(dirName, os.FileMode(0522))
if err != nil {
t.Errorf("TestChangeDirectory: Step2: %s", err.Error())
}
err = ChangeDirectory(st, dirName)
if err != nil {
t.Errorf("TestChangeDirectory: Step3: %s", err.Error())
}
err = os.Chdir(BasePath)
if err != nil {
t.Errorf("TestChangeDirectory: Step4: %s", err.Error())
}
err = os.Remove(dirName)
if err != nil {
t.Errorf("TestChangeDirectory: Step5: %s", err.Error())
}
}
func TestChangeDirectory_InvalidDirectoryName(t *testing.T) {
st := MakeStringStack(1)
err := ChangeDirectory(st, "some/not/cool/directory/")
if err != ErrInvalidDirectoryName {
t.Error("TestChangeDirectory: Changed directory to something containing the '/' character!")
}
}
func TestChangeDirectoryToPrevious_StackIsEmpty(t *testing.T) {
st := MakeStringStack(1)
err := ChangeDirectoryToPrevious(st)
if err != ErrAlreadyAtBaseDirectory {
t.Error("TestChangeDirectoryToPrevious: Stack is empty and no error occured!")
}
}