//makeRecord builds and returns record with attached file. //if nobody render null_article page. func (t *threadCGI) makeRecord(at *attached, suffix string, ca *thread.Cache) (*record.Record, error) { body := make(map[string]string) for _, name := range []string{"body", "base_stamp", "base_id", "name", "mail"} { if value := t.Req.FormValue(name); value != "" { body[name] = util.Escape(value) } } if at != nil { body["attach"] = at.Data body["suffix"] = strings.TrimSpace(suffix) } if len(body) == 0 { t.Header(t.M["null_article"], "", nil, true) t.Footer(nil) return nil, errors.New("null article") } stamp := time.Now().Unix() if t.Req.FormValue("error") != "" { stamp = t.errorTime() } rec := record.New(ca.Datfile, "", 0) passwd := t.Req.FormValue("passwd") rec.Build(stamp, body, passwd) return rec, nil }
//appendRSS appends cache ca to rss with contents,url to records,stamp,attached file. func (g *gatewayCGI) appendRSS(rsss *cgi.RSS, ca *thread.Cache) { now := time.Now().Unix() if ca.Stamp()+cfg.RSSRange < now { return } title := util.Escape(util.FileDecode(ca.Datfile)) path := cfg.ThreadURL + "/" + util.StrEncode(title) recs := ca.LoadRecords(record.Alive) for _, r := range recs { if r.Stamp+cfg.RSSRange < now { continue } if err := r.Load(); err != nil { log.Println(err) continue } desc := cgi.RSSTextFormat(r.GetBodyValue("body", "")) content := g.rssHTMLFormat(r.GetBodyValue("body", ""), cfg.ThreadURL, title) if attach := r.GetBodyValue("attach", ""); attach != "" { suffix := r.GetBodyValue("suffix", "") if reg := regexp.MustCompile("^[0-9A-Za-z]+$"); !reg.MatchString(suffix) { suffix = cfg.SuffixTXT } content += fmt.Sprintf("\n <p><a href=\"http://%s%s%s%s/%s/%d.%s\">%d.%s</a></p>", g.Host(), cfg.ThreadURL, "/", ca.Datfile, r.ID, r.Stamp, suffix, r.Stamp, suffix) } permpath := fmt.Sprintf("%s/%s", path[1:], r.ID[:8]) rsss.Append(permpath, title, cgi.RSSTextFormat(r.GetBodyValue("name", "")), desc, content, user.GetStrings(ca.Datfile), r.Stamp, false) } }
//boardApp just renders title stripped from url. func (m *mchCGI) boardApp() { l := m.Req.FormValue("Accept-Language") if l == "" { l = "ja" } msg := cgi.SearchMessage(l, cfg.FileDir) m.WR.Header().Set("Content-Type", "text/html; charset=Shift_JIS") board := util.Escape(util.GetBoard(m.Path())) var text string if board != "" { text = fmt.Sprintf("%s - %s - %s", msg["logo"], msg["description"], board) } else { text = fmt.Sprintf("%s - %s", msg["logo"], msg["description"]) } htmlStr := fmt.Sprintf( `<!DOCTYPE html> <html><head> <meta http-equiv="content-type" content="text/html; charset=Shift_JIS"> <title>%s</title> <meta name="description" content="%s"> </head><body> <h1>%s</h1> </body></html>`, text, text, text) m.serveContent("a.html", time.Time{}, htmlStr) }
//GetContents returns recstrs of cache. //len(recstrs) is <=2. //used in templates func (c *Cache) GetContents() []string { m, err := record.FromRecordDB(c.Datfile, record.Alive) if err != nil { log.Print(err) return nil } contents := make([]string, 0, 2) for _, tt := range m { contents = append(contents, util.Escape(tt.Recstr())) if len(contents) > 2 { return contents } } return contents }
//HTMLFormat converts plain text to html , including converting link string to <a href="link">. func (c *CGI) HTMLFormat(plain, appli string, title string, absuri bool) string { if strings.HasPrefix(plain, "@markdown") { plain = strings.Replace(plain, "<br>", "\n", -1) plain = strings.Replace(plain, "<", "<", -1) plain = strings.Replace(plain, ">", ">", -1) return string(blackfriday.MarkdownCommon([]byte(plain[len("@markdown"):]))) } buf := strings.Replace(plain, "<br>", "\n", -1) buf = strings.Replace(buf, "\t", " ", -1) buf = util.Escape(buf) regLink := regexp.MustCompile(`https?://[^\x00-\x20"'\(\)<>\[\]\x7F-\xFF]{2,}`) if cfg.EnableEmbed { var strs []string for _, str := range strings.Split(buf, "<br>") { s := regLink.ReplaceAllString(str, `<a href="$0">$0</a>`) strs = append(strs, s) for _, link := range regLink.FindAllString(str, -1) { e := util.EmbedURL(link) if e != "" { strs = append(strs, e) strs = append(strs, "") } } } buf = strings.Join(strs, "<br>") } reg1 := regexp.MustCompile(">>[0-9a-f]{8}") buf = reg1.ReplaceAllStringFunc(buf, func(str string) string { regg := regexp.MustCompile("(>>)([0-9a-f]{8})") id := regg.ReplaceAllString(str, "$2") return regg.ReplaceAllString(str, c.ResAnchor(id, appli, title, absuri)+"$1$2</a>") }) reg3 := regexp.MustCompile(`(:[a-z0-9_]+:)`) buf = reg3.ReplaceAllStringFunc(buf, func(str string) string { return util.Emoji(str) }) reg2 := regexp.MustCompile(`\[\[([^<>]+?)\]\]`) tmp := reg2.ReplaceAllStringFunc(buf, func(str string) string { bl := c.bracketLink(str[2:len(str)-2], appli, absuri) return bl }) return util.EscapeSpace(tmp) }
//printRecentRSS renders rss of caches which are written recently(are updated remotely). //including title,tags,last-modified. func printRecentRSS(w http.ResponseWriter, r *http.Request) { g, err := new(w, r) if err != nil { log.Println(err) return } rsss := cgi.NewRSS("UTF-8", "", fmt.Sprintf("%s - %s", g.M["recent"], g.M["logo"]), "http://"+g.Host(), "", "http://"+g.Host()+cfg.GatewayURL+"/"+"recent_rss", g.M["description"], xslURL) cl := thread.MakeRecentCachelist() for _, ca := range cl { title := util.Escape(util.FileDecode(ca.Datfile)) tags := suggest.Get(ca.Datfile, nil) tags = append(tags, user.GetByThread(ca.Datfile)...) rsss.Append(cfg.ThreadURL[1:]+"/"+util.StrEncode(title), title, "", "", html.EscapeString(title), tags.GetTagstrSlice(), ca.RecentStamp(), false) } g.WR.Header().Set("Content-Type", "text/xml; charset=UTF-8") if rsss.Len() != 0 { g.WR.Header().Set("Last-Modified", g.RFC822Time(rsss.Feeds[0].Date)) } rsss.MakeRSS1(g.WR) }