"net"
"os"
"os/signal"
+ "path"
"path/filepath"
"strings"
"syscall"
}
loc := "\t" + cfg.fqdn + "\t" + cfg.port + "\r\n"
list := ""
- updir, _ := filepath.Split(selector)
if dirname != cfg.docroot {
- list += "1..\t" + updir + loc
+ list += "1..\t" + path.Dir(selector) + loc
}
for _, fi := range fi {
if !cfg.showdot && isDotfile(fi.Name()) {
continue
}
+ reference := path.Join(selector, fi.Name())
fmode := fi.Mode()
fts := humanDate(fi.ModTime())
if fmode.IsDir() {
// create a directory reference
- list += "1" + fi.Name() + " | DIR | " + fts + "\t" + selector + pathSep + fi.Name() + loc
+ list += "1" + fi.Name() + " | DIR | " + fts + "\t" + reference + loc
} else if fmode.IsRegular() {
// create a file reference
- ftype, err := guessFiletype(dirname + pathSep + fi.Name())
- if check(err, "guessFiletype "+dirname+pathSep+fi.Name()) != nil {
+ fpath := filepath.Join(dirname, fi.Name())
+ ftype, err := guessFiletype(fpath)
+ if check(err, "guessFiletype "+fpath) != nil {
continue
}
- list += ftype + fi.Name() + " | " + humanSize(fi.Size()) + " | " + fts + "\t" + selector + pathSep + fi.Name() + loc
+ list += ftype + fi.Name() + " | " + humanSize(fi.Size()) + " | " + fts + "\t" + reference + loc
} else if cfg.fsymln && fmode&os.ModeSymlink != 0 {
// create a reference with attributes matching the link target
- linktarget, _ := os.Readlink(dirname + pathSep + fi.Name())
- if linktarget[:1] != pathSep {
- linktarget = dirname + pathSep + linktarget
+ fpath := filepath.Join(dirname, fi.Name())
+ linktarget, err := os.Readlink(fpath)
+ if check(err, "ReadLink "+fpath) != nil {
+ continue
+ }
+ if !filepath.IsAbs(linktarget) {
+ linktarget = filepath.Join(dirname, linktarget)
+ }
+ tpath, err := canonicalizePath(linktarget)
+ if check(err, "canonicalizePath "+tpath) != nil {
+ continue
+ }
+ lfi, err := os.Stat(tpath)
+ if check(err, "Stat ") != nil {
+ continue
}
- path, err := canonicalizePath(linktarget)
- if check(err, "canonicalizePath "+path) == nil {
- lfi, err := os.Stat(path)
- if check(err, "Stat "+path) == nil {
- fmode := lfi.Mode()
- fts := "[" + humanDate(lfi.ModTime()) + "]"
- if fmode.IsDir() {
- // link points to a directory
- list += "1" + fi.Name() + " | DIR | " + fts + "\t" + selector + pathSep + fi.Name() + loc
- } else if fmode.IsRegular() {
- // link points to a regular file
- ftype, err := guessFiletype(dirname + pathSep + fi.Name())
- if check(err, "guessFiletype "+dirname+pathSep+fi.Name()) != nil {
- continue
- }
- list += ftype + fi.Name() + " | " + humanSize(lfi.Size()) + " | " + fts + "\t" + selector + pathSep + fi.Name() + loc
- }
+ fmode := lfi.Mode()
+ fts := "[" + humanDate(lfi.ModTime()) + "]"
+ if fmode.IsDir() {
+ // link points to a directory
+ list += "1" + fi.Name() + " | DIR | " + fts + "\t" + reference + loc
+ } else if fmode.IsRegular() {
+ // link points to a regular file
+ fpath := filepath.Join(dirname, fi.Name())
+ ftype, err := guessFiletype(fpath)
+ if check(err, "guessFiletype "+fpath) != nil {
+ continue
}
+ list += ftype + fi.Name() + " | " + humanSize(lfi.Size()) + " | " + fts + "\t" + reference + loc
}
} else {
logger.Print("unhandled file mode: ", fi.Name(), " (", fmode.String(), ")")
if err == nil {
tracer.Print("send generated directory index")
if selector == "" {
- selector = pathSep
+ selector = "/"
}
page := "iIndex of " + selector + "\tErr\t" + cfg.fqdn + "\t" + cfg.port + "\r\n"
page += idxpage
req = strings.TrimSpace(req)
tracer.Print("request: '", req, "'")
// canonicalize, and validate referenced path
- path, err := validatePath(cfg.docroot, cfg.docroot+pathSep+req)
- if check(err, "validatePath "+path) != nil {
+ rpath, err := validatePath(cfg.docroot, filepath.Join(cfg.docroot, filepath.FromSlash(req)))
+ if check(err, "validatePath "+rpath) != nil {
sendError(conn, "404")
return
}
- tracer.Print("request path: '", path, "'")
- if !cfg.showdot && isDotfile(path) {
+ tracer.Print("request path: '", rpath, "'")
+ if !cfg.showdot && isDotfile(rpath) {
tracer.Print("skip dotfile")
sendError(conn, "404")
return
}
// check for symbolic link
if !cfg.fsymln {
- fi, err := os.Lstat(path)
- if check(err, "request path Lstat "+path) != nil {
+ fi, err := os.Lstat(rpath)
+ if check(err, "request path Lstat "+rpath) != nil {
sendError(conn, "404")
return
}
}
}
// stat the file
- fi, err := os.Stat(path)
- if check(err, "request path Stat "+path) != nil {
+ fi, err := os.Stat(rpath)
+ if check(err, "request path Stat "+rpath) != nil {
sendError(conn, "404")
return
}
fmode := fi.Mode()
// send appropriate resource (file or directory index)
- selector := path[len(cfg.docroot):]
+ selector := filepath.ToSlash(rpath[len(cfg.docroot):])
tracer.Print("selector: '", selector, "'")
var nbytes int64
if fmode.IsDir() {
err = nil
if cfg.idxpage != "" {
// send directory index file
- idxpath := path + pathSep + cfg.idxpage
+ idxpath := filepath.Join(rpath, cfg.idxpage)
nbytes, err = sendFile(conn, idxpath)
if err != nil {
- tracer.Print("no index file in ", path)
+ tracer.Print("no index file in ", rpath)
}
}
if err != nil {
return
}
// generate and send directory listing
- nbytes, err = sendIndex(conn, path, selector)
+ nbytes, err = sendIndex(conn, rpath, selector)
if check(err, "sendIndex ") != nil {
sendError(conn, "403")
return
}
}
} else if fmode.IsRegular() {
- nbytes, err = sendFile(conn, path)
- if check(err, "sendFile "+path) != nil {
+ nbytes, err = sendFile(conn, rpath)
+ if check(err, "sendFile "+rpath) != nil {
sendError(conn, "404")
return
}