Implementing upload server

This commit is contained in:
Denis-Cosmin Nutiu 2017-11-26 23:03:15 +02:00
parent 99ef1b0ea0
commit 34ab765a5c
7 changed files with 132 additions and 17 deletions

View file

@ -11,6 +11,12 @@ The server accepts the following commands:
//todo //todo
#### The upload server
If the upload server is running, the user will be able to put files
on the **absoluteServePath**. After the file is uploaded successfully,
if the timeout is not reached, the user will get back the filename.
#### Sending commands via netcat #### Sending commands via netcat
To grab a file the following command can be send: To grab a file the following command can be send:
@ -32,13 +38,19 @@ Sample Configuration File:
``` ```
{ {
"address": "localhost", "address": "localhost",
"port": "8080", "port": 8080,
"maxDirDepth": 30, "maxDirDepth": 30,
"absoluteServePath": "/Users/denis/Dropbox/Pictures/CuteAvatars", "absoluteServePath": "/Users/denis/Dropbox/Pictures/CuteAvatars",
"pic": { "pic": {
"color": false, "color": true,
"x": 0, "x": 197,
"y": 0 "y": 50
},
"upload": {
"enabled": false,
"timeout": 5,
"address": "localhost",
"port": 8081
} }
} }
``` ```
@ -53,7 +65,8 @@ The **config.json** file contains the following settings:
4. absoluteServePath - The path from where to serve the files. 4. absoluteServePath - The path from where to serve the files.
5. pic - The X and Y max size for the pic command. A value of 0 means original size 5. pic - The X and Y max size for the pic command. A value of 0 means original size.
6. upload - Settings for the upload server.
If one of the settings are changed, the server will reload the configuration. If one of the settings are changed, the server will reload the configuration.
Except for the absoluteServePath. Except for the absoluteServePath.

View file

