Implementing upload server
This commit is contained in:
parent
99ef1b0ea0
commit
34ab765a5c
7 changed files with 132 additions and 17 deletions
23
README.md
23
README.md
|
@ -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.
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -5,5 +5,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
server.Init()
|
||||||
|
|
||||||
|
go server.StartUploadServer()
|
||||||
server.StartFtpServer()
|
server.StartFtpServer()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue