github.com/dnutiu/simplFT@v0.0.0-20181023061248-df4b14cdce57/server/commands.go (about)

     1  package server
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"io/ioutil"
     7  	"log"
     8  	"math/rand"
     9  	"os"
    10  	"strconv"
    11  	"strings"
    12  
    13  	"github.com/spf13/viper"
    14  	"github.com/zyxar/image2ascii/ascii"
    15  )
    16  
    17  func randSeq(n int) string {
    18  	var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    19  	b := make([]rune, n)
    20  	for i := range b {
    21  		b[i] = letters[rand.Intn(len(letters))]
    22  	}
    23  	return string(b)
    24  }
    25  
    26  // UploadFile uploads a file to the server
    27  func UploadFile(c Client, filename string) error {
    28  	f, err := os.Create(MakePathFromStringStack(c.Stack()) + filename)
    29  	if err != nil {
    30  		return err
    31  	}
    32  	defer f.Close()
    33  
    34  	io.Copy(f, c.Connection())
    35  
    36  	return nil
    37  }
    38  
    39  // SendASCIIPic sends an image as ascii text to the client.
    40  func SendASCIIPic(c Client, path string) error {
    41  	f, err := os.Open(MakePathFromStringStack(c.Stack()) + path)
    42  	if err != nil {
    43  		log.Println(err)
    44  		return err
    45  	}
    46  	defer f.Close()
    47  	opt := ascii.Options{
    48  		Width:  viper.GetInt("pic.x"),
    49  		Height: viper.GetInt("pic.y"),
    50  		Color:  viper.GetBool("pic.color"),
    51  		Invert: false,
    52  		Flipx:  false,
    53  		Flipy:  false}
    54  
    55  	a, err := ascii.Decode(f, opt)
    56  	if err != nil {
    57  		log.Println(err)
    58  		return err
    59  	}
    60  	_, err = a.WriteTo(c.Connection())
    61  	return err
    62  }
    63  
    64  // GetFile sends the file to the client and returns true if it succeeds and false otherwise.
    65  // it also returns the total number of send bytes.
    66  func GetFile(c Client, path string) (int64, error) {
    67  	fileName, sanitized := sanitizeFilePath(path)
    68  	if sanitized {
    69  		return 0, ErrSlashNotAllowed
    70  	}
    71  
    72  	file, err := os.Open(MakePathFromStringStack(c.Stack()) + fileName)
    73  	if err != nil {
    74  		log.Println(err.Error())
    75  		return 0, err
    76  	}
    77  	defer file.Close()
    78  
    79  	totalSend, err := io.Copy(c.Connection(), file)
    80  
    81  	return totalSend, err
    82  }
    83  
    84  func sanitizeFilePath(path string) (string, bool) {
    85  	var fileName string
    86  	var sanitized bool
    87  	// Make sure the user can't request any files on the system.
    88  	lastForwardSlash := strings.LastIndex(path, "/")
    89  	if lastForwardSlash != -1 {
    90  		// Eliminate the last forward slash i.e ../../asdas will become asdas
    91  		fileName = path[lastForwardSlash+1:]
    92  		sanitized = true
    93  	} else {
    94  		fileName = path
    95  		sanitized = false
    96  	}
    97  	return fileName, sanitized
    98  }
    99  
   100  // ListFiles list the files from path and sends them to the connection
   101  func ListFiles(c Client) error {
   102  
   103  	files, err := ioutil.ReadDir(MakePathFromStringStack(c.Stack()))
   104  	if err != nil {
   105  		return err
   106  	}
   107  
   108  	buffer := bytes.NewBufferString("Directory Mode Size LastModified Name\n")
   109  	for _, f := range files {
   110  		buffer.WriteString(strconv.FormatBool(f.IsDir()) + " " + string(f.Mode().String()) + " " +
   111  			strconv.FormatInt(f.Size(), 10) + " " + f.ModTime().String() + " " + string(f.Name()) + " " + "\n")
   112  	}
   113  
   114  	_, err = c.Connection().Write(buffer.Bytes())
   115  	return err
   116  }
   117  
   118  // ClearScreen cleans the client's screen by sending clear to the terminal.
   119  func ClearScreen(c Client) error {
   120  	// Ansi clear: 1b 5b 48 1b 5b 4a
   121  	// clear | hexdump -C
   122  	var b = []byte{0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x4a}
   123  	_, err := c.Connection().Write(b)
   124  
   125  	return err
   126  }
   127  
   128  // ChangeDirectoryCommand changes the directory to the given directory
   129  func ChangeDirectoryCommand(c Client, directory string) error {
   130  	var err error
   131  	path, sanitized := sanitizeFilePath(directory)
   132  	if sanitized {
   133  		return ErrSlashNotAllowed
   134  	}
   135  
   136  	if path == "." {
   137  		err = nil
   138  	} else if path == ".." {
   139  		err = ChangeDirectoryToPrevious(c.Stack())
   140  	} else {
   141  		err = ChangeDirectory(c.Stack(), path)
   142  	}
   143  
   144  	return err
   145  }
   146  
   147  // ShowHelp writes the help text to the client.
   148  func ShowHelp(c Client) error {
   149  	var helpText = `
   150  The available commands are:
   151  get <filename> - Download the requested filename.
   152  ls             - List the files in the current directory.
   153  cd             - Changes the directory.
   154  clear          - Clear the screen.
   155  exit           - Close the connection with the server.c
   156  pic            - Returns the ascii art of an image. :-)
   157  `
   158  	_, err := c.Connection().Write([]byte(helpText))
   159  
   160  	return err
   161  }