Implementing the Path
This commit is contained in:
parent
9ce435af85
commit
143430ff5f
4 changed files with 188 additions and 6 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
85
server/server/path.go
Normal 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
|
||||||
|
}
|
94
server/server/path_test.go
Normal file
94
server/server/path_test.go
Normal 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!")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue