aboutsummaryrefslogtreecommitdiff
path: root/autoindex.go
diff options
context:
space:
mode:
authorJulian Hurst <ark@mansus.space>2022-12-08 18:34:25 +0100
committerJulian Hurst <ark@mansus.space>2022-12-08 18:34:25 +0100
commit238d7a12de4ad095c297f214a76438110798208b (patch)
tree104f42f9f4a1bfc8b3a32723091a229e384e50a4 /autoindex.go
downloadautoindex-238d7a12de4ad095c297f214a76438110798208b.tar.gz
Initial commit
Diffstat (limited to 'autoindex.go')
-rw-r--r--autoindex.go270
1 files changed, 270 insertions, 0 deletions
diff --git a/autoindex.go b/autoindex.go
new file mode 100644
index 0000000..6a388a6
--- /dev/null
+++ b/autoindex.go
@@ -0,0 +1,270 @@
+package main
+
+import (
+ "fmt"
+ "flag"
+ "archive/tar"
+ "compress/gzip"
+ "log"
+ "net/http"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "html/template"
+ "io"
+ "io/ioutil"
+ "time"
+ "strings"
+)
+
+const pwdlen int = 32
+var salt []byte = nil
+
+type IndexHandler struct {
+ docPath string
+ binPath string
+}
+
+type File struct {
+ Info os.FileInfo
+ Path string
+}
+
+func format(t time.Time) string {
+ return t.Format("2006-01-02 15:04")
+}
+
+func (handler IndexHandler) writeDirToTar(tw *tar.Writer, file os.FileInfo, name string) {
+ //hdr := &tar.Header{
+ //Name: name,
+ //Mode: int64(file.Mode()),
+ //ModTime: file.ModTime(),
+ //Typeflag: tar.TypeDir,
+ //}
+ //if err := tw.WriteHeader(hdr); err != nil {
+ //log.Fatal(err)
+ //}
+ p := filepath.Join(handler.docPath, name)
+ fileInfos, err := ioutil.ReadDir(p)
+ if err != nil {
+ panic(err)
+ }
+ for _, info := range fileInfos {
+ path := filepath.Join(name, info.Name())
+ path = strings.TrimPrefix(path, "/")
+ if info.IsDir() {
+ handler.writeDirToTar(tw, info, path)
+ } else {
+ hdr := &tar.Header{
+ Name: path,
+ Mode: int64(info.Mode()),
+ Size: info.Size(),
+ ModTime: info.ModTime(),
+ }
+ if err := tw.WriteHeader(hdr); err != nil {
+ log.Fatal(err)
+ }
+ absFilePath := filepath.Join(handler.docPath, path)
+ openFile, err := os.Open(absFilePath)
+ if err != nil {
+ panic(err)
+ }
+ defer openFile.Close()
+ _, err = io.Copy(tw, openFile)
+ if err != nil {
+ panic(err)
+ }
+ }
+ }
+}
+
+func (handler IndexHandler) TarArchive(w io.Writer, r *http.Request, s string) {
+ p := filepath.Join(handler.docPath, s)
+ f, err := os.Stat(p)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ if f.IsDir() {
+ s = strings.TrimPrefix(s, "/")
+ //gw := gzip.NewWriter(w)
+ //defer gw.Close()
+ var tw *tar.Writer
+ tw = tar.NewWriter(w)
+ defer tw.Close()
+ handler.writeDirToTar(tw, f, s)
+ //w.WriteHeader(http.StatusCreated)
+ } else {
+ return
+ }
+}
+
+func (handler IndexHandler) IsExistingIndex() (bool, string) {
+ ind := filepath.Join(handler.docPath, "index.html")
+ f, err := os.Stat(ind)
+ if err == nil && !f.IsDir() {
+ return true, ind
+ }
+ ind = filepath.Join(handler.docPath, "index.htm")
+ f, err = os.Stat(ind)
+ if err == nil && !f.IsDir() {
+ return true, ind
+ }
+ return false, ""
+}
+
+func (handler IndexHandler) ServeDir(w http.ResponseWriter, r *http.Request, dir string) {
+ fileInfos, err := ioutil.ReadDir(dir)
+ if err != nil {
+ panic(err)
+ }
+ var files []File = nil
+ for _, info := range fileInfos {
+ path := filepath.Join(r.URL.Path, info.Name())
+ files = append(files, File{info, path})
+ }
+ funcs := template.FuncMap {
+ "format": format,
+ }
+ tmpl, err := template.New("index.html").Funcs(funcs).ParseFiles(GetIndexPath())
+ if err != nil {
+ panic(err)
+ }
+ data := struct {
+ DocDir string
+ CurrentPath string
+ Parent string
+ Files []File
+ }{
+ filepath.Base(handler.docPath),
+ r.URL.Path,
+ filepath.Dir(r.URL.Path),
+ files,
+ }
+ tmpl.Execute(w, data)
+}
+
+func (handler IndexHandler) Execute(w http.ResponseWriter, r *http.Request, s string) {
+ b := filepath.Join(handler.binPath, s)
+ _, err := os.Stat(b)
+ if err != nil {
+ log.Println("stat")
+ log.Println(err)
+ return
+ }
+ log.Printf("Executing %s\n", b)
+ //out, err := exec.Command(b).CombinedOutput()
+ cmd := exec.Command(b)
+ out, err := cmd.StdoutPipe()
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ if err := cmd.Start(); err != nil {
+ log.Println(err)
+ return
+ }
+ //_, err = w.Write(out)
+ _, err = io.Copy(w, out)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+}
+
+func (handler IndexHandler) ServeFile(w http.ResponseWriter, r *http.Request, p string) {
+ http.ServeFile(w, r, p)
+}
+
+func (handler IndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if strings.HasPrefix(r.URL.Path, "/tararchive") {
+ s := strings.TrimPrefix(r.URL.Path, "/tararchive")
+ contentDisposition := fmt.Sprintf("attachment; filename=\"%v\"", filepath.Base(s) + ".tar")
+ log.Println(contentDisposition)
+ w.Header().Set("Content-Disposition", contentDisposition)
+ handler.TarArchive(w, r, s)
+ return
+ } else if strings.HasPrefix(r.URL.Path, "/gzarchive") {
+ s := strings.TrimPrefix(r.URL.Path, "/gzarchive")
+ contentDisposition := fmt.Sprintf("attachment; filename=\"%v\"", filepath.Base(s) + ".tar.gz")
+ log.Println(contentDisposition)
+ w.Header().Set("Content-Disposition", contentDisposition)
+ gw := gzip.NewWriter(w)
+ defer gw.Close()
+ handler.TarArchive(gw, r, s)
+ return
+ } else if r.URL.Path == "/ai_execute" && handler.binPath != "" {
+ handler.ServeDir(w, r, handler.binPath)
+ return
+ } else if strings.HasPrefix(r.URL.Path, "/ai_execute") {
+ s := strings.TrimPrefix(r.URL.Path, "/ai_execute")
+ handler.Execute(w, r, s)
+ return
+ }
+
+ p := filepath.Join(handler.docPath, r.URL.Path)
+ if r.URL.Path == "/" {
+ if ok, ind := handler.IsExistingIndex(); ok && r.URL.Path == "/" {
+ http.ServeFile(w, r, ind)
+ return
+ }
+ }
+ f, err := os.Stat(p)
+ if err != nil {
+ log.Println(err)
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+ if f.IsDir() {
+ fileInfos, err := ioutil.ReadDir(p)
+ if err != nil {
+ panic(err)
+ }
+ var files []File = nil
+ for _, info := range fileInfos {
+ path := filepath.Join(r.URL.Path, info.Name())
+ files = append(files, File{info, path})
+ }
+ funcs := template.FuncMap {
+ "format": format,
+ }
+ tmpl, err := template.New("index.html").Funcs(funcs).ParseFiles(GetIndexPath())
+ if err != nil {
+ panic(err)
+ }
+ data := struct {
+ DocDir string
+ CurrentPath string
+ Parent string
+ Files []File
+ }{
+ filepath.Base(handler.docPath),
+ r.URL.Path,
+ filepath.Dir(r.URL.Path),
+ files,
+ }
+ tmpl.Execute(w, data)
+ } else {
+ handler.ServeFile(w, r, p)
+ }
+}
+
+func usage() {
+ fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [OPTIONS] pathtodocdir\n", os.Args[0])
+ fmt.Fprint(flag.CommandLine.Output(), "\nOptions:\n")
+ flag.PrintDefaults()
+}
+
+func main() {
+ port := flag.Int("p", 8080, "The port to bind to.")
+ binPath := flag.String("b", "", "The autoindex executables directory.")
+ flag.Parse()
+ args := flag.Args()
+ if len(args) != 1 {
+ usage()
+ os.Exit(1)
+ }
+ handler := IndexHandler{args[0], *binPath}
+ log.Printf("Listening on port %d with docPath=%s", *port, handler.docPath)
+ log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", *port), handler))
+}