func (m *mchCGI) threadApp(board, datkey string) {
	m.WR.Header().Set("Content-Type", "text/plain; charset=Shift_JIS")
	n, err := strconv.ParseInt(datkey, 10, 64)
	if err != nil {
		log.Println(err)
		return
	}
	key := keylib.GetFilekey(n)
	if err != nil {
		m.WR.WriteHeader(404)
		fmt.Fprintf(m.WR, "404 Not Found")
		return
	}
	data := thread.NewCache(key)
	if !data.Exists() {
		m.WR.WriteHeader(404)
		fmt.Fprintf(m.WR, "404 Not Found")
		return
	}
	if m.CheckGetCache() {
		download.GetCache(true, data)
	}
	thread := keylib.MakeDat(data, board, m.Req.Host)
	str := strings.Join(thread, "\n") + "\n"
	m.serveContent("a.txt", time.Unix(data.Stamp(), 0), str)
}
threadApp load thread.Cache specified in the url and returns dat file
listing records. if thread.Cache len=0 or for each refering the thread.Cache 4 times
reloads thread.Cache fron network.
package mch
import (
	"bytes"
	"errors"
	"fmt"
	"html"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/shingetsu-gou/shingetsu-gou/cfg"
	"github.com/shingetsu-gou/shingetsu-gou/cgi"
	"github.com/shingetsu-gou/shingetsu-gou/mch"
	"github.com/shingetsu-gou/shingetsu-gou/mch/keylib"
	"github.com/shingetsu-gou/shingetsu-gou/record"
	"github.com/shingetsu-gou/shingetsu-gou/tag/user"
	"github.com/shingetsu-gou/shingetsu-gou/thread"
	"github.com/shingetsu-gou/shingetsu-gou/thread/download"
	"github.com/shingetsu-gou/shingetsu-gou/updateque"
	"github.com/shingetsu-gou/shingetsu-gou/util"
)
func Setup(s *cgi.LoggingServeMux) {
	log.Println("start 2ch interface")
	rtr := mux.NewRouter()
	cgi.RegistToRouter(rtr, "/2ch/", boardApp)
	cgi.RegistToRouter(rtr, "/2ch/dat/{datkey:[^\\.]+}.dat", threadApp)
	cgi.RegistToRouter(rtr, "/2ch/{board:[^/]+}/subject.txt", subjectApp)
	cgi.RegistToRouter(rtr, "/2ch/subject.txt", subjectApp)
	cgi.RegistToRouter(rtr, "/2ch/{board:[^/]+}/head.txt", headApp)
	cgi.RegistToRouter(rtr, "/2ch/head.txt", headApp)
	s.Handle("/2ch/", handlers.CompressHandler(rtr))
	s.RegistCompressHandler("/test/bbs.cgi", postCommentApp)
}
func boardApp(w http.ResponseWriter, r *http.Request) {
	a, err := new(w, r)
	if err != nil {
		log.Println(err)
		return
	}
	a.boardApp()
}
func threadApp(w http.ResponseWriter, r *http.Request) {
	a, err := new(w, r)
	if err != nil {
		log.Println(err)
		return
	}
	m := mux.Vars(r)
	board := m["board"]
	if board == "" {
		board = "2ch"
	}
	a.threadApp(board, m["datkey"])
}
func subjectApp(w http.ResponseWriter, r *http.Request) {
	a, err := new(w, r)
	if err != nil {
		log.Println(err)
		return
	}
	m := mux.Vars(r)
	a.subjectApp(m["board"])
}
func postCommentApp(w http.ResponseWriter, r *http.Request) {
	a, err := new(w, r)
	if err != nil {
		log.Println(err)
		return
	}
	a.postCommentApp()
}
func headApp(w http.ResponseWriter, r *http.Request) {
	a, err := new(w, r)
	if err != nil {
		log.Println(err)
		return
	}
	a.headApp()
}
type mchCGI struct {
	*cgi.CGI
}
func new(w http.ResponseWriter, r *http.Request) (*mchCGI, error) {
	c, err := cgi.NewCGI(w, r)
	if err != nil {
		w.WriteHeader(403)
		fmt.Fprintf(w, "403 Forbidden")
		return nil, err
	}
	a := mchCGI{
		CGI: c,
	}
	if !c.CheckVisitor() {
		http.Error(w, "403 Forbidden", http.StatusForbidden)
		return nil, errors.New("403 forbidden")
	}
	return &a, nil
}
func (m *mchCGI) serveContent(name string, t time.Time, str string) {
	br := bytes.NewReader([]byte(util.ToSJIS(str)))
	http.ServeContent(m.WR, m.Req, name, t, br)
}
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)
}