//bracketLink convert ling string to [[link]] string with href tag. // if not thread and rec link, simply return [[link]] func (c *CGI) bracketLink(link, appli string, absuri bool) string { var prefix string if absuri { prefix = "http://" + c.Host() } reg := regexp.MustCompile("^/(thread)/([^/]+)/([0-9a-f]{8})$") if m := reg.FindStringSubmatch(link); m != nil { url := prefix + cfg.ThreadURL + "/" + util.StrEncode(m[2]) + "/" + m[3] return "<a href=\"" + url + "\" class=\"reclink\">[[" + link + "]]</a>" } reg = regexp.MustCompile("^/(thread)/([^/]+)$") if m := reg.FindStringSubmatch(link); m != nil { uri := prefix + cfg.ThreadURL + "/" + util.StrEncode(m[2]) return "<a href=\"" + uri + "\">[[" + link + "]]</a>" } reg = regexp.MustCompile("^([^/]+)/([0-9a-f]{8})$") if m := reg.FindStringSubmatch(link); m != nil { uri := prefix + appli + "/" + util.StrEncode(m[1]) + "/" + m[2] return "<a href=\"" + uri + "\" class=\"reclink\">[[" + link + "]]</a>" } reg = regexp.MustCompile("^([^/]+)$") if m := reg.FindStringSubmatch(link); m != nil { uri := prefix + appli + "/" + util.StrEncode(m[1]) return "<a href=\"" + uri + "\">[[" + link + "]]</a>" } return "[[" + link + "]]" }
//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) } }
//ResAnchor returns a href string with url. func (c *CGI) ResAnchor(id, appli string, title string, absuri bool) string { title = util.StrEncode(title) var prefix, innerlink string if absuri { prefix = "http://" + c.Host() } else { innerlink = " class=\"innerlink\"" } return fmt.Sprintf("<a href=\"%s%s%s%s/%s\"%s>", prefix, appli, "/", title, id, innerlink) }
//jumpNewFile renders 302 redirect to page for making new thread specified in url query //"link"(thred name) "type"(thread) "tag" "search_new_file"("yes" or "no") func (g *gatewayCGI) jumpNewFile() { link := g.Req.FormValue("link") t := g.Req.FormValue("type") switch { case link == "": g.Header(g.M["null_title"], "", nil, true) g.Footer(nil) case strings.ContainsAny(link, "/[]<>"): g.Header(g.M["bad_title"], "", nil, true) g.Footer(nil) case t == "": g.Header(g.M["null_type"], "", nil, true) g.Footer(nil) case t == "thread": tag := util.StrEncode(g.Req.FormValue("tag")) search := util.StrEncode(g.Req.FormValue("search_new_file")) g.Print302(cfg.ThreadURL + "/" + util.StrEncode(link) + "?tag=" + tag + "&search_new_file" + search) default: g.Print404(nil, "") } }
//setCookie set cookie access=now time,tmpaccess=access var. func (t *threadCGI) setCookie(ca *thread.Cache, access string) []*http.Cookie { const ( saveCookie = 7 * 24 * time.Hour // Seconds ) c := http.Cookie{} c.Expires = time.Now().Add(saveCookie) c.Path = cfg.ThreadURL + "/" + util.StrEncode(util.FileDecode(ca.Datfile)) c.Name = "access" c.Value = strconv.FormatInt(time.Now().Unix(), 10) if access == "" { return []*http.Cookie{&c} } cc := http.Cookie{} cc.Name = "tmpaccess" cc.Value = access return []*http.Cookie{&c, &cc} }
//printThreadIndex adds records in multiform and redirect to its thread page. func (t *threadCGI) printThreadIndex() { err := t.Req.ParseMultipartForm(int64(cfg.RecordLimit) << 10) if err != nil { t.Print404(nil, "") return } if t.Req.FormValue("cmd") != "post" || !strings.HasPrefix(t.Req.FormValue("file"), "thread_") { t.Print404(nil, "") return } id := t.doPost() if id == "" { t.Print404(nil, "") return } datfile := t.Req.FormValue("file") title := util.StrEncode(util.FileDecode(datfile)) t.Print302(cfg.ThreadURL + "/" + title + "#r" + id) }
//printGateway just redirects to correspoinding url using thread.cgi. //or renders only title. func printGatewayThread(w http.ResponseWriter, r *http.Request) { reg := regexp.MustCompile("^/gateway.cgi/(thread)/?([^/]*)$") m := reg.FindStringSubmatch(r.URL.Path) var uri string switch { case m == nil: PrintTitle(w, r) return case m[2] != "": uri = cfg.ThreadURL + "/" + util.StrEncode(m[2]) case r.URL.RawQuery != "": uri = cfg.ThreadURL + "/" + r.URL.RawQuery default: PrintTitle(w, r) return } g, err := new(w, r) if err != nil { log.Println(err) return } g.Print302(uri) }
//renderCSV renders CSV including key string of caches in disk. //key is specified in url query. func (g *gatewayCGI) renderCSV(cl thread.Caches) { g.WR.Header().Set("Content-Type", "text/comma-separated-values;charset=UTF-8") p := strings.Split(g.Path(), "/") if len(p) < 3 { g.Print404(nil, "") return } cols := strings.Split(p[2], ",") cwr := csv.NewWriter(g.WR) for _, ca := range cl { title := util.FileDecode(ca.Datfile) p := cfg.ThreadURL + "/" + util.StrEncode(title) row := make([]string, len(cols)) for i, c := range cols { row[i] = g.makeOneRow(c, ca, p, title) } err := cwr.Write(row) if err != nil { log.Println(err) } } cwr.Flush() }
//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) }