diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..510bb9a --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/ChaoticByte/plaintext-encyclopedia + +go 1.22.4 diff --git a/main.go b/main.go new file mode 100644 index 0000000..93b8ff2 --- /dev/null +++ b/main.go @@ -0,0 +1,77 @@ +package main + +import ( + "html/template" + "io/fs" + "log" + "net/http" + "os" + "strings" +) + +var logger *log.Logger +var appTemplate *template.Template = template.New("app") + +type TemplateData struct { + TOC []string + Entry string + Title string + EntryTitle string +} + +func loadTemplate() { + data, err := os.ReadFile(TemplateFile) + if err != nil { logger.Panic(err) } + appTemplate.Parse(string(data)) +} + +func getTOC() []string { + entriesDirFs := os.DirFS(EntriesDirectory) + m, err := fs.Glob(entriesDirFs, "*") + if err != nil { logger.Panic(err) } + return m +} + +func getEntry(name string) (string, error) { + data, err := os.ReadFile(strings.TrimRight(EntriesDirectory, "/") + "/" + name) + if err != nil { return "", err } + return string(data), err +} + +func handleApplication(w http.ResponseWriter, req *http.Request) { + var entry string + var err error + entryName := strings.Trim(req.URL.Path, "/") + if entryName != "" { + if strings.Contains(entryName, "/") || strings.Contains(entryName, ".") { + // path traversal + logger.Println("Possible path traversal attempt from", req.RemoteAddr, "to", entryName) + w.WriteHeader(http.StatusForbidden) + return + } + // load entry + entry, err = getEntry(entryName) + if err != nil { + logger.Println("Couldn't open entry", entryName) + w.WriteHeader(http.StatusNotFound) + } + } + err = appTemplate.ExecuteTemplate(w, "app", TemplateData{TOC: getTOC(), Entry: entry, Title: MainTitle, EntryTitle: entryName}) + if err != nil { logger.Println(err) } +} + +func main() { + // get logger + logger = log.Default() + // load template + loadTemplate() + // handle static files + staticHandler := http.StripPrefix("/static/", http.FileServer(http.Dir(StaticDirectory))) + http.Handle("/static/", staticHandler) + // handle application + http.HandleFunc("/", handleApplication) + // start server + logger.Println("Starting server on", ServerListen) + err := http.ListenAndServe(ServerListen, nil) + if err != nil { logger.Panic(err) } +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..b5ff3aa --- /dev/null +++ b/public/index.html @@ -0,0 +1,27 @@ + + +
+ + + + +