about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/http/http.go178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/http/http.go b/src/http/http.go
index d02cfda..76ca62d 100644
--- a/src/http/http.go
+++ b/src/http/http.go
@@ -1 +1,179 @@
 package http
+
+import (
+	"fmt"
+	"html/template"
+	"io/ioutil"
+	"net/http"
+	"strings"
+
+	"git.darknebu.la/emile/faila/src/structs"
+	"github.com/gorilla/mux"
+	"github.com/sirupsen/logrus"
+	"github.com/spf13/viper"
+)
+
+// Server defines and runs an HTTP server
+func Server() {
+	r := mux.NewRouter()
+
+	// static js / css hosting
+	static := r.PathPrefix("/static/").Subrouter()
+	fs := http.FileServer(http.Dir("./hosted/static"))
+	static.PathPrefix("/").Handler(http.StripPrefix("/static/", fs))
+
+	t := r.PathPrefix("/").Subrouter()
+	t.PathPrefix("/").HandlerFunc(pathHandler)
+
+	// get the ip and port from the config
+	bindIP := viper.GetString("server.bindip")
+	listenPort := viper.GetString("server.listenport")
+
+	// define the http server
+	httpServer := http.Server{
+		Addr:    fmt.Sprintf("%s:%s", bindIP, listenPort),
+		Handler: r,
+	}
+
+	logrus.Warnf("HTTP server defined listening on %s:%s", bindIP, listenPort)
+	logrus.Fatal(httpServer.ListenAndServe())
+}
+
+func pathHandler(w http.ResponseWriter, r *http.Request) {
+	var content map[string]interface{}
+	content = make(map[string]interface{})
+
+	breadcrumbsList := breadcrumbs(r)
+	content["Breadcrumbs"] = breadcrumbsList
+
+	root := viper.GetString("server.root")
+	requestURI := fmt.Sprintf("%s%s", root, r.RequestURI)
+	logrus.Infof("requestURI: %s", requestURI)
+	logrus.Infof("r.RequestURI: %s", r.RequestURI)
+
+	// get all files in the request dir
+	files, err := ioutil.ReadDir(requestURI)
+	if err != nil {
+		logrus.Warn(err)
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	// define the items (files and dirs)
+	var items structs.Items
+	var dirCount int = 0
+	var fileCount int = 0
+	for _, f := range files {
+
+		// get the file or dirs modtime and format it in a readable way as
+		// described in the config
+		modTime := f.ModTime()
+		if viper.GetString("time.format") == "" {
+			logrus.Fatalf("Please insert a format for the time in the config (time.format), see the README for more information.")
+		}
+		humanModTime := modTime.Format(viper.GetString("time.format"))
+
+		// define the file or dir's url
+		var url string
+		if r.RequestURI != "/" {
+			url = fmt.Sprintf("%s/%s", r.RequestURI, f.Name())
+		} else {
+			url = fmt.Sprintf("/%s", f.Name())
+		}
+
+		// define the file or dir
+		item := structs.Item{
+			Name:         f.Name(),
+			HumanSize:    f.Size(),
+			URL:          url,
+			HumanModTime: humanModTime,
+			IsSymlink:    false,
+			Size:         "0",
+		}
+
+		// if it is a dir, say so
+		if f.IsDir() == true {
+			item.IsDir = true
+			dirCount++
+		}
+
+		items = append(items, item)
+	}
+
+	// add the items to the content map
+	content["Items"] = items
+
+	// ad the file and dir count to the contents map
+	content["NumDirs"] = dirCount
+	content["NumFiles"] = fileCount
+
+	// if there are more than one breadcrumb, define the uppath as the second
+	// last breadcrumb
+	// I did this, because somehow things broke when simply using ".." in
+	// combination with hidden folders
+	if len(breadcrumbsList) > 1 {
+		content["UpPath"] = breadcrumbsList[len(breadcrumbsList)-2].Link
+	} else {
+		content["UpPath"] = ".."
+	}
+
+	// In the caddy
+	content["ItemsLimitedTo"] = 100000000000
+
+	// define the sort order manually
+	// TODO: handle this correctly
+	content["Sort"] = "namedirfirst"
+	content["Order"] = "desc"
+
+	// if we're not at the root, we can still go futher down!
+	if r.RequestURI != "/" {
+		content["CanGoUp"] = "true"
+	}
+
+	// define a new template to render the challenges in
+	t := template.New("")
+	t, err = t.ParseGlob("./hosted/tmpl/*.html")
+	if err != nil {
+		logrus.Warn(err)
+		return
+	}
+
+	t.ExecuteTemplate(w, "index", content)
+}
+
+// breadcrumbs get's the breadcrumbs from the request
+func breadcrumbs(r *http.Request) structs.Breadcrumbs {
+	logrus.Debugf("----------------------------------------------------------")
+	logrus.Debugf("%s\n", r.RequestURI)
+
+	request := r.RequestURI
+
+	// mitigate path traversals
+	strippedRequest := strings.Replace(request, "..", "", -1)
+
+	if request != "/" {
+		strippedRequest = strings.TrimRight(strippedRequest, "/")
+	}
+
+	// continue without the first slash, as it produces an unused field that has
+	// no use
+	crumbs := strings.Split(strippedRequest[1:], "/")
+
+	// build the breadcrumbs from the split RequestURI
+	var breadcrumbs structs.Breadcrumbs
+	for i, crumb := range crumbs {
+
+		text := crumb
+
+		// the link is defined as the text until the given crumb
+		link := strings.Join(crumbs[:i+1], "/")
+
+		resultCrumb := structs.Crumb{
+			Text: text,
+			Link: fmt.Sprintf("/%s", link),
+		}
+		breadcrumbs = append(breadcrumbs, resultCrumb)
+	}
+
+	return breadcrumbs
+}