From 775601e007c7f1c0d3edb8228e3b1b7d304d34b6 Mon Sep 17 00:00:00 2001 From: Urban Wallasch Date: Fri, 5 Apr 2019 16:04:48 +0200 Subject: [PATCH] * Split source into several files. --- config.go | 86 ++++++++++++++++++++++++++++ gogopherd.go | 156 --------------------------------------------------- util.go | 108 +++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 156 deletions(-) create mode 100644 config.go create mode 100644 util.go diff --git a/config.go b/config.go new file mode 100644 index 0000000..3a91fd9 --- /dev/null +++ b/config.go @@ -0,0 +1,86 @@ +/* + * This file is part of the gogopherd project. + * + * Copyright 2019 Urban Wallasch + * See LICENSE file for more details. + * + */ + +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "os" +) + +var cfg = struct { + iface string + port string + fqdn string + docRoot string + message string + fsymln bool + verbose bool +}{ + iface: "localhost", + port: "7070", + fqdn: "localhost", + docRoot: ".", + message: "", + fsymln: false, + verbose: false, +} + +func initialize() { + help := false + flag.StringVar(&cfg.iface, "i", cfg.iface, "interface to bind to") + flag.StringVar(&cfg.port, "p", cfg.port, "TCP port to listen on") + flag.StringVar(&cfg.fqdn, "f", cfg.fqdn, "fully qualified domain name") + flag.StringVar(&cfg.docRoot, "r", cfg.docRoot, "document root directory") + flag.StringVar(&cfg.message, "M", cfg.message, "index greeter message") + flag.BoolVar(&help, "h", help, "show this help page") + flag.BoolVar(&cfg.fsymln, "s", cfg.fsymln, "follow symbolic links") + flag.BoolVar(&cfg.verbose, "v", cfg.verbose, "produce verbose output") + flag.Parse() + if help { + fmt.Println("Version ", version) + flag.Usage() + os.Exit(1) + } + if 0 != len(flag.Args()) { + fmt.Println("Version ", version) + fmt.Println("unrecognized options: ", flag.Args()) + flag.Usage() + os.Exit(1) + } + + logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) + if cfg.verbose { + tracer = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) + } else { + tracer = log.New(ioutil.Discard, "", 0) + } + pathSep = string(os.PathSeparator) + + var err error + cfg.docRoot, err = canonicalizePath(cfg.docRoot) + checkFatal(err, "canonicalizePath "+cfg.docRoot) + + if cfg.message != "" { + cfg.message = fmt.Sprintf("i%s\t\t\t\r\n", cfg.message) + } + + tracer.Print("Version ", version) + tracer.Print("interface: ", cfg.iface) + tracer.Print("TCP port: ", cfg.port) + tracer.Print("doc root: ", cfg.docRoot) + tracer.Print("fsymlinks: ", cfg.fsymln) + tracer.Print("fqdn: ", cfg.fqdn) + tracer.Print("message: ", cfg.message) + tracer.Print("verbose: ", cfg.verbose) +} + +/* EOF */ diff --git a/gogopherd.go b/gogopherd.go index f3618f1..b193b23 100644 --- a/gogopherd.go +++ b/gogopherd.go @@ -16,172 +16,16 @@ package main import ( "bufio" - "errors" - "flag" "fmt" "io" "io/ioutil" - "log" "net" - "net/http" "os" "path/filepath" "strconv" "strings" ) -var ( - logger *log.Logger - tracer *log.Logger - pathSep string -) - -var cfg = struct { - iface string - port string - fqdn string - docRoot string - message string - fsymln bool - verbose bool -}{ - iface: "localhost", - port: "7070", - fqdn: "localhost", - docRoot: ".", - message: "", - fsymln: false, - verbose: false, -} - -func initialize() { - help := false - flag.StringVar(&cfg.iface, "i", cfg.iface, "interface to bind to") - flag.StringVar(&cfg.port, "p", cfg.port, "TCP port to listen on") - flag.StringVar(&cfg.fqdn, "f", cfg.fqdn, "fully qualified domain name") - flag.StringVar(&cfg.docRoot, "r", cfg.docRoot, "document root directory") - flag.StringVar(&cfg.message, "M", cfg.message, "index greeter message") - flag.BoolVar(&help, "h", help, "show this help page") - flag.BoolVar(&cfg.fsymln, "s", cfg.fsymln, "follow symbolic links") - flag.BoolVar(&cfg.verbose, "v", cfg.verbose, "produce verbose output") - flag.Parse() - if help { - fmt.Println("Version ", version) - flag.Usage() - os.Exit(1) - } - if 0 != len(flag.Args()) { - fmt.Println("Version ", version) - fmt.Println("unrecognized options: ", flag.Args()) - flag.Usage() - os.Exit(1) - } - - logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) - if cfg.verbose { - tracer = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) - } else { - tracer = log.New(ioutil.Discard, "", 0) - } - pathSep = string(os.PathSeparator) - - var err error - cfg.docRoot, err = canonicalizePath(cfg.docRoot) - checkFatal(err, "canonicalizePath "+cfg.docRoot) - - if cfg.message != "" { - cfg.message = fmt.Sprintf("i%s\t\t\t\r\n", cfg.message) - } - - tracer.Print("interface: ", cfg.iface) - tracer.Print("TCP port: ", cfg.port) - tracer.Print("doc root: ", cfg.docRoot) - tracer.Print("fsymlinks: ", cfg.fsymln) - tracer.Print("fqdn: ", cfg.fqdn) - tracer.Print("message: ", cfg.message) - tracer.Print("verbose: ", cfg.verbose) -} - -func checkFatal(err error, msg string) { - if err != nil { - logger.Print(msg, ": ", err.Error()) - os.Exit(1) - } -} - -func check(err error, msg string) error { - if err != nil { - tracer.Print(msg, ": ", err.Error()) - } - return err -} - -func canonicalizePath(path string) (string, error) { - abs, err := filepath.Abs(path) - if check(err, "Abs "+path) != nil { - return path, err - } - return abs, err -} - -func validatePath(root string, path string) (string, error) { - cpath, err := canonicalizePath(path) - if check(err, "canonicalizePath "+path) != nil { - return path, err - } - if len(cpath) < len(root) || cpath[:len(root)] != root { - return cpath, errors.New("Path outside root") - } - return cpath, err -} - -func guessFiletype(path string) (string, error) { - // Open File - f, err := os.Open(path) - if check(err, "Open "+path) != nil { - return "i", err - } - defer f.Close() - // Get the content - buffer := make([]byte, 512) - n, err := f.Read(buffer) - if err != io.EOF && check(err, "Read "+path) != nil { - return "i", err - } - buffer = buffer[:n] - contentType := http.DetectContentType(buffer) - //tracer.Print("Content Type " + path + " == "+ contentType) - shortType := strings.Split(contentType, ";")[0] - genType := strings.Split(shortType, "/")[0] - gopherType := "9" - if shortType == "text/html" { - gopherType = "h" - } else if genType == "text" { - gopherType = "0" - } else if shortType == "image/gif" { - gopherType = "g" - } else if genType == "image" { - gopherType = "I" - } else if genType == "audio" { - gopherType = "s" - } - return gopherType, nil -} - -func humanSize(bytes int64) string { - var units = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"} - ui := 0 - decimals := 1 - if bytes < 1024 { - decimals = 0 - } - var n float64 - for n = float64(bytes); n > 1024; n /= 1024 { - ui = ui + 1 - } - return fmt.Sprintf("%.*f %s", decimals, n, units[ui]) -} - func createIndex(selector string) (string, error) { dirname := cfg.docRoot + selector fi, err := ioutil.ReadDir(dirname) diff --git a/util.go b/util.go new file mode 100644 index 0000000..35f42b5 --- /dev/null +++ b/util.go @@ -0,0 +1,108 @@ +/* + * This file is part of the gogopherd project. + * + * Copyright 2019 Urban Wallasch + * See LICENSE file for more details. + * + */ + +package main + +import ( + "errors" + "fmt" + "io" + "log" + "net/http" + "os" + "path/filepath" + "strings" +) + +var ( + logger *log.Logger + tracer *log.Logger + pathSep string +) + +func checkFatal(err error, msg string) { + if err != nil { + logger.Print(msg, ": ", err.Error()) + os.Exit(1) + } +} + +func check(err error, msg string) error { + if err != nil { + tracer.Print(msg, ": ", err.Error()) + } + return err +} + +func canonicalizePath(path string) (string, error) { + abs, err := filepath.Abs(path) + if check(err, "Abs "+path) != nil { + return path, err + } + return abs, err +} + +func validatePath(root string, path string) (string, error) { + cpath, err := canonicalizePath(path) + if check(err, "canonicalizePath "+path) != nil { + return path, err + } + if len(cpath) < len(root) || cpath[:len(root)] != root { + return cpath, errors.New("Path outside doc root hierarchy") + } + return cpath, err +} + +func guessFiletype(path string) (string, error) { + // Open File + f, err := os.Open(path) + if check(err, "Open "+path) != nil { + return "i", err + } + defer f.Close() + // Get the content + buffer := make([]byte, 512) + n, err := f.Read(buffer) + if err != io.EOF && check(err, "Read "+path) != nil { + return "i", err + } + buffer = buffer[:n] + contentType := http.DetectContentType(buffer) + //tracer.Print("Content Type " + path + " == "+ contentType) + shortType := strings.Split(contentType, ";")[0] + genType := strings.Split(shortType, "/")[0] + gopherType := "9" + if shortType == "text/html" { + gopherType = "h" + } else if genType == "text" { + gopherType = "0" + } else if shortType == "image/gif" { + gopherType = "g" + } else if genType == "image" { + gopherType = "I" + } else if genType == "audio" { + gopherType = "s" + } + return gopherType, nil +} + +func humanSize(bytes int64) string { + var units = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"} + ui := 0 + decimals := 1 + if bytes < 1024 { + decimals = 0 + } + var n float64 + for n = float64(bytes); n > 1024; n /= 1024 { + ui = ui + 1 + } + return fmt.Sprintf("%.*f %s", decimals, n, units[ui]) +} + +/* EOF */ -- 2.30.2