@ -5,14 +5,60 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
"math/rand"
"os" "os"
"strconv" "strconv"
"strings" "strings"
"bufio"
"time"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/zyxar/image2ascii/ascii" "github.com/zyxar/image2ascii/ascii"
) )
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
func UploadFile(c Client) (string, error) {
input := bufio.NewScanner(c.Connection())
start := time.Now()
timeout := time.Duration(viper.GetInt("upload.timeout")) * time.Second
var filename = randSeq(10)
var _, err = os.Stat(MakePathFromStringStack(c.Stack()) + filename)
// Make sure that the filename is random.
for !os.IsNotExist(err) {
filename = randSeq(10)
_, err = os.Stat(MakePathFromStringStack(c.Stack()) + filename)
}
f, err := os.Create(MakePathFromStringStack(c.Stack()) + filename)
if err != nil {
return filename, err
}
defer f.Close()
for input.Scan() {
if time.Since(start) >= timeout {
log.Println(c.Connection().RemoteAddr().String() + " has reached timeout!")
break
}
f.WriteString(input.Text() + "\n")
}
return filename, nil
}
// SendAsciiPic sends an image as ascii text to the client. // SendAsciiPic sends an image as ascii text to the client.
func SendAsciiPic(c Client, path string) error { func SendAsciiPic(c Client, path string) error {
f, err := os.Open(MakePathFromStringStack(c.Stack()) + path) f, err := os.Open(MakePathFromStringStack(c.Stack()) + path)

View file

@ -28,17 +28,20 @@ func loadConfigFromFile() error {
// setDefaultConfiguration will set the default configuration settings. // setDefaultConfiguration will set the default configuration settings.
func setDefaultConfiguration() { func setDefaultConfiguration() {
viper.SetDefault("address", "localhost") viper.SetDefault("address", "localhost")
viper.SetDefault("port", "8080") viper.SetDefault("port", 8080)
viper.SetDefault("configPath", ConfigPath) viper.SetDefault("configPath", ConfigPath)
viper.SetDefault("maxDirDepth", 30) viper.SetDefault("maxDirDepth", 30)
viper.SetDefault("absoluteServePath", "./") viper.SetDefault("absoluteServePath", "./")
viper.SetDefault("pic.x", 0) viper.SetDefault("pic.x", 0)
viper.SetDefault("pic.y", 0) viper.SetDefault("pic.y", 0)
viper.SetDefault("pic.color", false) viper.SetDefault("pic.color", false)
viper.SetDefault("upload.enabled", false)
viper.SetDefault("upload.address", "localhost")
viper.SetDefault("upload.port", 8081)
} }
// InitializedConfiguration initializes the configuration for the application. // InitializeConfiguration initializes the configuration for the application.
func InitializedConfiguration(callback func(e fsnotify.Event)) { func InitializeConfiguration() {
flag.StringVar(&ConfigPath, "config", ".", "Set the location of the config file.") flag.StringVar(&ConfigPath, "config", ".", "Set the location of the config file.")
flag.Parse() flag.Parse()
@ -46,5 +49,8 @@ func InitializedConfiguration(callback func(e fsnotify.Event)) {
loadConfigFromFile() loadConfigFromFile()
viper.WatchConfig() viper.WatchConfig()
viper.OnConfigChange(callback) }
func ConfigChangeCallback(cb func(event fsnotify.Event)) {
viper.OnConfigChange(cb)
} }

View file

@ -8,15 +8,15 @@ import (
func TestLoadConfigFromFile(t *testing.T) { func TestLoadConfigFromFile(t *testing.T) {
// SetDefaultConfiguration must be called BEFORE LoadConfigFromFile. // SetDefaultConfiguration must be called BEFORE LoadConfigFromFile.
InitializedConfiguration() InitializeConfiguration()
Address := viper.GetString("address") Address := viper.GetString("address")
if Address == "" { if Address == "" {
t.Error("TestLoadConfigFromFile: Can't get Address!") t.Error("TestLoadConfigFromFile: Can't get Address!")
} }
Port := viper.GetString("port") Port := viper.GetInt("port")
if Port == "" { if Port == 0 {
t.Error("TestLoadConfigFromFile: Can't get Port!") t.Error("TestLoadConfigFromFile: Can't get Port!")
} }

View file

@ -88,18 +88,21 @@ func HandleConnection(client Client) {
log.Println(client.Connection().RemoteAddr(), "has disconnected.") log.Println(client.Connection().RemoteAddr(), "has disconnected.")
} }
func StartFtpServer() { func Init() {
config.InitializedConfiguration(func(e fsnotify.Event) { config.InitializeConfiguration()
log.Println("Configuration reloaded!") config.ConfigChangeCallback(func(event fsnotify.Event) {
log.Println("Configuration reloaded successfully!")
}) })
}
func StartFtpServer() {
Addr := viper.GetString("address") Addr := viper.GetString("address")
Port := viper.GetString("port") Port := viper.GetInt("port")
DirDepth := viper.GetInt("maxDirDepth") DirDepth := viper.GetInt("maxDirDepth")
BasePath = viper.GetString("absoluteServePath") BasePath = viper.GetString("absoluteServePath")
// Start the server // Start the server
listener, err := net.Listen("tcp", Addr+":"+Port) listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", Addr, Port))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -122,3 +125,45 @@ func StartFtpServer() {
go HandleConnection(&client) go HandleConnection(&client)
} }
} }
func StartUploadServer() {
if viper.GetBool("upload.enabled") == false {
log.Println("Uploading not enabled. To enable modify the config file and restart the server")
return
}
Addr := viper.GetString("upload.address")
Port := viper.GetInt("upload.port")
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", Addr, Port))
if err != nil {
log.Fatal(err)
}
log.Println("Upload server running on:", Addr, "port", Port)
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
client := FTPClient{}
client.SetStack(MakeStringStack(1))
client.SetConnection(conn)
log.Println(conn.RemoteAddr().String() + " is uploading something.")
filename, err := UploadFile(&client)
if err == nil {
io.WriteString(conn, filename)
} else {
log.Print(conn.RemoteAddr().String())
log.Println(err)
}
log.Println(conn.RemoteAddr().String() + "'s upload finished.")
}
}

View file

@ -14,6 +14,8 @@ func TestMakePathFromStringStack(t *testing.T) {
st.Push("folder two") st.Push("folder two")
st.Push("trinity") st.Push("trinity")
BasePath = "./"
path := MakePathFromStringStack(st) 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")

View file

@ -5,5 +5,8 @@ import (
) )
func main() { func main() {
server.Init()
go server.StartUploadServer()
server.StartFtpServer() server.StartFtpServer()
} }