2017-10-20 15:08:25 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2017-10-28 20:40:24 +00:00
|
|
|
"bytes"
|
2017-11-23 09:09:12 +00:00
|
|
|
"io"
|
2017-10-28 20:40:24 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
2017-11-26 21:03:15 +00:00
|
|
|
"math/rand"
|
2017-10-20 15:08:25 +00:00
|
|
|
"os"
|
|
|
|
"strconv"
|
2017-10-28 20:40:24 +00:00
|
|
|
"strings"
|
2017-11-24 20:16:06 +00:00
|
|
|
|
2017-11-24 20:50:23 +00:00
|
|
|
"github.com/spf13/viper"
|
2017-11-24 20:35:59 +00:00
|
|
|
"github.com/zyxar/image2ascii/ascii"
|
2017-10-20 15:08:25 +00:00
|
|
|
)
|
|
|
|
|
2017-11-26 21:03:15 +00:00
|
|
|
func randSeq(n int) string {
|
|
|
|
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
|
|
b := make([]rune, n)
|
|
|
|
for i := range b {
|
|
|
|
b[i] = letters[rand.Intn(len(letters))]
|
|
|
|
}
|
|
|
|
return string(b)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UploadFile uploads a file to the server
|
2017-11-30 22:17:35 +00:00
|
|
|
func UploadFile(c Client, filename string) error {
|
2017-11-26 21:03:15 +00:00
|
|
|
f, err := os.Create(MakePathFromStringStack(c.Stack()) + filename)
|
|
|
|
if err != nil {
|
2017-11-30 22:17:35 +00:00
|
|
|
return err
|
2017-11-26 21:03:15 +00:00
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
2017-11-30 21:28:18 +00:00
|
|
|
io.Copy(f, c.Connection())
|
2017-11-26 21:03:15 +00:00
|
|
|
|
2017-11-30 22:17:35 +00:00
|
|
|
return nil
|
2017-11-26 21:03:15 +00:00
|
|
|
}
|
|
|
|
|
2017-12-16 20:46:55 +00:00
|
|
|
// SendASCIIPic sends an image as ascii text to the client.
|
|
|
|
func SendASCIIPic(c Client, path string) error {
|
2017-11-24 20:16:06 +00:00
|
|
|
f, err := os.Open(MakePathFromStringStack(c.Stack()) + path)
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
2017-11-24 20:35:59 +00:00
|
|
|
opt := ascii.Options{
|
2017-11-24 20:50:23 +00:00
|
|
|
Width: viper.GetInt("pic.x"),
|
|
|
|
Height: viper.GetInt("pic.y"),
|
2017-11-25 13:53:54 +00:00
|
|
|
Color: viper.GetBool("pic.color"),
|
2017-11-24 20:35:59 +00:00
|
|
|
Invert: false,
|
|
|
|
Flipx: false,
|
|
|
|
Flipy: false}
|
|
|
|
|
|
|
|
a, err := ascii.Decode(f, opt)
|
2017-11-24 20:16:06 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
return err
|
|
|
|
}
|
2017-11-24 20:35:59 +00:00
|
|
|
_, err = a.WriteTo(c.Connection())
|
2017-11-24 20:16:06 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-10-20 15:34:16 +00:00
|
|
|
// GetFile sends the file to the client and returns true if it succeeds and false otherwise.
|
2017-11-23 09:09:12 +00:00
|
|
|
// it also returns the total number of send bytes.
|
2017-11-08 20:18:23 +00:00
|
|
|
func GetFile(c Client, path string) (int, error) {
|
2017-11-09 20:39:58 +00:00
|
|
|
fileName, sanitized := sanitizeFilePath(path)
|
|
|
|
if sanitized {
|
|
|
|
return 0, ErrSlashNotAllowed
|
|
|
|
}
|
2017-10-20 15:08:25 +00:00
|
|
|
|
2017-11-23 19:18:20 +00:00
|
|
|
file, err := os.Open(MakePathFromStringStack(c.Stack()) + fileName)
|
2017-10-20 15:08:25 +00:00
|
|
|
if err != nil {
|
2017-11-23 09:09:12 +00:00
|
|
|
log.Println(err.Error())
|
2017-10-20 15:08:25 +00:00
|
|
|
return 0, err
|
|
|
|
}
|
2017-10-28 20:36:57 +00:00
|
|
|
defer file.Close()
|
|
|
|
|
2017-11-23 09:09:12 +00:00
|
|
|
var data = make([]byte, DataBufferSize, DataBufferSize)
|
|
|
|
totalSend := 0
|
|
|
|
for {
|
|
|
|
n, err := file.Read(data)
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
} else if err != nil {
|
|
|
|
return totalSend, err
|
|
|
|
}
|
|
|
|
|
|
|
|
totalSend += n
|
|
|
|
_, err = c.Connection().Write(data)
|
|
|
|
if err != nil {
|
2017-11-24 20:16:06 +00:00
|
|
|
break
|
2017-11-23 09:09:12 +00:00
|
|
|
}
|
2017-10-20 15:08:25 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 09:09:12 +00:00
|
|
|
return totalSend, nil
|
2017-10-28 20:36:57 +00:00
|
|
|
}
|
|
|
|
|
2017-11-09 20:39:58 +00:00
|
|
|
func sanitizeFilePath(path string) (string, bool) {
|
2017-10-28 20:36:57 +00:00
|
|
|
var fileName string
|
2017-11-09 20:39:58 +00:00
|
|
|
var sanitized bool
|
2017-10-28 20:36:57 +00:00
|
|
|
// 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:]
|
2017-11-09 20:39:58 +00:00
|
|
|
sanitized = true
|
2017-10-28 20:36:57 +00:00
|
|
|
} else {
|
|
|
|
fileName = path
|
2017-11-09 20:39:58 +00:00
|
|
|
sanitized = false
|
2017-10-28 20:36:57 +00:00
|
|
|
}
|
2017-11-09 20:39:58 +00:00
|
|
|
return fileName, sanitized
|
2017-10-28 20:36:57 +00:00
|
|
|
}
|
|
|
|
|
2017-10-20 15:08:25 +00:00
|
|
|
// ListFiles list the files from path and sends them to the connection
|
2017-11-08 20:18:23 +00:00
|
|
|
func ListFiles(c Client) error {
|
|
|
|
|
2017-11-23 19:18:20 +00:00
|
|
|
files, err := ioutil.ReadDir(MakePathFromStringStack(c.Stack()))
|
2017-10-20 15:08:25 +00:00
|
|
|
if err != nil {
|
2017-10-28 20:36:57 +00:00
|
|
|
return err
|
2017-10-20 15:08:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
buffer := bytes.NewBufferString("Directory Mode Size LastModified Name\n")
|
|
|
|
for _, f := range files {
|
|
|
|
buffer.WriteString(strconv.FormatBool(f.IsDir()) + " " + string(f.Mode().String()) + " " +
|
|
|
|
strconv.FormatInt(f.Size(), 10) + " " + f.ModTime().String() + " " + string(f.Name()) + " " + "\n")
|
|
|
|
}
|
|
|
|
|
2017-11-08 20:18:23 +00:00
|
|
|
_, err = c.Connection().Write(buffer.Bytes())
|
2017-11-24 20:16:06 +00:00
|
|
|
return err
|
2017-10-20 15:08:25 +00:00
|
|
|
}
|
2017-10-20 15:20:11 +00:00
|
|
|
|
2017-11-09 20:39:58 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2017-11-09 21:03:31 +00:00
|
|
|
if path == "." {
|
|
|
|
err = nil
|
|
|
|
} else if path == ".." {
|
2017-11-23 19:18:20 +00:00
|
|
|
err = ChangeDirectoryToPrevious(c.Stack())
|
2017-11-09 20:39:58 +00:00
|
|
|
} else {
|
2017-11-23 19:18:20 +00:00
|
|
|
err = ChangeDirectory(c.Stack(), path)
|
2017-11-09 20:39:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-12-16 20:46:55 +00:00
|
|
|
// ShowHelp writes the help text to the client.
|
2017-11-08 20:18:23 +00:00
|
|
|
func ShowHelp(c Client) error {
|
2017-10-29 13:01:45 +00:00
|
|
|
var helpText = `
|
2017-10-20 15:20:11 +00:00
|
|
|
The available commands are:
|
|
|
|
get <filename> - Download the requested filename.
|
2017-11-09 20:39:58 +00:00
|
|
|
ls - List the files in the current directory.
|
|
|
|
cd - Changes the directory.
|
|
|
|
clear - Clear the screen.
|
|
|
|
exit - Close the connection with the server.c
|
2017-11-24 20:16:06 +00:00
|
|
|
pic - Returns the ascii art of an image. :-)
|
2017-10-20 15:20:11 +00:00
|
|
|
`
|
2017-11-08 20:18:23 +00:00
|
|
|
_, err := c.Connection().Write([]byte(helpText))
|
2017-10-20 15:20:11 +00:00
|
|
|
|
|
|
|
return err
|
|
|
|
}
|