gosora/plugin_bbcode.go
Azareal e30707bc17 Refactored the installer's code. We're moving towards supporting multiple database engines.
More progress has been made with PostgreSQL, but it's still incomplete and experimental.
The items on the Social Group menu bar are no longer decorative and now let you jump from page to page.
Social Group permissions are now fully functional. More features to come like privacy levels, secondary board permissions, etc. for Social Groups.

One of our dependencies added a dependecy, so we've added that dependency as a dependency.
Tweaked the ForumStore to better conform to the tests.
Fixed an issue with the generated file comment stopping the build tags from being read by the compiler for a few files.
Fixed the test system.
Renamed the route_create_topic handler to route_topic_create_submit
Moved the user table into the query generator.
Fixed a bug in MySQL where it doesn't allow unique keys longer than 180 characters.
Fixed a race condition in the forum deletion handler.
Fixed a crash bug where Gosora crashes when [rand]0[/rand] is passed to the BBCode parser.
Fixed a bug with superadmins not being able to see all the forums they should be able to.
Fixed a bug in simple_forum_session_check where it assumes every request has an error.

Tests:
Added 8 ForumStore tests.
Added 4 Auth tests.
Added 14 bbcode_full_parse tests.
Added 4 bbcode_regex_parse tests.
Fixed a bug in one of the bbcode_full_parse tests.

Apparently, routes.go wasn't commited in the previous commit o_o
2017-07-12 12:05:18 +01:00

417 lines
12 KiB
Go

