package yatwiki3 import ( "errors" "fmt" "html/template" "net/http" "net/url" "strconv" "strings" "time" ) type WikiServer struct { db *WikiDB opts *ServerOptions pageTmp *template.Template loc *time.Location } func NewWikiServer(opts *ServerOptions) (*WikiServer, error) { wdb, err := NewWikiDB(opts.DBFilePath) if err != nil { return nil, err } tmpl, err := template.New("yatwiki/page").Parse(pageTemplate) if err != nil { return nil, err } loc, err := time.LoadLocation(opts.Timezone) if err != nil { return nil, err } ws := WikiServer{ db: wdb, opts: opts, pageTmp: tmpl, loc: loc, } return &ws, nil } func (this *WikiServer) Close() { this.db.Close() } func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Server", "YATWiki3") if r.Method == "GET" { if r.URL.Path == this.opts.ExpectBaseURL+"wiki.css" { w.Header().Set("Content-Type", "text/css") content, _ := wikiCssBytes() w.Write(content) return } else if r.URL.Path == this.opts.ExpectBaseURL+"highlight.js" { w.Header().Set("Content-Type", "application/javascript") content, _ := highlightJsBytes() w.Write(content) return } else if r.URL.Path == this.opts.ExpectBaseURL+"favicon.ico" && len(this.opts.FaviconFilePath) > 0 { w.Header().Set("Content-Type", "image/x-icon") http.ServeFile(w, r, this.opts.FaviconFilePath) return } else if r.URL.Path == this.opts.ExpectBaseURL+"download-database" { w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Disposition", `attachment; filename="database-`+fmt.Sprintf("%d", time.Now().Unix())+`.db"`) http.ServeFile(w, r, this.opts.DBFilePath) return } else if r.URL.Path == this.opts.ExpectBaseURL+"formatting" { this.routeFormatting(w, r) return } else if r.URL.Path == this.opts.ExpectBaseURL+"index" { this.routeIndex(w, r) return } else if strings.HasPrefix(r.URL.Path, this.opts.ExpectBaseURL+"view/") { articleTitle, err := url.QueryUnescape(r.URL.Path[len(this.opts.ExpectBaseURL+"view/"):]) if err != nil { this.serveErrorMessage(w, err) return } this.routeView(w, r, articleTitle) return } else if strings.HasPrefix(r.URL.Path, this.opts.ExpectBaseURL+"modify/") { articleTitle, err := url.QueryUnescape(r.URL.Path[len(this.opts.ExpectBaseURL+"modify/"):]) if err != nil { this.serveErrorMessage(w, err) return } this.routeModify(w, r, articleTitle) return } else if strings.HasPrefix(r.URL.Path, this.opts.ExpectBaseURL+"history/") { articleTitle, err := url.QueryUnescape(r.URL.Path[len(this.opts.ExpectBaseURL+"history/"):]) if err != nil { this.serveErrorMessage(w, err) return } this.routeHistory(w, r, articleTitle) return } else if strings.HasPrefix(r.URL.Path, this.opts.ExpectBaseURL+"raw/") { revId, err := strconv.Atoi(r.URL.Path[len(this.opts.ExpectBaseURL+"raw/"):]) if err != nil { this.serveErrorMessage(w, err) return } this.routeRawView(w, r, revId) return } else if strings.HasPrefix(r.URL.Path, this.opts.ExpectBaseURL+"archive/") { revId, err := strconv.Atoi(r.URL.Path[len(this.opts.ExpectBaseURL+"archive/"):]) if err != nil { this.serveErrorMessage(w, err) return } this.routeArchive(w, r, revId) return } else if strings.HasPrefix(r.URL.Path, this.opts.ExpectBaseURL+"recent/") { pageNum, err := strconv.Atoi(r.URL.Path[len(this.opts.ExpectBaseURL+"recent/"):]) if err != nil { this.serveErrorMessage(w, err) return } this.routeRecentChanges(w, r, pageNum) return } } // No match? Add 'Page not found' to next session response, and redirect to homepage this.serveErrorMessage(w, errors.New("Page not found")) }