Added the AddHashLinkType function so that plugins can add custom hash link types in an efficient manner.
Moved the hashLinkMap, etc. out of ParseMessage so that we can make them more pluggable. The first word in usernames can no longer be purely numeric. Added some ID mention tests.
This commit is contained in:
parent
f6b889b53b
commit
47d1010a53
103
common/parser.go
103
common/parser.go
|
@ -398,6 +398,62 @@ func peekMatch(cur int, phrase string, runes []rune) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ! Not concurrency safe
|
||||||
|
func AddHashLinkType(prefix string, handler func(*strings.Builder, string, *int)) {
|
||||||
|
// There can only be one hash link type starting with a specific character at the moment
|
||||||
|
hashType := hashLinkTypes[prefix[0]]
|
||||||
|
if hashType != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hashLinkMap[prefix] = handler
|
||||||
|
hashLinkTypes[prefix[0]] = prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeURL(sb *strings.Builder, url string, label string) {
|
||||||
|
sb.Write(URLOpen)
|
||||||
|
sb.WriteString(url)
|
||||||
|
sb.Write(URLOpen2)
|
||||||
|
sb.WriteString(label)
|
||||||
|
sb.Write(URLClose)
|
||||||
|
}
|
||||||
|
|
||||||
|
var hashLinkTypes = []string{'t': "tid-", 'r': "rid-", 'f': "fid-"}
|
||||||
|
var hashLinkMap = map[string]func(*strings.Builder, string, *int){
|
||||||
|
"tid-": func(sb *strings.Builder, msg string, i *int) {
|
||||||
|
tid, intLen := CoerceIntString(msg[*i:])
|
||||||
|
*i += intLen
|
||||||
|
|
||||||
|
topic, err := Topics.Get(tid)
|
||||||
|
if err != nil || !Forums.Exists(topic.ParentID) {
|
||||||
|
sb.Write(InvalidTopic)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeURL(sb, BuildTopicURL("", tid), "#tid-"+strconv.Itoa(tid))
|
||||||
|
},
|
||||||
|
"rid-": func(sb *strings.Builder, msg string, i *int) {
|
||||||
|
rid, intLen := CoerceIntString(msg[*i:])
|
||||||
|
*i += intLen
|
||||||
|
|
||||||
|
topic, err := TopicByReplyID(rid)
|
||||||
|
if err != nil || !Forums.Exists(topic.ParentID) {
|
||||||
|
sb.Write(InvalidTopic)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeURL(sb, BuildTopicURL("", topic.ID), "#rid-"+strconv.Itoa(rid))
|
||||||
|
},
|
||||||
|
"fid-": func(sb *strings.Builder, msg string, i *int) {
|
||||||
|
fid, intLen := CoerceIntString(msg[*i:])
|
||||||
|
*i += intLen
|
||||||
|
|
||||||
|
if !Forums.Exists(fid) {
|
||||||
|
sb.Write(InvalidForum)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeURL(sb, BuildForumURL("", fid), "#fid-"+strconv.Itoa(fid))
|
||||||
|
},
|
||||||
|
// TODO: Forum Shortcode Link
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
// TODO: Use templates to reduce the amount of boilerplate?
|
// TODO: Use templates to reduce the amount of boilerplate?
|
||||||
|
@ -427,51 +483,6 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
var lastItem = 0
|
var lastItem = 0
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
||||||
var writeURL = func(url string, label string) {
|
|
||||||
sb.Write(URLOpen)
|
|
||||||
sb.WriteString(url)
|
|
||||||
sb.Write(URLOpen2)
|
|
||||||
sb.WriteString(label)
|
|
||||||
sb.Write(URLClose)
|
|
||||||
}
|
|
||||||
var hashLinkTypes = []string{'t': "tid-", 'r': "rid-", 'f': "fid-"}
|
|
||||||
var hashLinkMap = map[string]func(){
|
|
||||||
"tid-": func() {
|
|
||||||
tid, intLen := CoerceIntString(msg[i:])
|
|
||||||
i += intLen
|
|
||||||
|
|
||||||
topic, err := Topics.Get(tid)
|
|
||||||
if err != nil || !Forums.Exists(topic.ParentID) {
|
|
||||||
sb.Write(InvalidTopic)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeURL(BuildTopicURL("", tid), "#tid-"+strconv.Itoa(tid))
|
|
||||||
},
|
|
||||||
"rid-": func() {
|
|
||||||
rid, intLen := CoerceIntString(msg[i:])
|
|
||||||
i += intLen
|
|
||||||
|
|
||||||
topic, err := TopicByReplyID(rid)
|
|
||||||
if err != nil || !Forums.Exists(topic.ParentID) {
|
|
||||||
sb.Write(InvalidTopic)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeURL(BuildTopicURL("", topic.ID), "#rid-"+strconv.Itoa(rid))
|
|
||||||
},
|
|
||||||
"fid-": func() {
|
|
||||||
fid, intLen := CoerceIntString(msg[i:])
|
|
||||||
i += intLen
|
|
||||||
|
|
||||||
if !Forums.Exists(fid) {
|
|
||||||
sb.Write(InvalidForum)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeURL(BuildForumURL("", fid), "#fid-"+strconv.Itoa(fid))
|
|
||||||
},
|
|
||||||
// TODO: Forum Shortcode Link
|
|
||||||
}
|
|
||||||
|
|
||||||
for ; len(msg) > (i + 1); i++ {
|
for ; len(msg) > (i + 1); i++ {
|
||||||
if (i == 0 && (msg[0] > 32)) || ((msg[i] < 33) && (msg[i+1] > 32)) {
|
if (i == 0 && (msg[0] > 32)) || ((msg[i] < 33) && (msg[i+1] > 32)) {
|
||||||
if (i != 0) || msg[i] < 33 {
|
if (i != 0) || msg[i] < 33 {
|
||||||
|
@ -485,7 +496,7 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||||
if msg[i+1:len(hashType)+1] == hashType {
|
if msg[i+1:len(hashType)+1] == hashType {
|
||||||
sb.WriteString(msg[lastItem:i])
|
sb.WriteString(msg[lastItem:i])
|
||||||
i += len(hashType) + 1
|
i += len(hashType) + 1
|
||||||
hashLinkMap[hashType]()
|
hashLinkMap[hashType](&sb, msg, &i)
|
||||||
lastItem = i
|
lastItem = i
|
||||||
}
|
}
|
||||||
} else if msg[i] == '@' {
|
} else if msg[i] == '@' {
|
||||||
|
|
|
@ -1262,6 +1262,9 @@ func TestParser(t *testing.T) {
|
||||||
msgList = addMETri(msgList, "#tid-1", "<a href='/topic/1'>#tid-1</a>")
|
msgList = addMETri(msgList, "#tid-1", "<a href='/topic/1'>#tid-1</a>")
|
||||||
msgList = addMETri(msgList, "https://github.com/Azareal/Gosora/#tid-1", "<a href='https://github.com/Azareal/Gosora/#tid-1'>https://github.com/Azareal/Gosora/#tid-1</a>")
|
msgList = addMETri(msgList, "https://github.com/Azareal/Gosora/#tid-1", "<a href='https://github.com/Azareal/Gosora/#tid-1'>https://github.com/Azareal/Gosora/#tid-1</a>")
|
||||||
msgList = addMETri(msgList, "#fid-1", "<a href='/forum/1'>#fid-1</a>")
|
msgList = addMETri(msgList, "#fid-1", "<a href='/forum/1'>#fid-1</a>")
|
||||||
|
msgList = addMETri(msgList, "@1", "<a href='/user/admin.1' class='mention'>@Admin</a>")
|
||||||
|
msgList = addMETri(msgList, "@0", "<span style='color: red;'>[Invalid Profile]</span>")
|
||||||
|
msgList = addMETri(msgList, "@-1", "<span style='color: red;'>[Invalid Profile]</span>1")
|
||||||
|
|
||||||
for _, item := range msgList {
|
for _, item := range msgList {
|
||||||
res = common.ParseMessage(item.Msg, 1, "forums")
|
res = common.ParseMessage(item.Msg, 1, "forums")
|
||||||
|
|
|
@ -212,6 +212,15 @@ func AccountRegister(w http.ResponseWriter, r *http.Request, user common.User) c
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isNumeric(data string) (numeric bool) {
|
||||||
|
for _, char := range data {
|
||||||
|
if char < 48 || char > 57 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||||
headerLite, _ := common.SimpleUserCheck(w, r, &user)
|
headerLite, _ := common.SimpleUserCheck(w, r, &user)
|
||||||
|
|
||||||
|
@ -247,6 +256,12 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
|
||||||
regError("You didn't put in an email.", "no-email")
|
regError("You didn't put in an email.", "no-email")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is so a numeric name won't interfere with mentioning a user by ID, there might be a better way of doing this like perhaps !@ to mean IDs and @ to mean usernames in the pre-parser
|
||||||
|
usernameBits := strings.Split(username, " ")
|
||||||
|
if isNumeric(usernameBits[0]) {
|
||||||
|
regError("The first word of your name may not be purely numeric", "numeric-name")
|
||||||
|
}
|
||||||
|
|
||||||
ok := common.HasSuspiciousEmail(email)
|
ok := common.HasSuspiciousEmail(email)
|
||||||
if ok {
|
if ok {
|
||||||
regError("Your email address is suspicious.", "suspicious-email")
|
regError("Your email address is suspicious.", "suspicious-email")
|
||||||
|
|
Loading…
Reference in New Issue