Implementing change directory command

This commit is contained in:
Denis-Cosmin Nutiu 2017-11-09 22:39:58 +02:00
parent 8158edf88c
commit da7f4cbfd0
5 changed files with 88 additions and 30 deletions

View file

@ -11,7 +11,10 @@ import (
// GetFile sends the file to the client and returns true if it succeeds and false otherwise.
func GetFile(c Client, path string) (int, error) {
fileName := sanitizeFilePath(path)
fileName, sanitized := sanitizeFilePath(path)
if sanitized {
return 0, ErrSlashNotAllowed
}
stack, ok := c.Stack().(*StringStack)
if !ok {
@ -51,17 +54,20 @@ func readFileData(file *os.File) ([]byte, error) {
return data, nil
}
func sanitizeFilePath(path string) string {
func sanitizeFilePath(path string) (string, bool) {
var fileName string
var sanitized bool
// Make sure the user can't request any files on the system.
lastForwardSlash := strings.LastIndex(path, "/")
if lastForwardSlash != -1 {
// Eliminate the last forward slash i.e ../../asdas will become asdas
fileName = path[lastForwardSlash+1:]
sanitized = true
} else {
fileName = path
sanitized = false
}
return fileName
return fileName, sanitized
}
// ListFiles list the files from path and sends them to the connection
@ -90,13 +96,46 @@ func ListFiles(c Client) error {
return nil
}
// ClearScreen cleans the client's screen by sending clear to the terminal.
func ClearScreen(c Client) error {
// Ansi clear: 1b 5b 48 1b 5b 4a
// clear | hexdump -C
var b = []byte{0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x4a}
_, err := c.Connection().Write(b)
return err
}
// ChangeDirectoryCommand changes the directory to the given directory
func ChangeDirectoryCommand(c Client, directory string) error {
var err error
path, sanitized := sanitizeFilePath(directory)
if sanitized {
return ErrSlashNotAllowed
}
stack, ok := c.Stack().(*StringStack)
if !ok {
return ErrStackCast
}
if path == ".." {
err = ChangeDirectoryToPrevious(stack)
} else {
err = ChangeDirectory(stack, path)
}
return err
}
func ShowHelp(c Client) error {
var helpText = `
The available commands are:
get <filename> - Download the requested filename.
ls - List the files in the current directory.
cd - Changes the directory.
clear - Clear the screen.
exit - Close the connection with the server.
exit - Close the connection with the server.c
`
_, err := c.Connection().Write([]byte(helpText))

View file

@ -44,4 +44,5 @@ 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")
ErrSlashNotAllowed = errors.New("slash is not allowed in file names")
)

View file

@ -25,6 +25,16 @@ func ProcessInput(c Client, text string) error {
thisCommand := commands[0]
switch thisCommand {
case "cd":
err := checkArgumentsLength(commandsLen, 2)
if err != nil {
return &InputError{thisCommand, err}
}
err = ChangeDirectoryCommand(c, commands[1])
if err != nil {
return err
}
case "get":
err := checkArgumentsLength(commandsLen, 2)
if err != nil {
@ -52,11 +62,10 @@ func ProcessInput(c Client, text string) error {
return &InputError{thisCommand, err}
}
// Ansi clear: 1b 5b 48 1b 5b 4a
// clear | hexdump -C
var b = []byte{0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x4a}
c.Connection().Write(b)
err = ClearScreen(c)
if err != nil {
return err
}
case "help":
// Check arguments
err := checkArgumentsLength(commandsLen, 1)

View file

@ -18,17 +18,17 @@ func containsSlash(dir string) bool {
}
// PATH is the constant which should contain the fixed path where the simpleFTP server will run
// This will act like a root cage.
// This will act like a root cage. It must end with a forward slash!
var BasePath = "/Users/denis/GoglandProjects/golangBook/"
// GetPath will return the complete path
func GetPath(stack *StringStack) string {
if stack.IsEmpty() {
return BasePath
}
return BasePath
}
//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 {
@ -56,10 +56,12 @@ func ChangeDirectory(stack *StringStack, directory string) error {
path := MakePathFromStringStack(stack)
fileInfo, err := os.Stat(path)
if err != nil {
stack.Pop()
return err
}
if fileInfo.IsDir() == false {
stack.Pop()
return ErrNotADirectory
}

View file

@ -7,16 +7,6 @@ import (
"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)
@ -25,7 +15,7 @@ func TestMakePathFromStringStack(t *testing.T) {
st.Push("trinity")
path := MakePathFromStringStack(st)
expected := fmt.Sprintf("%s/%s/%s/%s/", BasePath, "first", "folder two", "trinity")
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)
@ -77,6 +67,23 @@ func TestChangeDirectory(t *testing.T) {
}
}
func TestChangeDirectory_InvalidDirectoryIsNotInStack(t *testing.T) {
st := MakeStringStack(1)
err := os.Chdir(BasePath)
if err != nil {
t.Errorf("TestChangeDirectory_InvalidDirectoryIsNotInStack: Step1: %s", err.Error())
}
dirName := string(rand.Intn(10000))
// ignore no such directory error
ChangeDirectory(st, dirName)
if !st.IsEmpty() && st.Top() == dirName {
t.Errorf("TestChangeDirectory: Stack is corrupted because invalid directory remained in stack")
}
}
func TestChangeDirectory_InvalidDirectoryName(t *testing.T) {
st := MakeStringStack(1)
err := ChangeDirectory(st, "some/not/cool/directory/")