Added limited support for HTML in posts.

Newlines are now stripped from usernames, topic titles, and emails.
This commit is contained in:
Azareal 2017-12-31 07:01:44 +00:00
parent 0fcc1bc04d
commit 1639d81618
5 changed files with 80 additions and 15 deletions

View File

@ -4,6 +4,7 @@ import (
//"fmt" //"fmt"
"bytes" "bytes"
"html" "html"
"log"
"net/url" "net/url"
"regexp" "regexp"
"strconv" "strconv"
@ -166,28 +167,74 @@ func shortcodeToUnicode(msg string) string {
} }
// TODO: Write tests for this // TODO: Write tests for this
// TODO: Preparse Markdown and normalize it into HTML?
func PreparseMessage(msg string) string { func PreparseMessage(msg string) string {
msg = strings.Replace(msg, "<p><br>", "\n\n", -1) msg = strings.Replace(msg, "<p><br>", "\n\n", -1)
msg = strings.Replace(msg, "<p>", "\n\n", -1) msg = strings.Replace(msg, "<p>", "\n\n", -1)
msg = strings.Replace(msg, "</p>", "", -1) msg = strings.Replace(msg, "</p>", "", -1)
msg = strings.Replace(msg, "<br>", "\n\n", -1) msg = strings.Replace(msg, "<br>", "\n\n", -1)
msg = strings.TrimSpace(msg) // There are a few useful cases for having spaces, but I'd like to stop the WYSIWYG from inserting random lines here and there
if Sshooks["preparse_preassign"] != nil { if Sshooks["preparse_preassign"] != nil {
msg = RunSshook("preparse_preassign", msg) msg = RunSshook("preparse_preassign", msg)
} }
msg = html.EscapeString(msg) msg = html.EscapeString(msg)
/*var runes = []rune(msg)
var runes = []rune(msg)
msg = "" msg = ""
//var inBold = false var inBold = false
//var unclosedBolds = 0 var inItalic = false
var stepForward = func(i int, step int, runes []rune) int {
i += step
if i < len(runes) {
return i
}
return i - step
}
for i := 0; i < len(runes); i++ { for i := 0; i < len(runes); i++ {
char := runes[i] char := runes[i]
if char == '&' && peek(i, 1, runes) == 'l' && peek(i, 2, runes) == 't' && peek(i, 2, runes) == ';' { log.Print("string(char): ", string(char))
i += 2 if char == '&' && peek(i, 1, runes) == 'l' && peek(i, 2, runes) == 't' && peek(i, 3, runes) == ';' {
log.Print("past less than")
i = stepForward(i, 4, runes)
char := runes[i]
if char == '/' {
log.Print("in /")
i = stepForward(i, 1, runes)
char := runes[i]
if inItalic && char == 'e' && peekMatch(i, "m&gt;", runes) {
log.Print("in inItalic")
i += 5
inItalic = false
msg += "</em>"
} else if inBold && char == 's' && peekMatch(i, "trong&gt;", runes) {
log.Print("in inBold")
i += 9
inBold = false
msg += "</strong>"
}
} else if !inItalic && char == 'e' && peekMatch(i, "m&gt;", runes) {
log.Print("in !inItalic")
i += 5
inItalic = true
msg += "<em>"
} else if !inBold && char == 's' && peekMatch(i, "trong&gt;", runes) {
log.Print("in !inBold")
i += 9
inBold = true
msg += "<strong>"
}
} else { } else {
msg += string(char) msg += string(char)
} }
}*/ }
if inItalic {
msg += "</em>"
}
if inBold {
msg += "</strong>"
}
return shortcodeToUnicode(msg) return shortcodeToUnicode(msg)
} }
@ -200,6 +247,19 @@ func peek(cur int, skip int, runes []rune) rune {
return 0 // null byte return 0 // null byte
} }
// TODO: Test this
func peekMatch(cur int, phrase string, runes []rune) bool {
if cur+len(phrase) > len(runes) {
return false
}
for i, char := range phrase {
if runes[cur+i+1] != char {
return false
}
}
return true
}
// TODO: Write a test for this // TODO: Write a test for this
// TODO: We need a lot more hooks here. E.g. To add custom media types and handlers. // TODO: We need a lot more hooks here. E.g. To add custom media types and handlers.
func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/) string { func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/) string {

View File

@ -11,6 +11,7 @@ import (
"html" "html"
"html/template" "html/template"
"strconv" "strconv"
"strings"
"time" "time"
"../query_gen/lib" "../query_gen/lib"
@ -238,7 +239,7 @@ func (topic *Topic) Delete() error {
// TODO: Write tests for this // TODO: Write tests for this
func (topic *Topic) Update(name string, content string) error { func (topic *Topic) Update(name string, content string) error {
name = html.EscapeString(html.UnescapeString(name)) name = html.EscapeString(strings.Replace(html.UnescapeString(name), "\n", "", -1))
content = PreparseMessage(html.UnescapeString(content)) content = PreparseMessage(html.UnescapeString(content))
parsedContent := ParseMessage(content, topic.ParentID, "forums") parsedContent := ParseMessage(content, topic.ParentID, "forums")
_, err := topicStmts.edit.Exec(name, content, parsedContent, topic.ID) _, err := topicStmts.edit.Exec(name, content, parsedContent, topic.ID)

View File

@ -132,7 +132,7 @@ func routeTopicCreateSubmit(w http.ResponseWriter, r *http.Request, user common.
return common.NoPermissions(w, r, user) return common.NoPermissions(w, r, user)
} }
topicName := html.EscapeString(r.PostFormValue("topic-name")) topicName := html.EscapeString(strings.Replace(r.PostFormValue("topic-name"), "\n", "", -1))
content := common.PreparseMessage(r.PostFormValue("topic-content")) content := common.PreparseMessage(r.PostFormValue("topic-content"))
// TODO: Fully parse the post and store it in the parsed column // TODO: Fully parse the post and store it in the parsed column
tid, err := common.Topics.Create(fid, topicName, content, user.ID, user.LastIP) tid, err := common.Topics.Create(fid, topicName, content, user.ID, user.LastIP)
@ -828,7 +828,7 @@ func routeAccountEditUsernameSubmit(w http.ResponseWriter, r *http.Request, user
return ferr return ferr
} }
newUsername := html.EscapeString(r.PostFormValue("account-new-username")) newUsername := html.EscapeString(strings.Replace(r.PostFormValue("account-new-username"), "\n", "", -1))
err := user.ChangeName(newUsername) err := user.ChangeName(newUsername)
if err != nil { if err != nil {
return common.LocalError("Unable to change the username. Does someone else already have this name?", w, r, user) return common.LocalError("Unable to change the username. Does someone else already have this name?", w, r, user)

View File

@ -1039,12 +1039,14 @@ func routePanelUsersEditSubmit(w http.ResponseWriter, r *http.Request, user comm
return common.LocalError("Only administrators can edit the account of other administrators.", w, r, user) return common.LocalError("Only administrators can edit the account of other administrators.", w, r, user)
} }
newname := html.EscapeString(r.PostFormValue("user-name")) newname := html.EscapeString(strings.Replace(r.PostFormValue("user-name"), "\n", "", -1))
if newname == "" { if newname == "" {
return common.LocalError("You didn't put in a username.", w, r, user) return common.LocalError("You didn't put in a username.", w, r, user)
} }
newemail := html.EscapeString(r.PostFormValue("user-email")) // TODO: How should activation factor into admin set emails?
// TODO: How should we handle secondary emails? Do we even have secondary emails implemented?
newemail := html.EscapeString(strings.Replace(r.PostFormValue("user-email"), "\n", "", -1))
if newemail == "" { if newemail == "" {
return common.LocalError("You didn't put in an email address.", w, r, user) return common.LocalError("You didn't put in an email address.", w, r, user)
} }

View File

@ -749,7 +749,8 @@ func routeLoginSubmit(w http.ResponseWriter, r *http.Request, user common.User)
return common.LocalError("Bad Form", w, r, user) return common.LocalError("Bad Form", w, r, user)
} }
uid, err := common.Auth.Authenticate(html.EscapeString(r.PostFormValue("username")), r.PostFormValue("password")) username := html.EscapeString(strings.Replace(r.PostFormValue("username"), "\n", "", -1))
uid, err := common.Auth.Authenticate(username, r.PostFormValue("password"))
if err != nil { if err != nil {
return common.LocalError(err.Error(), w, r, user) return common.LocalError(err.Error(), w, r, user)
} }
@ -808,11 +809,11 @@ func routeRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.Use
if err != nil { if err != nil {
return common.LocalError("Bad Form", w, r, user) return common.LocalError("Bad Form", w, r, user)
} }
username := html.EscapeString(r.PostFormValue("username")) username := html.EscapeString(strings.Replace(r.PostFormValue("username"), "\n", "", -1))
if username == "" { if username == "" {
return common.LocalError("You didn't put in a username.", w, r, user) return common.LocalError("You didn't put in a username.", w, r, user)
} }
email := html.EscapeString(r.PostFormValue("email")) email := html.EscapeString(strings.Replace(r.PostFormValue("email"), "\n", "", -1))
if email == "" { if email == "" {
return common.LocalError("You didn't put in an email.", w, r, user) return common.LocalError("You didn't put in an email.", w, r, user)
} }
@ -827,6 +828,7 @@ func routeRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.Use
return common.LocalError("You can't use your email as your password.", w, r, user) return common.LocalError("You can't use your email as your password.", w, r, user)
} }
// ? Move this into Create()? What if we want to programatically set weak passwords for tests?
err = common.WeakPassword(password) err = common.WeakPassword(password)
if err != nil { if err != nil {
return common.LocalError(err.Error(), w, r, user) return common.LocalError(err.Error(), w, r, user)