diff options
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 153 |
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) + } +} |
