package main import ( "database/sql" "fmt" "html" "net/http" "net/mail" "os" "path/filepath" "strings" ) type ReturnQuery struct { EM []EmailMeta Err error } type Query struct { Query string Return chan ReturnQuery } func (q *Query) Error(err error) { if q.Return != nil { q.Return <- ReturnQuery{ Err: err, } } } func (q *Query) Result(m []EmailMeta, err error) { if q.Return != nil { q.Return <- ReturnQuery{ EM: m, Err: err, } } } var QChan = make(chan *Query, 10) func Web(db *sql.DB) { go func() { err := http.ListenAndServe("127.0.1.69:3141", http.HandlerFunc(Http)) if err != nil { QChan <- &Query{Query: "EXIT"} } }() var r *sql.Rows var q *Query var err error for { q = <-QChan if q.Query == "EXIT" { q.Error(fmt.Errorf("server stopped")) break } if q.Query == "" { q.Error(fmt.Errorf("empty query")) continue } if r, err = db.Query(q.Query); err != nil { q.Error(fmt.Errorf("query error: %w", err)) continue } q.Result(ReadRows(r)) } close(QChan) } func E(s ...string) []any { a := make([]any, len(s)) for i, v := range s { a[i] = html.EscapeString(v) } return a } type HtmlEM struct { Id string Date string Subject string ToName string ToAddr string FromName string FromAddr string } func Http(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { r.ParseForm() var q []string if r.Form.Get("to") != "" { q = append(q, fmt.Sprintf(` toaddr LIKE '%%%s%%'`, r.Form.Get("to"))) } if r.Form.Get("from") != "" { q = append(q, fmt.Sprintf(` fromaddr LIKE '%%%s%%'`, r.Form.Get("from"))) } if r.Form.Get("subject") != "" { q = append(q, fmt.Sprintf(` subject LIKE '%%%s%%'`, r.Form.Get("subject"))) } if r.Form.Get("date") != "" { q = append(q, fmt.Sprintf(` date LIKE '%%%s%%'`, r.Form.Get("date"))) } qu := Query{ Query: fmt.Sprintf("SELECT * FROM emails %s ORDER BY date DESC", func() string { if len(q) == 0 { return "" } return "WHERE " + strings.Join(q, " AND ") }()), Return: make(chan ReturnQuery), } QChan <- &qu ret := <-qu.Return close(qu.Return) if ret.Err != nil { http.Error(w, "Internal Server Error", 500) return } if len(ret.EM) == 0 { fmt.Fprint(w, `No Emails

No Emails Found

`) return } var htmlMetas []HtmlEM var err error var from *mail.Address var to []*mail.Address var addrlist []string var htmlMeta HtmlEM for _, em := range ret.EM { htmlMeta = HtmlEM{ Id: em.Id, Date: TimeStr(em.Date), Subject: em.Subject, } from, err = mail.ParseAddress(em.From) if err != nil { htmlMeta.FromAddr = em.From } else { htmlMeta.FromAddr = from.Address htmlMeta.FromName = from.Name } if htmlMeta.FromName == "" { htmlMeta.FromName = htmlMeta.FromAddr } to, err = mail.ParseAddressList(em.To) if err != nil || len(to) == 0 { addrlist = strings.Split(em.To, ", ") if len(addrlist) == 0 { htmlMeta.ToAddr = em.To } else { htmlMeta.ToAddr = addrlist[0] } } else { htmlMeta.ToAddr = to[0].Address htmlMeta.ToName = to[0].Name } if htmlMeta.ToName == "" { htmlMeta.ToName = htmlMeta.ToAddr } htmlMetas = append(htmlMetas, htmlMeta) } fmt.Fprint(w, `Emails `) for _, em := range htmlMetas { fmt.Fprintf(w, `
%s
%s
%s
%s
`, E(em.Id, em.Date, em.FromAddr, em.FromName, em.ToAddr, em.ToName, em.Subject)...) } fmt.Fprintf(w, "") return } if filepath.Base(r.URL.Path) == "html.html" && len(strings.Split(r.URL.Path[1:], "/")) == 2 { id := filepath.Base(filepath.Dir(r.URL.Path)) s, _ := os.ReadFile(filepath.Join(SAVEPATH, id, "header.txt")) b, _ := os.ReadFile(filepath.Join(SAVEPATH, id, "body.txt")) fmt.Fprintf(w, `%s
%s

%s
`, id, string(s), string(b), "/"+id) return } http.FileServer(http.Dir(SAVEPATH)).ServeHTTP(w, r) }