6 Commits

Author SHA1 Message Date
a260d102ee doc: update readme, bump version to 3.1.0 2017-10-08 17:09:15 +13:00
179617d058 contented integration 2017-10-08 17:08:26 +13:00
5347efb51a bump version to 3.0.3 2017-08-13 18:29:21 +12:00
e3cee5b94c doc: changelog update 2017-08-13 18:27:04 +12:00
e4cf02cde7 restructure error handling to prevent reflected XSS 2017-08-13 18:25:58 +12:00
06e5b4ddf9 bump version to 3.0.1 2017-08-13 18:07:29 +12:00
8 changed files with 57 additions and 14 deletions

View File

@@ -2,7 +2,7 @@
# Makefile for YATWiki3
#
VERSION:=3.0.1
VERSION:=3.1.0
SOURCES:=Makefile \
static \

View File

@@ -21,6 +21,7 @@ type ServerOptions struct {
ExternalBaseURL string
DeclareRSSLanguage string
DeclareRSSEmail string
ContentedServer string
}
func DefaultOptions() *ServerOptions {
@@ -41,5 +42,6 @@ func DefaultOptions() *ServerOptions {
ExternalBaseURL: "http://127.0.0.1/",
DeclareRSSLanguage: "en-GB",
DeclareRSSEmail: `nobody@example.com`,
ContentedServer: "",
}
}

View File

@@ -14,6 +14,7 @@ As of the 3.0 release, YATWiki is now a standalone server instead of a PHP scrip
- IP-based ban system
- Article index, random article, download database backup
- Source code highlighting (thanks [url=https://github.com/isagalaev/highlight.js]highlight.js[/url])
- Optional integration with `contented` for file/image uploads
Written in Golang, PHP
@@ -35,6 +36,12 @@ This package can be installed via go get: `go get code.ivysaur.me/yatwiki`
=CHANGELOG=
2017-10-08 3.1.0
- Feature: Support content upload to a `contented` server
2017-08-11 3.0.2
- Fix an issue with XSS prevention for web browsers other than Chrome
2017-08-11 3.0.1
- Feature: New `TrustXForwardedFor` config option for usage behind reverse proxies
- Fix an issue with article titles containing `+`

View File

@@ -17,7 +17,9 @@ type pageTemplateOptions struct {
LoadCodeResources bool
DefaultPage string
AllowDownload bool
SessionMessage template.HTML
SessionMessage string
PageNotExistsError bool
PageNotExistsTarget string
}
func DefaultPageTemplateOptions(opts *ServerOptions) *pageTemplateOptions {
@@ -105,6 +107,12 @@ function els(e,s){ // no js exec in innerHTML
{{end}}
</div>
<div class="content">
{{if .PageNotExistsError}}
<div class="info">
No such article exists.
<a href="{{.BaseURL}}modify/{{.PageNotExistsTarget | pathcomponent}}">Click here</a> to create it.
</div>
{{end}}
{{if len .SessionMessage}}
<div class="info">{{.SessionMessage}}</div>
{{end}}

View File

@@ -8,12 +8,8 @@ import (
"time"
)
func (this *WikiServer) noSuchArticleError(title string) template.HTML {
return template.HTML(`No such article exists. <a href="` + this.opts.ExpectBaseURL + `modify/` + template.HTMLEscapeString(url.PathEscape(title)) + `">Click here</a> to create it.`)
}
func (this *WikiServer) serveErrorMessage(w http.ResponseWriter, message error) {
this.serveErrorHTMLMessage(w, template.HTML(template.HTMLEscapeString(message.Error())))
func (this *WikiServer) serveErrorMessage(w http.ResponseWriter, err error) {
this.serveErrorText(w, err.Error())
}
func (this *WikiServer) serveInternalError(w http.ResponseWriter, r *http.Request, e error) {
@@ -21,8 +17,12 @@ func (this *WikiServer) serveInternalError(w http.ResponseWriter, r *http.Reques
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) {
this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?error="+url.QueryEscape(string(msg)))
func (this *WikiServer) serveErrorText(w http.ResponseWriter, msg string) {
this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?error="+url.QueryEscape(msg))
}
func (this *WikiServer) serveNoSuchArticle(w http.ResponseWriter, lookingFor string) {
this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?notfound="+url.QueryEscape(lookingFor))
}
func (this *WikiServer) serveRedirect(w http.ResponseWriter, location string) {
@@ -32,7 +32,14 @@ func (this *WikiServer) serveRedirect(w http.ResponseWriter, location string) {
func (this *WikiServer) servePageResponse(w http.ResponseWriter, r *http.Request, pto *pageTemplateOptions) {
w.WriteHeader(200)
pto.SessionMessage = template.HTML(r.URL.Query().Get("error")) // FIXME reflected XSS (although Chrome automatically blocks it..)
if noSuchArticleTarget, ok := r.URL.Query()["notfound"]; ok {
pto.PageNotExistsError = true
pto.PageNotExistsTarget = noSuchArticleTarget[0]
} else {
pto.SessionMessage = r.URL.Query().Get("error")
}
err := this.pageTmp.Execute(w, pto)
if err != nil {

View File

@@ -12,7 +12,7 @@ func (this *WikiServer) routeHistory(w http.ResponseWriter, r *http.Request, art
revs, err := this.db.GetRevisionHistory(articleTitle)
if err != nil {
if err == sql.ErrNoRows {
this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle))
this.serveNoSuchArticle(w, articleTitle)
return
}
@@ -21,7 +21,7 @@ func (this *WikiServer) routeHistory(w http.ResponseWriter, r *http.Request, art
}
if len(revs) == 0 {
this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle))
this.serveNoSuchArticle(w, articleTitle)
return
}

View File

@@ -49,6 +49,25 @@ func (this *WikiServer) routeModify(w http.ResponseWriter, r *http.Request, arti
</label>
<input type="submit" value="Save &raquo;">
| <a href="` + template.HTMLEscapeString(this.opts.ExpectBaseURL+`formatting`) + `" target="_blank">formatting&nbsp;help</a>
`
if len(this.opts.ContentedServer) > 0 {
content += `
<script type="text/javascript" src="` + this.opts.ContentedServer + `jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="` + this.opts.ContentedServer + `sdk.js"></script>
| <a href="javascript:;" id="open-contented-uploader">upload...</a>
<script type="text/javascript">
$("#open-contented-uploader").on('click', function() {
contented.init("#contentctr", function(items) {
for (var i = 0; i < items.length; ++i) {
$("#contentctr textarea").append(" " + "` + this.opts.ContentedServer + `get/" + items[i] + " ");
}
});
});
</script>
`
}
content += `
</div>
<div id="contentctr"><textarea name="content">` + template.HTMLEscapeString(existingBody) + `</textarea></div>
</form>

View File

@@ -19,7 +19,7 @@ func (this *WikiServer) routeView(w http.ResponseWriter, r *http.Request, articl
return
}
this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle))
this.serveNoSuchArticle(w, articleTitle)
return
}
this.serveErrorMessage(w, err)