Added the BBCode plugin.
Restructured the plugin system. Multiple plugins can bind to the same hook now (not available for variadic hooks yet!) The parser is now benchmarked. The bench_round4 is run with both plugin_markdown and plugin_bbcode enabled. Added a benchmark for the BBCode plugin. Moved some of the template writing logic into a more generalised function. URLs are now recognised by the system and linked. Converted more custom errors into LocalError calls. Faster and less bandwidth intensive Emojis on Edge. Fixed a bug with replies not working.
This commit is contained in:
parent
33c2f4ccb0
commit
e90d96961f
87
extend.go
87
extend.go
|
@ -2,8 +2,8 @@
|
|||
package main
|
||||
import "log"
|
||||
|
||||
var plugins map[string]Plugin = make(map[string]Plugin)
|
||||
var hooks map[string]func(interface{})interface{} = make(map[string]func(interface{})interface{})
|
||||
var plugins map[string]*Plugin = make(map[string]*Plugin)
|
||||
var hooks map[string][]func(interface{})interface{} = make(map[string][]func(interface{})interface{})
|
||||
var vhooks map[string]func(...interface{})interface{} = make(map[string]func(...interface{})interface{})
|
||||
|
||||
type Plugin struct
|
||||
|
@ -19,11 +19,64 @@ type Plugin struct
|
|||
Init func()
|
||||
Activate func()error
|
||||
Deactivate func()
|
||||
|
||||
Hooks map[string]int
|
||||
}
|
||||
|
||||
/*func add_hook(name string, handler func(interface{})interface{}) {
|
||||
hooks[name] = handler
|
||||
}*/
|
||||
func NewPlugin(uname string, name string, author string, url string, settings string, tag string, ptype string, init func(), activate func()error, deactivate func()) *Plugin {
|
||||
return &Plugin{
|
||||
UName: uname,
|
||||
Name: name,
|
||||
Author: author,
|
||||
URL: url,
|
||||
Settings: settings,
|
||||
Tag: tag,
|
||||
Type: ptype,
|
||||
Init: init,
|
||||
Activate: activate,
|
||||
Deactivate: deactivate,
|
||||
|
||||
/*
|
||||
The Active field should never be altered by a plugin. It's used internally by the software to determine whether an admin has enabled a plugin or not and whether to run it. This will be overwritten by the user's preference.
|
||||
*/
|
||||
Active: false,
|
||||
Hooks: make(map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
func (plugin *Plugin) AddHook(name string, handler interface{}) {
|
||||
switch h := handler.(type) {
|
||||
case func(interface{})interface{}:
|
||||
if len(hooks[name]) == 0 {
|
||||
var hookSlice []func(interface{})interface{}
|
||||
hookSlice = append(hookSlice, h)
|
||||
hooks[name] = hookSlice
|
||||
} else {
|
||||
hooks[name] = append(hooks[name], h)
|
||||
}
|
||||
plugin.Hooks[name] = len(hooks[name])
|
||||
case func(...interface{}) interface{}:
|
||||
vhooks[name] = h
|
||||
plugin.Hooks[name] = 0
|
||||
default:
|
||||
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
||||
}
|
||||
}
|
||||
|
||||
func (plugin *Plugin) RemoveHook(name string, handler interface{}) {
|
||||
switch handler.(type) {
|
||||
case func(interface{})interface{}:
|
||||
key := plugin.Hooks[name]
|
||||
hook := hooks[name]
|
||||
hook = append(hook[:key], hook[key + 1:]...)
|
||||
hooks[name] = hook
|
||||
case func(...interface{}) interface{}:
|
||||
delete(vhooks, name)
|
||||
default:
|
||||
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
||||
}
|
||||
delete(plugin.Hooks, name)
|
||||
}
|
||||
|
||||
func init_plugins() {
|
||||
for name, body := range plugins {
|
||||
|
@ -35,27 +88,11 @@ func init_plugins() {
|
|||
}
|
||||
}
|
||||
|
||||
func add_hook(name string, handler interface{}) {
|
||||
switch h := handler.(type) {
|
||||
case func(interface{})interface{}:
|
||||
hooks[name] = h
|
||||
case func(...interface{}) interface{}:
|
||||
vhooks[name] = h
|
||||
default:
|
||||
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
||||
}
|
||||
}
|
||||
|
||||
func remove_hook(name string/*, plugin string */) {
|
||||
delete(hooks, name)
|
||||
}
|
||||
|
||||
func run_hook(name string, data interface{}) interface{} {
|
||||
return hooks[name](data)
|
||||
}
|
||||
|
||||
func remove_vhook(name string) {
|
||||
delete(vhooks, name)
|
||||
for _, hook := range hooks[name] {
|
||||
data = hook(data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func run_vhook(name string, data ...interface{}) interface{} {
|
||||
|
|
132
general_test.go
132
general_test.go
|
@ -714,6 +714,138 @@ func BenchmarkCustomRouter(b *testing.B) {
|
|||
})
|
||||
}
|
||||
|
||||
func BenchmarkParser(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.Run("empty_post", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = parse_message("")
|
||||
}
|
||||
})
|
||||
b.Run("short_post", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = parse_message("Hey everyone, how's it going?")
|
||||
}
|
||||
})
|
||||
b.Run("one_smily", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = parse_message("Hey everyone, how's it going? :)")
|
||||
}
|
||||
})
|
||||
b.Run("five_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = parse_message("Hey everyone, how's it going? :):):):):)")
|
||||
}
|
||||
})
|
||||
b.Run("ten_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = parse_message("Hey everyone, how's it going? :):):):):):):):):):)")
|
||||
}
|
||||
})
|
||||
b.Run("twenty_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = parse_message("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkBBCodePluginWithRegexp(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.Run("empty_post", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("")
|
||||
}
|
||||
})
|
||||
b.Run("short_post", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("Hey everyone, how's it going?")
|
||||
}
|
||||
})
|
||||
b.Run("one_smily", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("Hey everyone, how's it going? :)")
|
||||
}
|
||||
})
|
||||
b.Run("five_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("Hey everyone, how's it going? :):):):):)")
|
||||
}
|
||||
})
|
||||
b.Run("ten_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("Hey everyone, how's it going? :):):):):):):):):):)")
|
||||
}
|
||||
})
|
||||
b.Run("twenty_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)")
|
||||
}
|
||||
})
|
||||
b.Run("one_bold", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("[b]H[/b]ey everyone, how's it going?")
|
||||
}
|
||||
})
|
||||
b.Run("five_bold", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?")
|
||||
}
|
||||
})
|
||||
b.Run("ten_bold", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b][b]e[/b][b]r[/b][b]y[/b][b]o[/b][b]n[/b]e, how's it going?")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkBBCodePluginWithCustomParser(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.Run("empty_post", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("")
|
||||
}
|
||||
})
|
||||
b.Run("short_post", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("Hey everyone, how's it going?")
|
||||
}
|
||||
})
|
||||
b.Run("one_smily", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("Hey everyone, how's it going? :)")
|
||||
}
|
||||
})
|
||||
b.Run("five_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("Hey everyone, how's it going? :):):):):)")
|
||||
}
|
||||
})
|
||||
b.Run("ten_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("Hey everyone, how's it going? :):):):):):):):):):)")
|
||||
}
|
||||
})
|
||||
b.Run("twenty_smilies", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)")
|
||||
}
|
||||
})
|
||||
b.Run("one_bold", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("[b]H[/b]ey everyone, how's it going?")
|
||||
}
|
||||
})
|
||||
b.Run("five_bold", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?")
|
||||
}
|
||||
})
|
||||
b.Run("ten_bold", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = bbcode_parse2("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b][b]e[/b][b]r[/b][b]y[/b][b]o[/b][b]n[/b]e, how's it going?")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/*func TestRoute(t *testing.T) {
|
||||
|
||||
}*/
|
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
Binary file not shown.
After Width: | Height: | Size: 127 KiB |
93
main.go
93
main.go
|
@ -33,7 +33,6 @@ var forums map[int]Forum = make(map[int]Forum)
|
|||
var static_files map[string]SFile = make(map[string]SFile)
|
||||
|
||||
var template_topic_handle func(TopicPage,io.Writer) = nil
|
||||
var template_topic_origin_handle func(TopicPage,io.Writer) = nil
|
||||
var template_topic_alt_handle func(TopicPage,io.Writer) = nil
|
||||
var template_topics_handle func(TopicsPage,io.Writer) = nil
|
||||
var template_forum_handle func(ForumPage,io.Writer) = nil
|
||||
|
@ -75,7 +74,6 @@ func compile_templates() {
|
|||
topicList = append(topicList, TopicUser{1,"Topic Title","The topic content.",1,false,false,"",1,"open","Admin","","",0,"","","",""})
|
||||
topics_page := TopicsPage{"Topic List",user,noticeList,topicList,""}
|
||||
topics_tmpl := c.compile_template("topics.html","templates/","TopicsPage", topics_page, varList)
|
||||
//topics_tmpl := c.compile_template("topics.html","templates/","Page", pi, varList)
|
||||
|
||||
forum_page := ForumPage{"General Forum",user,noticeList,topicList,"There aren't any topics in this forum yet."}
|
||||
forum_tmpl := c.compile_template("forum.html","templates/","ForumPage", forum_page, varList)
|
||||
|
@ -90,17 +88,7 @@ func compile_templates() {
|
|||
}
|
||||
|
||||
func write_template(name string, content string) {
|
||||
f, err := os.Create("./template_" + name + ".go")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = f.WriteString(content)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
f.Sync()
|
||||
f.Close()
|
||||
write_file("./template_" + name + ".go", content)
|
||||
}
|
||||
|
||||
func main(){
|
||||
|
@ -137,84 +125,8 @@ func main(){
|
|||
|
||||
init_plugins()
|
||||
|
||||
// In a directory to stop it clashing with the other paths
|
||||
/*http.HandleFunc("/static/", route_static)
|
||||
|
||||
fs_u := http.FileServer(http.Dir("./uploads"))
|
||||
http.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u))
|
||||
|
||||
http.HandleFunc("/overview/", route_overview)
|
||||
http.HandleFunc("/topics/create/", route_topic_create)
|
||||
http.HandleFunc("/topics/", route_topics)
|
||||
http.HandleFunc("/forums/", route_forums)
|
||||
http.HandleFunc("/forum/", route_forum)
|
||||
http.HandleFunc("/topic/create/submit/", route_create_topic)
|
||||
http.HandleFunc("/topic/", route_topic_id)
|
||||
http.HandleFunc("/reply/create/", route_create_reply)
|
||||
//http.HandleFunc("/reply/edit/", route_reply_edit)
|
||||
//http.HandleFunc("/reply/delete/", route_reply_delete)
|
||||
http.HandleFunc("/reply/edit/submit/", route_reply_edit_submit)
|
||||
http.HandleFunc("/reply/delete/submit/", route_reply_delete_submit)
|
||||
http.HandleFunc("/report/submit/", route_report_submit)
|
||||
http.HandleFunc("/topic/edit/submit/", route_edit_topic)
|
||||
http.HandleFunc("/topic/delete/submit/", route_delete_topic)
|
||||
http.HandleFunc("/topic/stick/submit/", route_stick_topic)
|
||||
http.HandleFunc("/topic/unstick/submit/", route_unstick_topic)
|
||||
|
||||
// Custom Pages
|
||||
http.HandleFunc("/pages/", route_custom_page)
|
||||
|
||||
// Accounts
|
||||
http.HandleFunc("/accounts/login/", route_login)
|
||||
http.HandleFunc("/accounts/create/", route_register)
|
||||
http.HandleFunc("/accounts/logout/", route_logout)
|
||||
http.HandleFunc("/accounts/login/submit/", route_login_submit)
|
||||
http.HandleFunc("/accounts/create/submit/", route_register_submit)
|
||||
|
||||
//http.HandleFunc("/accounts/list/", route_login) // Redirect /accounts/ and /user/ to here..
|
||||
//http.HandleFunc("/accounts/create/full/", route_logout)
|
||||
//http.HandleFunc("/user/edit/", route_logout)
|
||||
http.HandleFunc("/user/edit/critical/", route_account_own_edit_critical) // Password & Email
|
||||
http.HandleFunc("/user/edit/critical/submit/", route_account_own_edit_critical_submit)
|
||||
http.HandleFunc("/user/edit/avatar/", route_account_own_edit_avatar)
|
||||
http.HandleFunc("/user/edit/avatar/submit/", route_account_own_edit_avatar_submit)
|
||||
http.HandleFunc("/user/edit/username/", route_account_own_edit_username)
|
||||
http.HandleFunc("/user/edit/username/submit/", route_account_own_edit_username_submit)
|
||||
http.HandleFunc("/user/edit/email/token/", route_account_own_edit_email_token_submit)
|
||||
http.HandleFunc("/user/", route_profile)
|
||||
http.HandleFunc("/profile/reply/create/", route_profile_reply_create)
|
||||
http.HandleFunc("/profile/reply/edit/submit/", route_profile_reply_edit_submit)
|
||||
http.HandleFunc("/profile/reply/delete/submit/", route_profile_reply_delete_submit)
|
||||
//http.HandleFunc("/user/edit/submit/", route_logout)
|
||||
http.HandleFunc("/users/ban/", route_ban)
|
||||
http.HandleFunc("/users/ban/submit/", route_ban_submit)
|
||||
http.HandleFunc("/users/unban/", route_unban)
|
||||
http.HandleFunc("/users/activate/", route_activate)
|
||||
|
||||
// Admin
|
||||
http.HandleFunc("/panel/", route_panel)
|
||||
http.HandleFunc("/panel/forums/", route_panel_forums)
|
||||
http.HandleFunc("/panel/forums/create/", route_panel_forums_create_submit)
|
||||
http.HandleFunc("/panel/forums/delete/", route_panel_forums_delete)
|
||||
http.HandleFunc("/panel/forums/delete/submit/", route_panel_forums_delete_submit)
|
||||
http.HandleFunc("/panel/forums/edit/submit/", route_panel_forums_edit_submit)
|
||||
http.HandleFunc("/panel/settings/", route_panel_settings)
|
||||
http.HandleFunc("/panel/settings/edit/", route_panel_setting)
|
||||
http.HandleFunc("/panel/settings/edit/submit/", route_panel_setting_edit)
|
||||
http.HandleFunc("/panel/themes/", route_panel_themes)
|
||||
http.HandleFunc("/panel/themes/default/", route_panel_themes_default)
|
||||
http.HandleFunc("/panel/plugins/", route_panel_plugins)
|
||||
http.HandleFunc("/panel/plugins/activate/", route_panel_plugins_activate)
|
||||
http.HandleFunc("/panel/plugins/deactivate/", route_panel_plugins_deactivate)
|
||||
http.HandleFunc("/panel/users/", route_panel_users)
|
||||
http.HandleFunc("/panel/users/edit/", route_panel_users_edit)
|
||||
http.HandleFunc("/panel/users/edit/submit/", route_panel_users_edit_submit)
|
||||
http.HandleFunc("/panel/groups/", route_panel_groups)
|
||||
|
||||
http.HandleFunc("/", default_route)*/
|
||||
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/static/", route_static)
|
||||
router.HandleFunc("/static/", route_static) // In a directory to stop it clashing with the other paths
|
||||
|
||||
fs_u := http.FileServer(http.Dir("./uploads"))
|
||||
router.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u))
|
||||
|
@ -295,7 +207,6 @@ func main(){
|
|||
if server_port == "" {
|
||||
server_port = "80"
|
||||
}
|
||||
//http.ListenAndServe(":" + server_port, nil)
|
||||
http.ListenAndServe(":" + server_port, router)
|
||||
} else {
|
||||
if server_port == "" {
|
||||
|
|
10
pages.go
10
pages.go
|
@ -1,6 +1,6 @@
|
|||
package main
|
||||
import "strings"
|
||||
//import "regexp"
|
||||
import "regexp"
|
||||
|
||||
type Page struct
|
||||
{
|
||||
|
@ -71,6 +71,13 @@ type AreYouSure struct
|
|||
Message string
|
||||
}
|
||||
|
||||
var urlpattern string = `(?s)([ {1}])((http|https|ftp|mailto)*)(:{??)\/\/([\.a-zA-Z\/]+)([ {1}])`
|
||||
var url_reg *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
url_reg = regexp.MustCompile(urlpattern)
|
||||
}
|
||||
|
||||
func shortcode_to_unicode(msg string) string {
|
||||
//re := regexp.MustCompile(":(.):")
|
||||
msg = strings.Replace(msg,":grinning:","😀",-1)
|
||||
|
@ -126,6 +133,7 @@ func parse_message(msg string) string {
|
|||
msg = strings.Replace(msg,":)","😀",-1)
|
||||
msg = strings.Replace(msg,":D","😃",-1)
|
||||
msg = strings.Replace(msg,":P","😛",-1)
|
||||
msg = url_reg.ReplaceAllString(msg,"<a href=\"$2$3//$4\" rel=\"nofollow\">$2$3//$4</a>")
|
||||
msg = strings.Replace(msg,"\n","<br>",-1)
|
||||
if hooks["parse_assign"] != nil {
|
||||
out := run_hook("parse_assign", msg)
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
package main
|
||||
//import "log"
|
||||
//import "fmt"
|
||||
import "regexp"
|
||||
|
||||
var bbcode_bold *regexp.Regexp
|
||||
var bbcode_italic *regexp.Regexp
|
||||
var bbcode_underline *regexp.Regexp
|
||||
var bbcode_url *regexp.Regexp
|
||||
var bbcode_url_label *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
plugins["bbcode"] = NewPlugin("bbcode","BBCode","Azareal","http://github.com/Azareal","","","",init_bbcode,nil,deactivate_bbcode)
|
||||
}
|
||||
|
||||
func init_bbcode() {
|
||||
plugins["bbcode"].AddHook("parse_assign", bbcode_parse2)
|
||||
bbcode_bold = regexp.MustCompile(`(?s)\[b\](.*)\[/b\]`)
|
||||
bbcode_italic = regexp.MustCompile(`(?s)\[i\](.*)\[/i\]`)
|
||||
bbcode_underline = regexp.MustCompile(`(?s)\[u\](.*)\[/u\]`)
|
||||
urlpattern := `(http|https|ftp|mailto*)(:??)\/\/([\.a-zA-Z\/]+)`
|
||||
bbcode_url = regexp.MustCompile(`\[url\]` + urlpattern + `\[/url\]`)
|
||||
bbcode_url_label = regexp.MustCompile(`(?s)\[url=` + urlpattern + `\](.*)\[/url\]`)
|
||||
}
|
||||
|
||||
func deactivate_bbcode() {
|
||||
plugins["bbcode"].RemoveHook("parse_assign", bbcode_parse2)
|
||||
}
|
||||
|
||||
func bbcode_parse(data interface{}) interface{} {
|
||||
msg := data.(string)
|
||||
msg = bbcode_bold.ReplaceAllString(msg,"<b>$1</b>")
|
||||
msg = bbcode_italic.ReplaceAllString(msg,"<i>$1</i>")
|
||||
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>")
|
||||
return msg
|
||||
}
|
||||
|
||||
func bbcode_parse2(data interface{}) interface{} {
|
||||
msg := data.(string)
|
||||
msgbytes := []byte(msg)
|
||||
has_u := false
|
||||
has_b := false
|
||||
has_i := false
|
||||
complex_bbc := false
|
||||
for i := 0; i < len(msgbytes); i++ {
|
||||
//log.Print(msgbytes[i])
|
||||
//fmt.Println(string(msgbytes[i]))
|
||||
//continue
|
||||
if msgbytes[i] == '[' {
|
||||
if msgbytes[i + 2] != ']' {
|
||||
if msgbytes[i + 1] == '/' {
|
||||
if msgbytes[i + 3] == ']' {
|
||||
if msgbytes[i + 2] == 'u' {
|
||||
msgbytes[i] = '<'
|
||||
msgbytes[i + 3] = '>'
|
||||
has_u = false
|
||||
}
|
||||
if msgbytes[i + 2] == 'b' {
|
||||
msgbytes[i] = '<'
|
||||
msgbytes[i + 3] = '>'
|
||||
has_b = false
|
||||
}
|
||||
if msgbytes[i + 2] == 'i' {
|
||||
msgbytes[i] = '<'
|
||||
msgbytes[i + 3] = '>'
|
||||
has_i = false
|
||||
}
|
||||
i += 3
|
||||
} else {
|
||||
complex_bbc = true
|
||||
}
|
||||
} else {
|
||||
complex_bbc = true
|
||||
}
|
||||
} else {
|
||||
if msgbytes[i + 1] == 'u' {
|
||||
msgbytes[i] = '<'
|
||||
msgbytes[i + 2] = '>'
|
||||
has_u = true
|
||||
}
|
||||
if msgbytes[i + 1] == 'b' {
|
||||
msgbytes[i] = '<'
|
||||
msgbytes[i + 2] = '>'
|
||||
has_b = true
|
||||
}
|
||||
if msgbytes[i + 1] == 'i' {
|
||||
msgbytes[i] = '<'
|
||||
msgbytes[i + 2] = '>'
|
||||
has_i = true
|
||||
}
|
||||
i += 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There's an unclosed tag in there x.x
|
||||
if has_i || has_u || has_b {
|
||||
closer := []byte("</u></i></b>")
|
||||
msgbytes = append(msgbytes, closer...)
|
||||
}
|
||||
msg = string(msgbytes)
|
||||
//fmt.Println(msg)
|
||||
|
||||
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>")
|
||||
}
|
||||
return msg
|
||||
}
|
|
@ -2,16 +2,16 @@ package main
|
|||
import "html/template"
|
||||
|
||||
func init() {
|
||||
plugins["helloworld"] = Plugin{"helloworld","Hello World","Azareal","http://github.com/Azareal","",false,"","",init_helloworld,nil,deactivate_helloworld}
|
||||
plugins["helloworld"] = NewPlugin("helloworld","Hello World","Azareal","http://github.com/Azareal","","","",init_helloworld,nil,deactivate_helloworld)
|
||||
}
|
||||
|
||||
// init_helloworld is separate from init() as we don't want the plugin to run if the plugin is disabled
|
||||
func init_helloworld() {
|
||||
add_hook("rrow_assign", helloworld_reply)
|
||||
plugins["helloworld"].AddHook("rrow_assign", helloworld_reply)
|
||||
}
|
||||
|
||||
func deactivate_helloworld() {
|
||||
remove_hook("rrow_assign")
|
||||
plugins["helloworld"].RemoveHook("rrow_assign", helloworld_reply)
|
||||
}
|
||||
|
||||
func helloworld_reply(data interface{}) interface{} {
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
package main
|
||||
|
||||
import "regexp"
|
||||
|
||||
var bold_italic *regexp.Regexp
|
||||
var bold *regexp.Regexp
|
||||
var italic *regexp.Regexp
|
||||
var markdown_bold_italic *regexp.Regexp
|
||||
var markdown_bold *regexp.Regexp
|
||||
var markdown_italic *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
plugins["markdown"] = Plugin{"markdown","Markdown","Azareal","http://github.com/Azareal","",false,"","",init_markdown,nil,deactivate_markdown}
|
||||
plugins["markdown"] = NewPlugin("markdown","Markdown","Azareal","http://github.com/Azareal","","","",init_markdown,nil,deactivate_markdown)
|
||||
}
|
||||
|
||||
func init_markdown() {
|
||||
add_hook("parse_assign", markdown_parse)
|
||||
bold_italic = regexp.MustCompile(`\*\*\*(.*)\*\*\*`)
|
||||
bold = regexp.MustCompile(`\*\*(.*)\*\*`)
|
||||
italic = regexp.MustCompile(`\*(.*)\*`)
|
||||
plugins["markdown"].AddHook("parse_assign", markdown_parse)
|
||||
markdown_bold_italic = regexp.MustCompile(`\*\*\*(.*)\*\*\*`)
|
||||
markdown_bold = regexp.MustCompile(`\*\*(.*)\*\*`)
|
||||
markdown_italic = regexp.MustCompile(`\*(.*)\*`)
|
||||
}
|
||||
|
||||
func deactivate_markdown() {
|
||||
remove_hook("parse_assign")
|
||||
plugins["markdown"].RemoveHook("parse_assign", markdown_parse)
|
||||
}
|
||||
|
||||
func markdown_parse(data interface{}) interface{} {
|
||||
msg := data.(string)
|
||||
msg = bold_italic.ReplaceAllString(msg,"<i><b>$1</b></i>")
|
||||
msg = bold.ReplaceAllString(msg,"<b>$1</b>")
|
||||
msg = italic.ReplaceAllString(msg,"<i>$1</i>")
|
||||
msg = markdown_bold_italic.ReplaceAllString(msg,"<i><b>$1</b></i>")
|
||||
msg = markdown_bold.ReplaceAllString(msg,"<b>$1</b>")
|
||||
msg = markdown_italic.ReplaceAllString(msg,"<i>$1</i>")
|
||||
return msg
|
||||
}
|
|
@ -12,8 +12,6 @@ func init() {
|
|||
|
||||
The Settings field points to the route for managing the settings for this plugin. Coming soon.
|
||||
|
||||
The Active field should always be set to false in the init() function of a plugin. It's used internally by the software to determine whether an admin has enabled a plugin or not and whether to run it. This will be overwritten by the user's preference.
|
||||
|
||||
The Tag field is for providing a tiny snippet of information separate from the description.
|
||||
|
||||
The Type field is for the type of the plugin. This gets changed to "go" automatically and we would suggest leaving "".
|
||||
|
@ -24,7 +22,7 @@ func init() {
|
|||
|
||||
The Deactivate field is for the handler which is called by the software when the admin hits the Deactivate button in the control panel. You should clean-up any resources you have allocated, remove any hooks, close any statements, etc. within this handler.
|
||||
*/
|
||||
plugins["skeleton"] = Plugin{"skeleton","Skeleton","Azareal","","",false,"","",init_skeleton, activate_skeleton, deactivate_skeleton}
|
||||
plugins["skeleton"] = NewPlugin("skeleton","Skeleton","Azareal","","","","",init_skeleton, activate_skeleton, deactivate_skeleton)
|
||||
}
|
||||
|
||||
func init_skeleton() {}
|
||||
|
|
34
routes.go
34
routes.go
|
@ -605,20 +605,9 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
success := 1
|
||||
tid, err := strconv.Atoi(r.PostFormValue("tid"))
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
success = 0
|
||||
|
||||
errmsg := "Unable to create the reply"
|
||||
pi := Page{"Error","error",user,nList,tList,errmsg}
|
||||
|
||||
var b bytes.Buffer
|
||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||
errpage := b.String()
|
||||
w.WriteHeader(500)
|
||||
fmt.Fprintln(w,errpage)
|
||||
LocalError("Failed to convert the TopicID", w, r, user)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -626,15 +615,15 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) {
|
|||
log.Print(content)
|
||||
_, err = create_reply_stmt.Exec(tid,content,parse_message(content),user.ID)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
success = 0
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
var topic_name string
|
||||
err = db.QueryRow("select title from topics where tid = ?", tid).Scan(&topic_name)
|
||||
if err == sql.ErrNoRows {
|
||||
log.Print(err)
|
||||
success = 0
|
||||
LocalError("Couldn't find the parent topic", w, r, user)
|
||||
return
|
||||
} else if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
|
@ -646,18 +635,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if success != 1 {
|
||||
errmsg := "Unable to create the reply"
|
||||
pi := Page{"Error","error",user,nList,tList,errmsg}
|
||||
|
||||
var b bytes.Buffer
|
||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||
errpage := b.String()
|
||||
w.WriteHeader(500)
|
||||
fmt.Fprintln(w,errpage)
|
||||
} else {
|
||||
http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
||||
}
|
||||
http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func route_profile_reply_create(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
package main
|
||||
import "strconv"
|
||||
import "io"
|
||||
import "strconv"
|
||||
|
||||
func init() {
|
||||
template_forum_handle = template_forum
|
||||
|
|
|
@ -130,19 +130,19 @@ w.Write([]byte(`
|
|||
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">` + item.CreatedByName + `</div>
|
||||
</div>
|
||||
<div class="content_container" style="background: white;margin-left: 137px;min-height: 128px;margin-bottom: 0;margin-right: 3px;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
||||
<div class="editable_block user_content" style="padding: 5px;margin-top: 3px;margin-bottom: 0;background: white;min-height: 133px;padding-bottom: 0;width: 100%;">` + string(item.ContentHtml) + `</div>
|
||||
<div class="button_container" style="border-top: solid 1px #eaeaea;border-spacing: 0px;border-collapse: collapse;padding: 0;margin: 0;display: block;">
|
||||
<div class="editable_block user_content">` + string(item.ContentHtml) + `</div>
|
||||
<div class="button_container">
|
||||
`))
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditReply {
|
||||
w.Write([]byte(`<a href="/reply/edit/submit/` + strconv.Itoa(item.ID) + `" style="border-right: solid 1px #eaeaea;color: #505050;font-size: 13px;padding-left: 5px;padding-right: 5px;">Edit</a>`))
|
||||
w.Write([]byte(`<a href="/reply/edit/submit/` + strconv.Itoa(item.ID) + `" class="action_button">Edit</a>`))
|
||||
}
|
||||
w.Write([]byte(`
|
||||
`))
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteReply {
|
||||
w.Write([]byte(`<a href="/reply/delete/submit/` + strconv.Itoa(item.ID) + `" style="border-right: solid 1px #eaeaea;color: #505050;font-size: 13px;padding-left: 0;padding-right: 5px;">Delete</a>`))
|
||||
w.Write([]byte(`<a href="/reply/delete/submit/` + strconv.Itoa(item.ID) + `" class="action_button">Delete</a>`))
|
||||
}
|
||||
w.Write([]byte(`
|
||||
<a href="/report/submit/` + strconv.Itoa(item.ID) + `?session=` + tmpl_topic_alt_vars.CurrentUser.Session + `&type=reply" style="border: none;border-right: solid 1px #eaeaea;padding-right: 6px;color: #505050;font-size: 13px;">Report</a>
|
||||
<a href="/report/submit/` + strconv.Itoa(item.ID) + `?session=` + tmpl_topic_alt_vars.CurrentUser.Session + `&type=reply" class="action_button">Report</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{template "header.html" . }}
|
||||
<div class="rowblock">
|
||||
<div class="rowitem"><a>{{ .Title }}</a></div>
|
||||
<div class="rowitem"><a>{{.Title}}</a></div>
|
||||
</div>
|
||||
<div class="rowblock">
|
||||
{{range .ItemList}}<div class="rowitem passive" style="{{ if .Avatar }}background-image: url({{ .Avatar }});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}{{ if .Sticky }}background-color: #FFFFCC;{{else if .Is_Closed}}background-color: #eaeaea;{{end}}">
|
||||
|
|
|
@ -1,9 +1 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "header.html" . }}
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
{{template "header.html" . }}{{template "$page_name" . }}{{template "footer.html" . }}
|
|
@ -40,11 +40,11 @@
|
|||
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">{{.CreatedByName}}</div>
|
||||
</div>
|
||||
<div class="content_container" style="background: white;margin-left: 137px;min-height: 128px;margin-bottom: 0;margin-right: 3px;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
||||
<div class="editable_block user_content" style="padding: 5px;margin-top: 3px;margin-bottom: 0;background: white;min-height: 133px;padding-bottom: 0;width: 100%;">{{.ContentHtml}}</div>
|
||||
<div class="button_container" style="border-top: solid 1px #eaeaea;border-spacing: 0px;border-collapse: collapse;padding: 0;margin: 0;display: block;">
|
||||
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}" style="border-right: solid 1px #eaeaea;color: #505050;font-size: 13px;padding-left: 5px;padding-right: 5px;">Edit</a>{{end}}
|
||||
{{if $.CurrentUser.Perms.DeleteReply}}<a href="/reply/delete/submit/{{.ID}}" style="border-right: solid 1px #eaeaea;color: #505050;font-size: 13px;padding-left: 0;padding-right: 5px;">Delete</a>{{end}}
|
||||
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" style="border: none;border-right: solid 1px #eaeaea;padding-right: 6px;color: #505050;font-size: 13px;">Report</a>
|
||||
<div class="editable_block user_content">{{.ContentHtml}}</div>
|
||||
<div class="button_container">
|
||||
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}" class="action_button">Edit</a>{{end}}
|
||||
{{if $.CurrentUser.Perms.DeleteReply}}<a href="/reply/delete/submit/{{.ID}}" class="action_button">Delete</a>{{end}}
|
||||
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button">Report</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,22 +9,11 @@ body
|
|||
font-family: arial;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'EmojiFont';
|
||||
src: url('https://github.com/Ranks/emojione/raw/master/assets/fonts/emojione-svg.woff2') format('woff2'),
|
||||
url('https://github.com/Ranks/emojione/raw/master/assets/fonts/emojione-svg.woff') format('woff'), local("arial");
|
||||
}
|
||||
|
||||
/* Patch for Edge */
|
||||
@supports (-ms-ime-align:auto) {
|
||||
.user_content
|
||||
{
|
||||
font-family: EmojiFont, arial;
|
||||
}
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
.user_content
|
||||
{
|
||||
font-family: EmojiFont, arial;
|
||||
font-family: Segoe UI Emoji, arial;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,6 +319,41 @@ button.username
|
|||
background-color: #FEB7CC;
|
||||
}
|
||||
|
||||
/* Tempra Conflux */
|
||||
.user_content {
|
||||
padding: 5px;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 0;
|
||||
background: white;
|
||||
min-height: 129px;
|
||||
padding-bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button_container {
|
||||
border-top: solid 1px #eaeaea;
|
||||
border-spacing: 0px;
|
||||
border-collapse: collapse;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 3px;
|
||||
display: block;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.action_button {
|
||||
display: block;
|
||||
float: left;
|
||||
border-right: solid 1px #eaeaea;
|
||||
color: #505050;
|
||||
font-size: 13px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
/* Media Queries from Simple. Probably useless in Conflux */
|
||||
@media (max-width: 880px) {
|
||||
li
|
||||
{
|
||||
|
|
|
@ -9,22 +9,11 @@ body
|
|||
font-family: arial;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'EmojiFont';
|
||||
src: url('https://github.com/Ranks/emojione/raw/master/assets/fonts/emojione-svg.woff2') format('woff2'),
|
||||
url('https://github.com/Ranks/emojione/raw/master/assets/fonts/emojione-svg.woff') format('woff'), local("arial");
|
||||
}
|
||||
|
||||
/* Patch for Edge */
|
||||
@supports (-ms-ime-align:auto) {
|
||||
.user_content
|
||||
{
|
||||
font-family: EmojiFont, arial;
|
||||
}
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
.user_content
|
||||
{
|
||||
font-family: EmojiFont, arial;
|
||||
font-family: Segoe UI Emoji, arial;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
user.go
2
user.go
|
@ -154,7 +154,7 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, succ
|
|||
user.Session = cookie.Value
|
||||
|
||||
// Is this session valid..?
|
||||
err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName)
|
||||
err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName)
|
||||
if err == sql.ErrNoRows {
|
||||
user.ID = 0
|
||||
user.Session = ""
|
||||
|
|
16
utils.go
16
utils.go
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
import "log"
|
||||
import "fmt"
|
||||
import "time"
|
||||
import "os"
|
||||
import "encoding/base64"
|
||||
import "crypto/rand"
|
||||
import "net/smtp"
|
||||
|
@ -87,3 +89,17 @@ func SendEmail(email string, subject string, msg string) bool {
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func write_file(name string, content string) {
|
||||
f, err := os.Create(name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = f.WriteString(content)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
f.Sync()
|
||||
f.Close()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue