From 19b8fdb504280cc9717204c0d6ac69fbad63a227 Mon Sep 17 00:00:00 2001 From: mappu Date: Sun, 9 Jul 2017 13:00:45 +1200 Subject: [PATCH] implement 'article index' page, better error handling --- WikiServer.go | 72 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/WikiServer.go b/WikiServer.go index 49f6a0d..c2ef867 100644 --- a/WikiServer.go +++ b/WikiServer.go @@ -2,9 +2,12 @@ package yatwiki3 import ( "database/sql" + "errors" + "fmt" "html/template" "log" "net/http" + "net/url" "strings" ) @@ -79,7 +82,32 @@ func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  • [section=header]content[/section]
  • [html]raw html[/html]
  • ` - this.servePageResponse(w, pto) + this.servePageResponse(w, r, pto) + return + + } else if r.URL.Path == this.opts.ExpectBaseURL+"index" { + titles, err := this.db.ListTitles() + if err != nil { + this.serveInternalError(w, r, err) + return + } + + totalRevs, err := this.db.TotalRevisions() + if err != nil { + this.serveInternalError(w, r, err) + return + } + + content := fmt.Sprintf(`

    Article Index


    There are %d edits to %d pages.

    ` + + pto := DefaultPageTemplateOptions(this.opts) + pto.CurrentPageName = "Index" + pto.Content = template.HTML(content) + this.servePageResponse(w, r, pto) return } else if strings.HasPrefix(r.URL.Path, this.opts.ExpectBaseURL+"view/") { @@ -91,6 +119,11 @@ func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { a, err := this.db.GetLatestVersion(articleTitle) if err != nil { + + if err == sql.ErrNoRows { + this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle)) + return + } this.serveErrorMessage(w, err) return } @@ -103,7 +136,7 @@ func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { pto.Content = bcr.RenderHTML(string(a.Body)) pto.LoadCodeResources = bcr.CodePresent - this.servePageResponse(w, pto) + this.servePageResponse(w, r, pto) return } @@ -111,30 +144,31 @@ func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // No match? Add 'Page not found' to next session response, and redirect to homepage - http.Error(w, "Page not found", 404) + this.serveErrorMessage(w, errors.New("Page not found")) - /* - pto.SessionMessage = `Invalid request.` - //pto.CurrentPageIsArticle = true - //pto.CurrentPageName = "quotes/\"2017" +} - bcr := NewBBCodeRenderer(this.opts.ExpectBaseURL) - pto.Content = bcr.RenderHTML(`[h]Hello World[/h] this content is [b]bold[/b] `) - - this.servePageResponse(w, pto) - */ +func (this *WikiServer) noSuchArticleError(title string) template.HTML { + return template.HTML(`No such article exists. Click here to create it.`) } func (this *WikiServer) serveErrorMessage(w http.ResponseWriter, message error) { - if message == sql.ErrNoRows { - // 404 not found - } - - // TODO Add error message to session response, and redirect to homepage - http.Error(w, message.Error(), 500) + this.serveErrorHTMLMessage(w, template.HTML(template.HTMLEscapeString(message.Error()))) } -func (this *WikiServer) servePageResponse(w http.ResponseWriter, pto *pageTemplateOptions) { +func (this *WikiServer) serveInternalError(w http.ResponseWriter, r *http.Request, e error) { + log.Printf("Internal error from %s while accessing %s(%s): %s", r.RemoteAddr, r.Method, r.URL.Path, e.Error()) + http.Error(w, "An internal error occurred. Please ask an administrator to check the log file.", 500) +} + +func (this *WikiServer) serveErrorHTMLMessage(w http.ResponseWriter, msg template.HTML) { + w.Header().Set("Location", this.opts.ExpectBaseURL+"view/"+url.QueryEscape(this.opts.DefaultPage)+"?error="+url.QueryEscape(string(msg))) + w.WriteHeader(302) // moved (not permanently) +} + +func (this *WikiServer) servePageResponse(w http.ResponseWriter, r *http.Request, pto *pageTemplateOptions) { + pto.SessionMessage = template.HTML(r.URL.Query().Get("error")) // FIXME reflected XSS (although Chrome automatically blocks it..) + err := this.pageTmp.Execute(w, pto) if err != nil { log.Println(err.Error())