package main import ( "fmt" "git.sophuwu.com/authuwu" "git.sophuwu.com/authuwu/userpass" "git.sophuwu.com/gophuwu/flags" "git.sophuwu.com/manhttpd/CFG" "git.sophuwu.com/manhttpd/embeds" "git.sophuwu.com/manhttpd/manpage" "git.sophuwu.com/manhttpd/neterr" "golang.org/x/term" "net/http" "os" "os/exec" "regexp" "strings" "time" ) func init() { err := flags.NewFlag("conf", "c", "configuration file to use", "/etc/manhttpd/manhttpd.conf") neterr.ChkFtl("creating conf flag:", err) err = flags.NewFlag("passwd", "p", "open the program in password edit mode", false) neterr.ChkFtl("creating passwd flag:", err) err = flags.NewFlag("user", "u", "choose a username to set/change/delete password for", "") neterr.ChkFtl("creating user flag:", err) err = flags.ParseArgs() neterr.ChkFtl("parsing flags:", err) CFG.ParseConfig() embeds.OpenAndParse() } func setPasswd() { u, err := flags.GetStringFlag("user") if err != nil { fmt.Println("getting user flag:", err) return } if u == "" { fmt.Println("no user specified, use -u to set a password for a user") return } var in []byte fmt.Printf("Enter password for user %s (leave empty to delete user): \n", u) in, err = term.ReadPassword(0) if err != nil { fmt.Println("could not read password:", err) return } password := string(in) if password == "" { fmt.Printf("delete user %s? (y/N): ", u) in = make([]byte, 1) os.Stdin.Read(in) if in[0] != 'y' && in[0] != 'Y' { userpass.DeleteUser(u) fmt.Printf("User %s deleted.\n", u) return } fmt.Printf("exiting with no changes\n") return } fmt.Println("Enter password again: ") in, err = term.ReadPassword(0) if err != nil { fmt.Println("could not read password:", err) return } if string(in) != password { fmt.Println("Passwords do not match, please try again.") return } err = userpass.NewUser(u, password) } func main() { b, err := flags.GetBoolFlag("passwd") neterr.ChkFtl("getting passwd flag:", err) if b { err = authuwu.OpenDB(CFG.PasswdFile) neterr.ChkFtl("opening password database:", err) setPasswd() authuwu.CloseDB() return } if CFG.RequireAuth { err = authuwu.OpenDB(CFG.PasswdFile) neterr.ChkFtl("error opening password database:", err) PageHandler = authuwu.NewAuthuwuHandler(PageHandler, time.Hour*24*3, embeds.LoginPage) } CFG.ListenAndServe(Handler) } var RxWords = regexp.MustCompile(`("[^"]+")|([^ ]+)`).FindAllString var RxWhatIs = regexp.MustCompile(`([a-zA-Z0-9_\-]+) [(]([0-9a-z]+)[)][\- ]+(.*)`).FindAllStringSubmatch func SearchHandler(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if neterr.Err400.Is(err) { embeds.WriteError(w, r, neterr.Err400, r.Form.Get("q")) return } q := r.Form.Get("q") if q == "" { http.Redirect(w, r, r.URL.Path, http.StatusFound) } if strings.HasPrefix(q, "manweb:") { http.Redirect(w, r, "?"+q, http.StatusFound) return } if func() bool { m := manpage.New(q) return m.Where() == nil }() { http.Redirect(w, r, "?"+q, http.StatusFound) return } var args = RxWords("-lw "+q, -1) for i := range args { args[i] = strings.TrimSpace(args[i]) args[i] = strings.TrimPrefix(args[i], `"`) args[i] = strings.TrimSuffix(args[i], `"`) if (args[i] == "-r" || args[i] == "-w") && args[0] != "-l" { args[0] = "-l" } } cmd := exec.Command(CFG.DbCmd, args...) b, e := cmd.Output() if len(b) < 1 || e != nil { embeds.WriteError(w, r, neterr.Err404, q) return } var output string for _, line := range RxWhatIs(string(b), -1) { // strings.Split(string(b), "\n") { if len(line) == 4 { output += fmt.Sprintf(`

%s (%s) - %s

%c`, line[1], line[2], line[1], line[2], line[3], 10) } } embeds.WriteHtml(w, r, "Search", output, q) } var PageHandler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { SearchHandler(w, r) return } name := r.URL.RawQuery if name == "manweb:help" { embeds.Help(w, r) return } var nerr neterr.NetErr title := "Index" var html string if name != "" { man := manpage.New(name) html, nerr = man.Html() if nerr != nil { embeds.WriteError(w, r, nerr, name) return } title = man.Name } embeds.WriteHtml(w, r, title, html, name) }) var Handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Has("static") { StaticHandler(w, r) return } PageHandler.ServeHTTP(w, r) }) type ManHandler struct { h http.Handler } func (m ManHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Has("static") { StaticHandler(w, r) return } m.h.ServeHTTP(w, r) } func StaticHandler(w http.ResponseWriter, r *http.Request) { q := r.URL.Query().Get("static") if f, ok := embeds.StaticFile(q); ok { w.Header().Set("Content-Type", f.ContentType) w.Header().Set("Content-Length", f.Length) f.WriteTo(w) return } }