From ff33e649bd6fec535e6b9bf43a55242f9d210e8a Mon Sep 17 00:00:00 2001 From: Urban Wallasch Date: Sat, 6 Apr 2019 20:36:19 +0200 Subject: [PATCH] * Added -I directory index file command line option; default: index.goph. * Dropped -M message command line option. * Refactored send file and send index logic. --- config.go | 17 +++++++----- gogopherd.go | 73 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 62 insertions(+), 28 deletions(-) diff --git a/config.go b/config.go index 8b0564d..2928658 100644 --- 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) } diff --git a/gogopherd.go b/gogopherd.go index 1e6bfe7..bc31d17 100644 --- a/gogopherd.go +++ b/gogopherd.go @@ -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 -- 2.30.2