From 1639d816188697e324a29bead66bff1969a73c28 Mon Sep 17 00:00:00 2001 From: Azareal Date: Sun, 31 Dec 2017 07:01:44 +0000 Subject: [PATCH] Added limited support for HTML in posts. Newlines are now stripped from usernames, topic titles, and emails. --- common/parser.go | 74 +++++++++++++++++++++++++++++++++++++++++++----- common/topic.go | 3 +- member_routes.go | 4 +-- panel_routes.go | 6 ++-- routes.go | 8 ++++-- 5 files changed, 80 insertions(+), 15 deletions(-) diff --git a/common/parser.go b/common/parser.go index 8c268291..0bd6bdb4 100644 --- a/common/parser.go +++ b/common/parser.go @@ -4,6 +4,7 @@ import ( //"fmt" "bytes" "html" + "log" "net/url" "regexp" "strconv" @@ -166,28 +167,74 @@ func shortcodeToUnicode(msg string) string { } // TODO: Write tests for this +// TODO: Preparse Markdown and normalize it into HTML? func PreparseMessage(msg string) string { msg = strings.Replace(msg, "


", "\n\n", -1) msg = strings.Replace(msg, "

", "\n\n", -1) msg = strings.Replace(msg, "

", "", -1) msg = strings.Replace(msg, "
", "\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 { msg = RunSshook("preparse_preassign", msg) } msg = html.EscapeString(msg) - /*var runes = []rune(msg) + + var runes = []rune(msg) msg = "" - //var inBold = false - //var unclosedBolds = 0 + var inBold = false + 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++ { char := runes[i] - if char == '&' && peek(i, 1, runes) == 'l' && peek(i, 2, runes) == 't' && peek(i, 2, runes) == ';' { - i += 2 - + log.Print("string(char): ", string(char)) + 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>", runes) { + log.Print("in inItalic") + i += 5 + inItalic = false + msg += "" + } else if inBold && char == 's' && peekMatch(i, "trong>", runes) { + log.Print("in inBold") + i += 9 + inBold = false + msg += "" + } + } else if !inItalic && char == 'e' && peekMatch(i, "m>", runes) { + log.Print("in !inItalic") + i += 5 + inItalic = true + msg += "" + } else if !inBold && char == 's' && peekMatch(i, "trong>", runes) { + log.Print("in !inBold") + i += 9 + inBold = true + msg += "" + } } else { msg += string(char) } - }*/ + } + + if inItalic { + msg += "" + } + if inBold { + msg += "" + } + return shortcodeToUnicode(msg) } @@ -200,6 +247,19 @@ func peek(cur int, skip int, runes []rune) rune { 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: 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 { diff --git a/common/topic.go b/common/topic.go index 6784bb75..6b69692e 100644 --- a/common/topic.go +++ b/common/topic.go @@ -11,6 +11,7 @@ import ( "html" "html/template" "strconv" + "strings" "time" "../query_gen/lib" @@ -238,7 +239,7 @@ func (topic *Topic) Delete() error { // TODO: Write tests for this 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)) parsedContent := ParseMessage(content, topic.ParentID, "forums") _, err := topicStmts.edit.Exec(name, content, parsedContent, topic.ID) diff --git a/member_routes.go b/member_routes.go index 2ed3ce5d..c5498787 100644 --- a/member_routes.go +++ b/member_routes.go @@ -132,7 +132,7 @@ func routeTopicCreateSubmit(w http.ResponseWriter, r *http.Request, user common. 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")) // TODO: Fully parse the post and store it in the parsed column 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 } - newUsername := html.EscapeString(r.PostFormValue("account-new-username")) + newUsername := html.EscapeString(strings.Replace(r.PostFormValue("account-new-username"), "\n", "", -1)) err := user.ChangeName(newUsername) if err != nil { return common.LocalError("Unable to change the username. Does someone else already have this name?", w, r, user) diff --git a/panel_routes.go b/panel_routes.go index 3c7aa05e..28acdc0c 100644 --- a/panel_routes.go +++ b/panel_routes.go @@ -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) } - newname := html.EscapeString(r.PostFormValue("user-name")) + newname := html.EscapeString(strings.Replace(r.PostFormValue("user-name"), "\n", "", -1)) if newname == "" { 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 == "" { return common.LocalError("You didn't put in an email address.", w, r, user) } diff --git a/routes.go b/routes.go index e9671d2a..a2c5bb1a 100644 --- a/routes.go +++ b/routes.go @@ -749,7 +749,8 @@ func routeLoginSubmit(w http.ResponseWriter, r *http.Request, user common.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 { 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 { 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 == "" { 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 == "" { 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) } + // ? Move this into Create()? What if we want to programatically set weak passwords for tests? err = common.WeakPassword(password) if err != nil { return common.LocalError(err.Error(), w, r, user)