summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go153
1 files changed, 153 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 00000000..e613e60d
--- /dev/null
+++ b/main.go
@@ -0,0 +1,153 @@
+package main
+
+import (
+ "fmt"
+ "html/template"
+ "log"
+ "net/http"
+ "os"
+ "regexp"
+ "database/sql"
+ _ "modernc.org/sqlite"
+)
+
+type Entry struct {
+ os string
+ name string
+ section int
+ path string
+}
+
+type Database struct {
+ DB *sql.DB
+}
+
+func (d *Database) Search(w http.ResponseWriter, r *http.Request) {
+ query := r.URL.Query()
+
+ log.Println("Request for:", r.URL.String())
+
+ name := query["name"][0]
+ section := query["section"][0]
+ osName := query["os"][0]
+
+ log.Println(name)
+
+ rows, err := d.DB.Query("SELECT * FROM manpages WHERE name == ? AND section == ? AND os == ?;", name, section, osName)
+ if err != nil {
+ log.Println(err)
+ ErrorPage(w, http.StatusText(500), 500)
+ return
+ }
+ defer rows.Close()
+
+ var entries []Entry
+ for rows.Next() {
+ var entry Entry
+
+ if err := rows.Scan(&entry.os, &entry.name, &entry.section, &entry.path); err != nil {
+ log.Println(err)
+ ErrorPage(w, http.StatusText(500), 500)
+ return
+ }
+
+ entries = append(entries, entry)
+ }
+
+ if len(entries) > 0 {
+ for _, e := range entries {
+ data, err := os.ReadFile(e.path)
+ if err != nil {
+ log.Println(err)
+ ErrorPage(w, http.StatusText(500), 500)
+ return
+ }
+ fmt.Fprintf(w, "%s", data)
+ }
+ } else {
+ fmt.Fprintf(w, "<center><h1>No results found for %s %s(%s)</h1></center>", osName, name, section)
+ }
+}
+
+func GetFiles(w http.ResponseWriter, r *http.Request) {
+ log.Println("Request for:", r.URL.String())
+ url := fmt.Sprintf("static%s", r.URL.String())
+ htmlRegex, err := regexp.Compile("^static/.*\\.html$")
+ if err != nil {
+ ErrorPage(w, "Internal Server Error", 500)
+ return
+ }
+
+ if url == "static/" {
+ url = "static/index.html"
+ }
+
+ if htmlRegex.MatchString(url) {
+ t := template.Must(template.ParseFiles("templates/template.html"))
+
+ html, err := os.ReadFile(url)
+ if err != nil {
+ ErrorPage(w, http.StatusText(500), 500)
+ return
+ }
+
+ t.Execute(w, template.HTML(html))
+ } else {
+ http.ServeFile(w, r, url)
+ }
+}
+
+func ErrorPage(w http.ResponseWriter, message string, code int) {
+ log.Println(code, message)
+ t := template.Must(template.ParseFiles("templates/error.html"))
+ t.Execute(w, struct {
+ Code int
+ Message string
+ }{
+ Code: code,
+ Message: message,
+ })
+}
+
+func Usage() {
+ fmt.Fprintf(os.Stderr, "%s [--port port]\n", os.Args[0])
+}
+
+func main() {
+ port := ":8000"
+
+ for i := 1; i < len(os.Args); i++ {
+ switch os.Args[i] {
+ case "--port":
+ if i+1 >= len(os.Args) {
+ Usage()
+ } else {
+ port = ":" + os.Args[i+1]
+ i++
+ }
+ default:
+ log.Println("Unknown option: ", os.Args[i])
+ Usage()
+ }
+ }
+
+ db, err := sql.Open("sqlite", "man.db")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := db.Ping(); err != nil {
+ log.Fatal(err)
+ }
+
+ dbWrapper := &Database{ DB: db }
+
+ http.HandleFunc("/search", dbWrapper.Search)
+ http.HandleFunc("/", GetFiles)
+ log.Fatal(http.ListenAndServe(port, nil))
+
+ err = db.Close()
+ if err != nil {
+ log.Fatal(err)
+ }
+}