Use a Go 1.10 String Builder instead of byte slices in ParseMessage.

Removed a couple of unnecessary lines from global.js
This commit is contained in:
Azareal 2018-09-20 11:51:18 +10:00
parent 5d4013f500
commit 46f03775c9
3 changed files with 98 additions and 114 deletions

View File

@ -421,195 +421,184 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
for _, filter := range wordFilters { for _, filter := range wordFilters {
msg = strings.Replace(msg, filter.Find, filter.Replacement, -1) msg = strings.Replace(msg, filter.Find, filter.Replacement, -1)
} }
msg += " "
// Search for URLs, mentions and hashlinks in the messages... // Search for URLs, mentions and hashlinks in the messages...
var msgbytes = []byte(msg) //var msgbytes = []byte(msg)
var outbytes []byte //var outbytes []byte
msgbytes = append(msgbytes, SpaceGap...) //msgbytes = append(msgbytes, SpaceGap...)
var sb strings.Builder
var lastItem = 0 var lastItem = 0
var i = 0 var i = 0
// TODO: Use a bytes buffer or a string builder here for ; len(msg) > (i + 1); i++ {
for ; len(msgbytes) > (i + 1); i++ { if (i == 0 && (msg[0] > 32)) || ((msg[i] < 33) && (msg[i+1] > 32)) {
if (i == 0 && (msgbytes[0] > 32)) || ((msgbytes[i] < 33) && (msgbytes[i+1] > 32)) { if (i != 0) || msg[i] < 33 {
if (i != 0) || msgbytes[i] < 33 {
i++ i++
} }
if msg[i] == '#' {
if msgbytes[i] == '#' { if msg[i+1:i+5] == "tid-" {
if bytes.Equal(msgbytes[i+1:i+5], []byte("tid-")) { sb.WriteString(msg[lastItem:i])
outbytes = append(outbytes, msgbytes[lastItem:i]...)
i += 5 i += 5
start := i start := i
tid, intLen := CoerceIntBytes(msgbytes[start:]) tid, intLen := CoerceIntString(msg[start:])
i += intLen i += intLen
topic, err := Topics.Get(tid) topic, err := Topics.Get(tid)
if err != nil || !Forums.Exists(topic.ParentID) { if err != nil || !Forums.Exists(topic.ParentID) {
outbytes = append(outbytes, InvalidTopic...) sb.Write(InvalidTopic)
lastItem = i lastItem = i
continue continue
} }
outbytes = append(outbytes, URLOpen...) sb.Write(URLOpen)
var urlBit = []byte(BuildTopicURL("", tid)) sb.WriteString(BuildTopicURL("", tid))
outbytes = append(outbytes, urlBit...) sb.Write(URLOpen2)
outbytes = append(outbytes, URLOpen2...) sb.WriteString("#tid-" + strconv.Itoa(tid))
var tidBit = []byte("#tid-" + strconv.Itoa(tid)) sb.Write(URLClose)
outbytes = append(outbytes, tidBit...)
outbytes = append(outbytes, URLClose...)
lastItem = i lastItem = i
} else if bytes.Equal(msgbytes[i+1:i+5], []byte("rid-")) { } else if msg[i+1:i+5] == "rid-" {
outbytes = append(outbytes, msgbytes[lastItem:i]...) sb.WriteString(msg[lastItem:i])
i += 5 i += 5
start := i start := i
rid, intLen := CoerceIntBytes(msgbytes[start:]) rid, intLen := CoerceIntString(msg[start:])
i += intLen i += intLen
topic, err := TopicByReplyID(rid) topic, err := TopicByReplyID(rid)
if err != nil || !Forums.Exists(topic.ParentID) { if err != nil || !Forums.Exists(topic.ParentID) {
outbytes = append(outbytes, InvalidTopic...) sb.Write(InvalidTopic)
lastItem = i lastItem = i
continue continue
} }
outbytes = append(outbytes, URLOpen...) sb.Write(URLOpen)
var urlBit = []byte(BuildTopicURL("", topic.ID)) sb.WriteString(BuildTopicURL("", topic.ID))
outbytes = append(outbytes, urlBit...) sb.Write(URLOpen2)
outbytes = append(outbytes, URLOpen2...) sb.WriteString("#rid-" + strconv.Itoa(rid))
var ridBit = []byte("#rid-" + strconv.Itoa(rid)) sb.Write(URLClose)
outbytes = append(outbytes, ridBit...)
outbytes = append(outbytes, URLClose...)
lastItem = i lastItem = i
} else if bytes.Equal(msgbytes[i+1:i+5], []byte("fid-")) { } else if msg[i+1:i+5] == "fid-" {
outbytes = append(outbytes, msgbytes[lastItem:i]...) sb.WriteString(msg[lastItem:i])
i += 5 i += 5
start := i start := i
fid, intLen := CoerceIntBytes(msgbytes[start:]) fid, intLen := CoerceIntString(msg[start:])
i += intLen i += intLen
if !Forums.Exists(fid) { if !Forums.Exists(fid) {
outbytes = append(outbytes, InvalidForum...) sb.Write(InvalidForum)
lastItem = i lastItem = i
continue continue
} }
outbytes = append(outbytes, URLOpen...) sb.Write(URLOpen)
var urlBit = []byte(BuildForumURL("", fid)) sb.WriteString(BuildForumURL("", fid))
outbytes = append(outbytes, urlBit...) sb.Write(URLOpen2)
outbytes = append(outbytes, URLOpen2...) sb.WriteString("#fid-" + strconv.Itoa(fid))
var fidBit = []byte("#fid-" + strconv.Itoa(fid)) sb.Write(URLClose)
outbytes = append(outbytes, fidBit...)
outbytes = append(outbytes, URLClose...)
lastItem = i lastItem = i
} else { } else {
// TODO: Forum Shortcode Link // TODO: Forum Shortcode Link
} }
} else if msgbytes[i] == '@' { } else if msg[i] == '@' {
outbytes = append(outbytes, msgbytes[lastItem:i]...) sb.WriteString(msg[lastItem:i])
i++ i++
start := i start := i
uid, intLen := CoerceIntBytes(msgbytes[start:]) uid, intLen := CoerceIntString(msg[start:])
i += intLen i += intLen
menUser, err := Users.Get(uid) menUser, err := Users.Get(uid)
if err != nil { if err != nil {
outbytes = append(outbytes, InvalidProfile...) sb.Write(InvalidProfile)
lastItem = i lastItem = i
continue continue
} }
outbytes = append(outbytes, URLOpen...) sb.Write(URLOpen)
var urlBit = []byte(menUser.Link) sb.WriteString(menUser.Link)
outbytes = append(outbytes, urlBit...) sb.Write(bytesSinglequote)
outbytes = append(outbytes, bytesSinglequote...) sb.Write(urlMention)
outbytes = append(outbytes, urlMention...) sb.Write(bytesGreaterthan)
outbytes = append(outbytes, bytesGreaterthan...) sb.WriteString("@" + menUser.Name)
var uidBit = []byte("@" + menUser.Name) sb.Write(URLClose)
outbytes = append(outbytes, uidBit...)
outbytes = append(outbytes, URLClose...)
lastItem = i lastItem = i
} else if msgbytes[i] == 'h' || msgbytes[i] == 'f' || msgbytes[i] == 'g' || msgbytes[i] == '/' { } else if msg[i] == 'h' || msg[i] == 'f' || msg[i] == 'g' || msg[i] == '/' {
if msgbytes[i+1] == 't' && msgbytes[i+2] == 't' && msgbytes[i+3] == 'p' { if msg[i+1] == 't' && msg[i+2] == 't' && msg[i+3] == 'p' {
if msgbytes[i+4] == 's' && msgbytes[i+5] == ':' && msgbytes[i+6] == '/' { if msg[i+4] == 's' && msg[i+5] == ':' && msg[i+6] == '/' {
// Do nothing // Do nothing
} else if msgbytes[i+4] == ':' && msgbytes[i+5] == '/' { } else if msg[i+4] == ':' && msg[i+5] == '/' {
// Do nothing // Do nothing
} else { } else {
continue continue
} }
} else if msgbytes[i+1] == 't' && msgbytes[i+2] == 'p' && msgbytes[i+3] == ':' && msgbytes[i+4] == '/' { } else if msg[i+1] == 't' && msg[i+2] == 'p' && msg[i+3] == ':' && msg[i+4] == '/' {
// Do nothing // Do nothing
} else if msgbytes[i+1] == 'i' && msgbytes[i+2] == 't' && msgbytes[i+3] == ':' && msgbytes[i+4] == '/' { } else if msg[i+1] == 'i' && msg[i+2] == 't' && msg[i+3] == ':' && msg[i+4] == '/' {
// Do nothing // Do nothing
} else if msgbytes[i+1] == '/' { } else if msg[i+1] == '/' {
// Do nothing // Do nothing
} else { } else {
continue continue
} }
//log.Print("Normal URL") sb.WriteString(msg[lastItem:i])
outbytes = append(outbytes, msgbytes[lastItem:i]...) urlLen := PartialURLStringLen(msg[i:])
urlLen := PartialURLBytesLen(msgbytes[i:]) if msg[i+urlLen] > 32 { // space and invisibles
if msgbytes[i+urlLen] > 32 { // space and invisibles sb.Write(InvalidURL)
//log.Print("INVALID URL")
outbytes = append(outbytes, InvalidURL...)
i += urlLen i += urlLen
continue continue
} }
media, ok := parseMediaBytes(msgbytes[i : i+urlLen]) media, ok := parseMediaString(msg[i : i+urlLen])
if !ok { if !ok {
outbytes = append(outbytes, InvalidURL...) sb.Write(InvalidURL)
i += urlLen i += urlLen
continue continue
} }
var addImage = func(url string) { var addImage = func(url string) {
outbytes = append(outbytes, imageOpen...) sb.Write(imageOpen)
outbytes = append(outbytes, []byte(url)...) sb.WriteString(url)
outbytes = append(outbytes, imageOpen2...) sb.Write(imageOpen2)
outbytes = append(outbytes, []byte(url)...) sb.WriteString(url)
outbytes = append(outbytes, imageClose...) sb.Write(imageClose)
i += urlLen i += urlLen
lastItem = i lastItem = i
} }
// TODO: Reduce the amount of code duplication // TODO: Reduce the amount of code duplication
if media.Type == "attach" { if media.Type == "attach" {
addImage(media.URL+"?sectionID="+strconv.Itoa(sectionID)+"&sectionType="+sectionType) addImage(media.URL + "?sectionID=" + strconv.Itoa(sectionID) + "&sectionType=" + sectionType)
continue continue
} else if media.Type == "image" { } else if media.Type == "image" {
addImage(media.URL) addImage(media.URL)
continue continue
} else if media.Type == "raw" { } else if media.Type == "raw" {
outbytes = append(outbytes, []byte(media.Body)...) sb.WriteString(media.Body)
i += urlLen i += urlLen
lastItem = i lastItem = i
continue continue
} else if media.Type != "" { } else if media.Type != "" {
outbytes = append(outbytes, unknownMedia...) sb.Write(unknownMedia)
i += urlLen i += urlLen
continue continue
} }
outbytes = append(outbytes, URLOpen...) sb.Write(URLOpen)
outbytes = append(outbytes, msgbytes[i:i+urlLen]...) sb.WriteString(msg[i : i+urlLen])
outbytes = append(outbytes, URLOpen2...) sb.Write(URLOpen2)
outbytes = append(outbytes, msgbytes[i:i+urlLen]...) sb.WriteString(msg[i : i+urlLen])
outbytes = append(outbytes, URLClose...) sb.Write(URLClose)
i += urlLen i += urlLen
lastItem = i lastItem = i
} }
} }
} }
if lastItem != i && sb.Len() != 0 {
if lastItem != i && len(outbytes) != 0 { calclen := len(msg) - 10
calclen := len(msgbytes) - 10
if calclen <= lastItem { if calclen <= lastItem {
calclen = lastItem calclen = lastItem
} }
outbytes = append(outbytes, msgbytes[lastItem:calclen]...) sb.WriteString(msg[lastItem:calclen])
msg = string(outbytes) msg = sb.String()
} }
msg = strings.Replace(msg, "\n", "<br>", -1) msg = strings.Replace(msg, "\n", "<br>", -1)
@ -620,16 +609,16 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
// 6, 7, 8, 6, 2, 7 // 6, 7, 8, 6, 2, 7
// ftp://, http://, https:// git://, //, mailto: (not a URL, just here for length comparison purposes) // ftp://, http://, https:// git://, //, mailto: (not a URL, just here for length comparison purposes)
// TODO: Write a test for this // TODO: Write a test for this
func validateURLBytes(data []byte) bool { func validateURLString(data string) bool {
datalen := len(data) datalen := len(data)
i := 0 i := 0
if datalen >= 6 { if datalen >= 6 {
if bytes.Equal(data[0:6], []byte("ftp://")) || bytes.Equal(data[0:6], []byte("git://")) { if data[0:6] == "ftp://" || data[0:6] == "git://" {
i = 6 i = 6
} else if datalen >= 7 && bytes.Equal(data[0:7], httpProtBytes) { } else if datalen >= 7 && data[0:7] == "http://" {
i = 7 i = 7
} else if datalen >= 8 && bytes.Equal(data[0:8], []byte("https://")) { } else if datalen >= 8 && data[0:8] == "https://" {
i = 8 i = 8
} }
} else if datalen >= 2 && data[0] == '/' && data[1] == '/' { } else if datalen >= 2 && data[0] == '/' && data[1] == '/' {
@ -674,17 +663,17 @@ func validatedURLBytes(data []byte) (url []byte) {
} }
// TODO: Write a test for this // TODO: Write a test for this
func PartialURLBytes(data []byte) (url []byte) { func PartialURLString(data string) (url []byte) {
datalen := len(data) datalen := len(data)
i := 0 i := 0
end := datalen - 1 end := datalen - 1
if datalen >= 6 { if datalen >= 6 {
if bytes.Equal(data[0:6], []byte("ftp://")) || bytes.Equal(data[0:6], []byte("git://")) { if data[0:6] == "ftp://" || data[0:6] == "git://" {
i = 6 i = 6
} else if datalen >= 7 && bytes.Equal(data[0:7], httpProtBytes) { } else if datalen >= 7 && data[0:7] == "http://" {
i = 7 i = 7
} else if datalen >= 8 && bytes.Equal(data[0:8], []byte("https://")) { } else if datalen >= 8 && data[0:8] == "https://" {
i = 8 i = 8
} }
} else if datalen >= 2 && data[0] == '/' && data[1] == '/' { } else if datalen >= 2 && data[0] == '/' && data[1] == '/' {
@ -698,22 +687,22 @@ func PartialURLBytes(data []byte) (url []byte) {
} }
} }
url = append(url, data[0:end]...) url = append(url, []byte(data[0:end])...)
return url return url
} }
// TODO: Write a test for this // TODO: Write a test for this
func PartialURLBytesLen(data []byte) int { func PartialURLStringLen(data string) int {
datalen := len(data) datalen := len(data)
i := 0 i := 0
if datalen >= 6 { if datalen >= 6 {
//log.Print(string(data[0:5])) //log.Print(string(data[0:5]))
if bytes.Equal(data[0:6], []byte("ftp://")) || bytes.Equal(data[0:6], []byte("git://")) { if data[0:6] == "ftp://" || data[0:6] == "git://" {
i = 6 i = 6
} else if datalen >= 7 && bytes.Equal(data[0:7], httpProtBytes) { } else if datalen >= 7 && data[0:7] == "http://" {
i = 7 i = 7
} else if datalen >= 8 && bytes.Equal(data[0:8], []byte("https://")) { } else if datalen >= 8 && data[0:8] == "https://" {
i = 8 i = 8
} }
} else if datalen >= 2 && data[0] == '/' && data[1] == '/' { } else if datalen >= 2 && data[0] == '/' && data[1] == '/' {
@ -738,11 +727,11 @@ type MediaEmbed struct {
} }
// TODO: Write a test for this // TODO: Write a test for this
func parseMediaBytes(data []byte) (media MediaEmbed, ok bool) { func parseMediaString(data string) (media MediaEmbed, ok bool) {
if !validateURLBytes(data) { if !validateURLString(data) {
return media, false return media, false
} }
url, err := parseURL(data) url, err := url.Parse(data)
if err != nil { if err != nil {
return media, false return media, false
} }
@ -813,12 +802,8 @@ func parseMediaBytes(data []byte) (media MediaEmbed, ok bool) {
return media, true return media, true
} }
func parseURL(data []byte) (*url.URL, error) {
return url.Parse(string(data))
}
// TODO: Write a test for this // TODO: Write a test for this
func CoerceIntBytes(data []byte) (res int, length int) { func CoerceIntString(data string) (res int, length int) {
if !(data[0] > 47 && data[0] < 58) { if !(data[0] > 47 && data[0] < 58) {
return 0, 1 return 0, 1
} }
@ -826,7 +811,7 @@ func CoerceIntBytes(data []byte) (res int, length int) {
i := 0 i := 0
for ; len(data) > i; i++ { for ; len(data) > i; i++ {
if !(data[i] > 47 && data[i] < 58) { if !(data[i] > 47 && data[i] < 58) {
conv, err := strconv.Atoi(string(data[0:i])) conv, err := strconv.Atoi(data[0:i])
if err != nil { if err != nil {
return 0, i return 0, i
} }
@ -834,7 +819,7 @@ func CoerceIntBytes(data []byte) (res int, length int) {
} }
} }
conv, err := strconv.Atoi(string(data)) conv, err := strconv.Atoi(data)
if err != nil { if err != nil {
return 0, i return 0, i
} }

View File

@ -332,11 +332,12 @@ func bbcodeFullParse(msg string) string {
return msg return msg
} }
// TODO: Strip the containing [url] so the media parser can work it's magic instead? Or do we want to allow something like [url=]label[/url] here?
func bbcodeParseURL(i int, start int, lastTag int, msgbytes []byte, outbytes []byte) (int, int, int, []byte) { func bbcodeParseURL(i int, start int, lastTag int, msgbytes []byte, outbytes []byte) (int, int, int, []byte) {
start = i + 5 start = i + 5
outbytes = append(outbytes, msgbytes[lastTag:i]...) outbytes = append(outbytes, msgbytes[lastTag:i]...)
i = start i = start
i += common.PartialURLBytesLen(msgbytes[start:]) i += common.PartialURLStringLen(string(msgbytes[start:]))
if !bytes.Equal(msgbytes[i:i+6], []byte("[/url]")) { if !bytes.Equal(msgbytes[i:i+6], []byte("[/url]")) {
outbytes = append(outbytes, common.InvalidURL...) outbytes = append(outbytes, common.InvalidURL...)
return i, start, lastTag, outbytes return i, start, lastTag, outbytes

View File

@ -222,8 +222,6 @@ function runWebSockets() {
alertList.splice(alertList.length-1,1); alertList.splice(alertList.length-1,1);
delete alertMapping[key]; delete alertMapping[key];
// TODO: Add support for other alert feeds like PM Alerts // TODO: Add support for other alert feeds like PM Alerts
var generalAlerts = document.getElementById("general_alerts"); var generalAlerts = document.getElementById("general_alerts");
if(alertList.length < 8) { if(alertList.length < 8) {