* Added -I directory index file command line option; default: index.goph.
authorUrban Wallasch <urban.wallasch@freenet.de>
Sat, 6 Apr 2019 18:36:19 +0000 (20:36 +0200)
committerUrban Wallasch <urban.wallasch@freenet.de>
Sat, 6 Apr 2019 18:36:19 +0000 (20:36 +0200)
* Dropped -M message command line option.
* Refactored send file and send index logic.

config.go
gogopherd.go

index 8b0564d425d0116e0105f29d71d7ddd5ccdc5071..29286582baa8d2ef779b61b399e597b337a1acc6 100644 (file)
--- a/config.go
+++ b/config.go
@@ -12,6 +12,8 @@ import (
        "flag"
        "fmt"
        "os"
+       "path/filepath"
+       "strings"
 )
 
 var cfg = struct {
@@ -19,7 +21,7 @@ var cfg = struct {
        port    string
        fqdn    string
        docRoot string
-       message string
+       dirIdx  string
        fsymln  bool
        showdot bool
        noidx   bool
@@ -29,7 +31,7 @@ var cfg = struct {
        port:    "7070",
        fqdn:    "localhost",
        docRoot: ".",
-       message: "",
+       dirIdx:  "index.goph",
        fsymln:  false,
        showdot: false,
        noidx:   false,
@@ -42,7 +44,7 @@ func initialize() {
        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.StringVar(&cfg.dirIdx, "I", cfg.dirIdx, "directory index page")
        flag.BoolVar(&help, "h", help, "show this help page")
        flag.BoolVar(&cfg.fsymln, "s", cfg.fsymln, "follow symbolic links")
        flag.BoolVar(&cfg.showdot, "d", cfg.showdot, "allow access to dotfiles")
@@ -67,19 +69,20 @@ func initialize() {
        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)
+       cfg.dirIdx = filepath.Base(strings.TrimSpace(cfg.dirIdx))
+       if cfg.dirIdx == "." || cfg.dirIdx == pathSep {
+               cfg.dirIdx = ""
        }
 
        tracer.Print("Version ", version)
+       tracer.Print("fqdn:      ", cfg.fqdn)
        tracer.Print("interface: ", cfg.iface)
        tracer.Print("TCP port:  ", cfg.port)
        tracer.Print("doc root:  ", cfg.docRoot)
+       tracer.Print("dir index: ", cfg.dirIdx)
        tracer.Print("fsymlinks: ", cfg.fsymln)
        tracer.Print("showdot:   ", cfg.showdot)
        tracer.Print("noidx:     ", cfg.noidx)
-       tracer.Print("fqdn:      ", cfg.fqdn)
-       tracer.Print("message:   ", cfg.message)
        tracer.Print("verbose:   ", cfg.verbose)
 }
 
index 1e6bfe7f417004389147db2fe78a0e365a298d27..bc31d17013fd7802666e78e0ccf78a8318cdc871 100644 (file)
@@ -24,8 +24,7 @@ import (
        "strings"
 )
 
-func createIndex(selector string) (string, error) {
-       dirname := cfg.docRoot + selector
+func createIndex(dirname string, selector string) (string, error) {
        fi, err := ioutil.ReadDir(dirname)
        if check(err, "Readdir "+dirname) != nil {
                return "", err
@@ -84,6 +83,35 @@ func createIndex(selector string) (string, error) {
        return list, error(nil)
 }
 
+func sendIndex(conn net.Conn, path string, selector string) (int64, error) {
+       var nbytes int
+       nbytes = 0
+       diridx, err := createIndex(path, selector)
+       if err == nil {
+               if selector == "" {
+                       selector = pathSep
+               }
+               page := ""
+               // TODO append banner
+               page += "iIndex of " + selector + "\tErr\t" + cfg.fqdn + "\t" + cfg.port + "\r\n"
+               page += diridx
+               // TODO append footer
+               nbytes, err = conn.Write([]byte(page))
+       }
+       return int64(nbytes), err
+}
+
+func sendFile(conn net.Conn, path string) (int64, error) {
+       var nbytes int64
+       nbytes = 0
+       file, err := os.Open(path)
+       if err == nil {
+               defer file.Close()
+               nbytes, err = io.Copy(conn, file)
+       }
+       return nbytes, err
+}
+
 func replyErr(conn net.Conn, msg string) {
        tracer.Print("sending error reply: " + msg)
        s := "3Gopher Meditation: " + msg + "\tErr\t" + cfg.fqdn + "\t" + cfg.port + "\r\n"
@@ -140,31 +168,34 @@ func handleRequest(conn net.Conn) {
        tracer.Print("selector: '", selector, "'")
        var nbytes int64
        if fmode.IsDir() {
-               if cfg.noidx {
-                       replyErr(conn, "403")
-                       return
-               }
-               diridx, err := createIndex(selector)
-               if check(err, "makeIndex "+path) != nil {
-                       replyErr(conn, "404")
-                       return
+               err = nil
+               if cfg.dirIdx != "" {
+                       // send directory index file
+                       idxpath := path + pathSep + cfg.dirIdx
+                       nbytes, err = sendFile(conn, idxpath)
+                       if err != nil {
+                               tracer.Print("no index file in " + path)
+                       }
                }
-               nb, err := conn.Write([]byte(cfg.message + diridx))
-               if check(err, "Write") != nil {
-                       return
+               if err != nil {
+                       // failed to send directory index file
+                       if cfg.noidx {
+                               replyErr(conn, "403")
+                               return
+                       }
+                       // generate and send directory listing
+                       nbytes, err = sendIndex(conn, path, selector)
+                       if check(err, "sendIndex ") != nil {
+                               replyErr(conn, "403")
+                               return
+                       }
                }
-               nbytes = int64(nb)
        } else if fmode.IsRegular() {
-               file, err := os.Open(path)
-               if check(err, "Open "+path) != nil {
+               nbytes, err = sendFile(conn, path)
+               if check(err, "sendFile "+path) != nil {
                        replyErr(conn, "404")
                        return
                }
-               defer file.Close()
-               nbytes, err = io.Copy(conn, file)
-               if check(err, "Copy "+path) != nil {
-                       return
-               }
        } else {
                replyErr(conn, "404")
                return