package main
//import "log"
//import "fmt"
import "bytes"
//import "strings"
import "strconv"
import "regexp"
import "time"
import "math/rand"
var random *rand.Rand
var bbcode_invalid_number []byte
var bbcode_no_negative []byte
var bbcode_missing_tag []byte
var bbcode_bold *regexp.Regexp
var bbcode_italic *regexp.Regexp
var bbcode_underline *regexp.Regexp
var bbcode_strikethrough *regexp.Regexp
var bbcode_url *regexp.Regexp
var bbcode_url_label *regexp.Regexp
var bbcode_quotes *regexp.Regexp
var bbcode_code *regexp.Regexp
func init() {
plugins["bbcode"] = NewPlugin("bbcode","BBCode","Azareal","http://github.com/Azareal","","","",init_bbcode,nil,deactivate_bbcode,nil,nil)
}
func init_bbcode() error {
//plugins["bbcode"].AddHook("parse_assign", bbcode_parse_without_code)
plugins["bbcode"].AddHook("parse_assign", bbcode_full_parse)
bbcode_invalid_number = []byte("<span style='color: red;'>[Invalid Number]</span>")
bbcode_no_negative = []byte("<span style='color: red;'>[No Negative Numbers]</span>")
bbcode_missing_tag = []byte("<span style='color: red;'>[Missing Tag]</span>")
bbcode_bold = regexp.MustCompile(`(?s)\[b\](.*)\[/b\]`)
bbcode_italic = regexp.MustCompile(`(?s)\[i\](.*)\[/i\]`)
bbcode_underline = regexp.MustCompile(`(?s)\[u\](.*)\[/u\]`)
bbcode_strikethrough = regexp.MustCompile(`(?s)\[s\](.*)\[/s\]`)
urlpattern := `(http|https|ftp|mailto*)(:??)\/\/([\.a-zA-Z\/]+)`
bbcode_url = regexp.MustCompile(`\[url\]` + urlpattern + `\[/url\]`)
bbcode_url_label = regexp.MustCompile(`(?s)\[url=` + urlpattern + `\](.*)\[/url\]`)
bbcode_quotes = regexp.MustCompile(`\[quote\](.*)\[/quote\]`)
bbcode_code = regexp.MustCompile(`\[code\](.*)\[/code\]`)
random = rand.New(rand.NewSource(time.Now().UnixNano()))
return nil
}
func deactivate_bbcode() {
//plugins["bbcode"].RemoveHook("parse_assign", bbcode_parse_without_code)
plugins["bbcode"].RemoveHook("parse_assign", bbcode_full_parse)
}
func bbcode_regex_parse(msg string) string {
msg = bbcode_bold.ReplaceAllString(msg,"<b>$1</b>")
msg = bbcode_italic.ReplaceAllString(msg,"<i>$1</i>")
msg = bbcode_underline.ReplaceAllString(msg,"<u>$1</u>")
msg = bbcode_strikethrough.ReplaceAllString(msg,"<s>$1</s>")
msg = bbcode_url.ReplaceAllString(msg,"<a href=''$1$2//$3' rel='nofollow'>$1$2//$3</i>")
msg = bbcode_url_label.ReplaceAllString(msg,"<a href=''$1$2//$3' rel='nofollow'>$4</i>")
msg = bbcode_quotes.ReplaceAllString(msg,"<span class='postQuote'>$1</span>")
//msg = bbcode_code.ReplaceAllString(msg,"<span class='codequotes'>$1</span>")
return msg
}
// Only does the simple BBCode like [u], [b], [i] and [s]
func bbcode_simple_parse(msg string) string {
var has_u, has_b, has_i, has_s bool
msgbytes := []byte(msg)
for i := 0; (i + 2) < len(msgbytes); i++ {
if msgbytes[i] == '[' && msgbytes[i + 2] == ']' {
if msgbytes[i + 1] == 'b' && !has_b {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_b = true
} else if msgbytes[i + 1] == 'i' && !has_i {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_i = true
} else if msgbytes[i + 1] == 'u' && !has_u {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_u = true
} else if msgbytes[i + 1] == 's' && !has_s {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_s = true
}
i += 2
}
}
// There's an unclosed tag in there x.x
if has_i || has_u || has_b || has_s {
close_under := []byte("</u>")
close_italic := []byte("</i>")
close_bold := []byte("</b>")
close_strike := []byte("</s>")
if has_i {
msgbytes = append(msgbytes, close_italic...)
}
if has_u {
msgbytes = append(msgbytes, close_under...)
}
if has_b {
msgbytes = append(msgbytes, close_bold...)
}
if has_s {
msgbytes = append(msgbytes, close_strike...)
}
}
return string(msgbytes)
}
// Here for benchmarking purposes. Might add a plugin setting for disabling [code] as it has it's paws everywhere
func bbcode_parse_without_code(msg string) string {
var has_u, has_b, has_i, has_s bool
var complex_bbc bool
msgbytes := []byte(msg)
for i := 0; (i + 3) < len(msgbytes); i++ {
if msgbytes[i] == '[' {
if msgbytes[i + 2] != ']' {
if msgbytes[i + 1] == '/' {
if msgbytes[i + 3] == ']' {
if msgbytes[i + 2] == 'b' {
msgbytes[i] = '<'
msgbytes[i + 3] = '>'
has_b = false
} else if msgbytes[i + 2] == 'i' {
msgbytes[i] = '<'
msgbytes[i + 3] = '>'
has_i = false
} else if msgbytes[i + 2] == 'u' {
msgbytes[i] = '<'
msgbytes[i + 3] = '>'
has_u = false
} else if msgbytes[i + 2] == 's' {
msgbytes[i] = '<'
msgbytes[i + 3] = '>'
has_s = false
}
i += 3
} else {
complex_bbc = true
}
} else {
complex_bbc = true
}
} else {
if msgbytes[i + 1] == 'b' && !has_b {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_b = true
} else if msgbytes[i + 1] == 'i' && !has_i {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_i = true
} else if msgbytes[i + 1] == 'u' && !has_u {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_u = true
} else if msgbytes[i + 1] == 's' && !has_s {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_s = true
}
i += 2
}
}
}
// There's an unclosed tag in there x.x
if has_i || has_u || has_b || has_s {
close_under := []byte("</u>")
close_italic := []byte("</i>")
close_bold := []byte("</b>")
close_strike := []byte("</s>")
if has_i {
msgbytes = append(bytes.TrimSpace(msgbytes), close_italic...)
}
if has_u {
msgbytes = append(bytes.TrimSpace(msgbytes), close_under...)
}
if has_b {
msgbytes = append(bytes.TrimSpace(msgbytes), close_bold...)
}
if has_s {
msgbytes = append(bytes.TrimSpace(msgbytes), close_strike...)
}
}
// Copy the new complex parser over once the rough edges have been smoothed over
if complex_bbc {
msg = bbcode_url.ReplaceAllString(msg,"<a href='$1$2//$3' rel='nofollow'>$1$2//$3</i>")
msg = bbcode_url_label.ReplaceAllString(msg,"<a href='$1$2//$3' rel='nofollow'>$4</i>")
msg = bbcode_quotes.ReplaceAllString(msg,"<span class='postQuote'>$1</span>")
msg = bbcode_code.ReplaceAllString(msg,"<span class='codequotes'>$1</span>")
}
return string(msgbytes)
}
// Does every type of BBCode
func bbcode_full_parse(msg string) string {
var has_u, has_b, has_i, has_s, has_c bool
var complex_bbc bool
msgbytes := []byte(msg)
msgbytes = append(msgbytes,space_gap...)
//fmt.Println("BBCode Simple Pre:")
//fmt.Println("`"+string(msgbytes)+"`")
//fmt.Println("----")
for i := 0; i < len(msgbytes); i++ {
if msgbytes[i] == '[' {
if msgbytes[i + 2] != ']' {
if msgbytes[i + 1] == '/' {
if msgbytes[i + 3] == ']' {
if !has_c {
if msgbytes[i + 2] == 'b' {
msgbytes[i] = '<'
msgbytes[i + 3] = '>'
has_b = false
} else if msgbytes[i + 2] == 'i' {
msgbytes[i] = '<'
msgbytes[i + 3] = '>'
has_i = false
} else if msgbytes[i + 2] == 'u' {
msgbytes[i] = '<'
msgbytes[i + 3] = '>'
has_u = false
} else if msgbytes[i + 2] == 's' {
msgbytes[i] = '<'
msgbytes[i + 3] = '>'
has_s = false
}
i += 3
}
} else {
if msgbytes[i+2] == 'c' && msgbytes[i+3] == 'o' && msgbytes[i+4] == 'd' && msgbytes[i+5] == 'e' && msgbytes[i+6] == ']' {
has_c = false
i += 7
}
//if msglen >= (i+6) {
// fmt.Println("boo")
// fmt.Println(msglen)
// fmt.Println(i+6)
// fmt.Println(string(msgbytes[i:i+6]))
//}
complex_bbc = true
}
} else {
if msgbytes[i+1] == 'c' && msgbytes[i+2] == 'o' && msgbytes[i+3] == 'd' && msgbytes[i+4] == 'e' && msgbytes[i+5] == ']' {
has_c = true
i += 6
}
//if msglen >= (i+5) {
// fmt.Println("boo2")
// fmt.Println(string(msgbytes[i:i+5]))
//}
complex_bbc = true
}
} else if !has_c {
if msgbytes[i + 1] == 'b' && !has_b {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_b = true
} else if msgbytes[i + 1] == 'i' && !has_i {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_i = true
} else if msgbytes[i + 1] == 'u' && !has_u {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_u = true
} else if msgbytes[i + 1] == 's' && !has_s {
msgbytes[i] = '<'
msgbytes[i + 2] = '>'
has_s = true
}
i += 2
}
}
}
// There's an unclosed tag in there somewhere x.x
if has_i || has_u || has_b || has_s {
close_under := []byte("</u>")
close_italic := []byte("</i>")
close_bold := []byte("</b>")
close_strike := []byte("</s>")
if has_i {
msgbytes = append(bytes.TrimSpace(msgbytes), close_italic...)
}
if has_u {
msgbytes = append(bytes.TrimSpace(msgbytes), close_under...)
}
if has_b {
msgbytes = append(bytes.TrimSpace(msgbytes), close_bold...)
}
if has_s {
msgbytes = append(bytes.TrimSpace(msgbytes), close_strike...)
}
msgbytes = append(msgbytes,space_gap...)
}
if complex_bbc {
i := 0
var start, lastTag int
var outbytes []byte
//fmt.Println("BBCode Pre:")
//fmt.Println("`"+string(msgbytes)+"`")
//fmt.Println("----")
for ; i < len(msgbytes); i++ {
MainLoop:
if msgbytes[i] == '[' {
OuterComplex:
if msgbytes[i + 1] == 'u' {
if msgbytes[i+2] == 'r' && msgbytes[i+3] == 'l' && msgbytes[i+4] == ']' {
start = i + 5
outbytes = append(outbytes, msgbytes[lastTag:i]...)
i = start
i += partial_url_bytes_len(msgbytes[start:])
//fmt.Println("Partial Bytes:")
//fmt.Println(string(msgbytes[start:]))
//fmt.Println("-----")
if !bytes.Equal(msgbytes[i:i+6],[]byte("[/url]")) {
//fmt.Println("Invalid Bytes:")
//fmt.Println(string(msgbytes[i:i+6]))
//fmt.Println("-----")
outbytes = append(outbytes, invalid_url...)
goto MainLoop
}
outbytes = append(outbytes, url_open...)
outbytes = append(outbytes, msgbytes[start:i]...)
outbytes = append(outbytes, url_open2...)
outbytes = append(outbytes, msgbytes[start:i]...)
outbytes = append(outbytes, url_close...)
i += 6
lastTag = i
}
} else if msgbytes[i + 1] == 'r' {
if bytes.Equal(msgbytes[i+2:i+6],[]byte("and]")) {
outbytes = append(outbytes, msgbytes[lastTag:i]...)
start = i + 6
i = start
for ;; i++ {
if msgbytes[i] == '[' {
if !bytes.Equal(msgbytes[i+1:i+7],[]byte("/rand]")) {
outbytes = append(outbytes, bbcode_missing_tag...)
goto OuterComplex
}
break
} else if (len(msgbytes) - 1) < (i + 10) {
outbytes = append(outbytes, bbcode_missing_tag...)
goto OuterComplex
}
}
number, err := strconv.ParseInt(string(msgbytes[start:i]),10,64)
if err != nil {
outbytes = append(outbytes, bbcode_invalid_number...)
goto MainLoop
}
// TO-DO: Add support for negative numbers?
if number < 0 {
outbytes = append(outbytes, bbcode_no_negative...)
goto MainLoop
}
var dat []byte
if number == 0 {
dat = []byte("0")
} else {
dat = []byte(strconv.FormatInt((random.Int63n(number)),10))
}
outbytes = append(outbytes, dat...)
//log.Print("Outputted the random number")
i += 7
lastTag = i
}
}
}
}
//fmt.Println(string(outbytes))
if lastTag != i {
outbytes = append(outbytes, msgbytes[lastTag:]...)
//fmt.Println("Outbytes:",`"`+string(outbytes)+`"`)
//fmt.Println("----")
}
if len(outbytes) != 0 {
//fmt.Println("BBCode Post:",`"`+string(outbytes[0:len(outbytes) - 10])+`"`)
//fmt.Println("----")
msg = string(outbytes[0:len(outbytes) - 10])
} else {
msg = string(msgbytes[0:len(msgbytes) - 10])
}
//msg = bbcode_url.ReplaceAllString(msg,"<a href=\"$1$2//$3\" rel=\"nofollow\">$1$2//$3</i>")
msg = bbcode_url_label.ReplaceAllString(msg,"<a href='$1$2//$3' rel='nofollow'>$4</i>")
msg = bbcode_quotes.ReplaceAllString(msg,"<span class='postQuote'>$1</span>")
msg = bbcode_code.ReplaceAllString(msg,"<span class='codequotes'>$1</span>")
} else {
msg = string(msgbytes[0:len(msgbytes) - 10])
}
return msg
}