package main import ( "fmt" "git.sophuwu.com/authuwu" cookies "git.sophuwu.com/authuwu/cookie" "git.sophuwu.com/authuwu/userpass" "git.sophuwu.com/gophuwu/flags" "git.sophuwu.com/manweb/CFG" "git.sophuwu.com/manweb/embeds" "git.sophuwu.com/manweb/logs" "git.sophuwu.com/manweb/manpage" "git.sophuwu.com/manweb/neterr" "git.sophuwu.com/manweb/stats" "git.sophuwu.com/manweb/tldr" "golang.org/x/term" "net/http" "os" "os/exec" "regexp" "strings" "time" ) func init() { err := flags.NewFlag("conf", "c", "configuration file to use", "/etc/manweb/manweb.conf") logs.CheckFatal("creating conf flag", err) err = flags.NewFlag("passwd", "p", "open the program in password edit mode", false) logs.CheckFatal("creating passwd flag", err) err = flags.NewFlag("user", "u", "choose a username to set/change/delete password for", "") logs.CheckFatal("creating user flag", err) err = flags.ParseArgs() logs.CheckFatal("parsing flags", err) CFG.ParseConfig() embeds.OpenAndParse() tldr.Open() } 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") logs.CheckFatal("getting passwd flag", err) if b { err = authuwu.OpenDB(CFG.PasswdFile) if err != nil { if err.Error() == "timeout" { logs.Error("The database is currently opened by another process.") return } logs.Fatal("opening password database", err) } setPasswd() authuwu.CloseDB() return } if CFG.RequireAuth { err = authuwu.OpenDB(CFG.PasswdFile) logs.CheckFatal("opening password database", err) _ = cookies.PurgeExpiredCookies() PageHandler = authuwu.NewAuthuwuHandler(PageHandler, time.Hour*24*3, embeds.LoginPage) logs.AddOnExit(func() { authuwu.CloseDB() }) } if CFG.EnableStats { stats.OpenDB() logs.AddOnExit(func() { stats.CloseDB() }) } CFG.ListenAndServe(Handler) logs.Exit(0) } 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, q string) { 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) { 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, "") stats.SpecialCount("Search") } var PageHandler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { name := r.URL.RawQuery name = strings.TrimSpace(name) if r.Method == "POST" { n := r.PostFormValue("q") n = strings.TrimSpace(n) if n == "" { name = "" } else if n != "" { name = n if strings.ContainsAny(name, `"*?^|`) { SearchHandler(w, r, name) return } } } if name == "" { embeds.WriteHtml(w, r, "Index", stats.Html(), "", "") return } if embeds.Help(w, r, name) { return } if manpage.Http(w, r, name) { return } if CFG.TldrPages && tldr.Http(w, r, name) { return } SearchHandler(w, r, 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) }) 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 } }