diff --git a/README.md b/README.md index d854f7f3..bca745cf 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,14 @@ In-memory static file, forum and group caches. A profile system including profile comments and moderation tools for the profile owner. +A template engine which compiles templates down into machine code. Over ten times faster than html/templates. + A plugin system. # Dependencies -Go. The programming language this program is written in, and the compiler which it requires. You will need to install this. https://golang.org/doc/install +Go 1.7. The programming language this program is written in, and the compiler which it requires. You will need to install this. https://golang.org/doc/install MySQL Database. You will need to setup a MySQL Database somewhere. A MariaDB Database works equally well, and is much faster than MySQL. If you're curious about how to install this, you might want to try the WNMP or XAMPP bundles on Windows. diff --git a/config.go b/config.go index e610a9ee..ef9ebec7 100644 --- a/config.go +++ b/config.go @@ -23,4 +23,4 @@ var noavatar = "https://api.adorable.io/avatars/285/{id}@" + siteurl + ".png" var items_per_page = 50 // Developer flag -var debug = true \ No newline at end of file +var debug = false \ No newline at end of file diff --git a/data.sql b/data.sql index ce190c66..ddf955c3 100644 --- a/data.sql +++ b/data.sql @@ -11,6 +11,7 @@ CREATE TABLE `users`( `createdAt` datetime not null, `lastActiveAt` datetime not null, `session` varchar(200) DEFAULT '' not null, + `last_ip` varchar(200) DEFAULT '0.0.0.0.0' not null, `email` varchar(200) DEFAULT '' not null, `avatar` varchar(20) DEFAULT '' not null, `message` text not null, @@ -54,6 +55,7 @@ CREATE TABLE `topics`( `is_closed` tinyint DEFAULT 0 not null, `sticky` tinyint DEFAULT 0 not null, `parentID` int DEFAULT 1 not null, + `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, `data` varchar(200) DEFAULT '' not null, primary key(`tid`) ) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; @@ -67,6 +69,7 @@ CREATE TABLE `replies`( `createdBy` int not null, `lastEdit` int not null, `lastEditBy` int not null, + `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, primary key(`rid`) ) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; diff --git a/experimental/center-experiment.css b/experimental/center-experiment.css new file mode 100644 index 00000000..22be1bae --- /dev/null +++ b/experimental/center-experiment.css @@ -0,0 +1,333 @@ +* { + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +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"); +} + +@supports (-ms-ime-align:auto) { +.user_content +{ + font-family: EmojiFont, arial; +} +} +@-moz-document url-prefix() { +.user_content +{ + font-family: EmojiFont, arial; +} +} + +.move_left +{ + float: left; + position: relative; + left: 50%; +} +.move_right +{ + float: left; + position: relative; + left: -50%; +} +ul +{ + padding-left: 0px; + padding-right: 0px; + height: 28px; + list-style-type: none; +} +li +{ + height: 28px; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + padding-left: 10px; + padding-top: 5px; + padding-bottom: 5px; + font-weight: bold; + text-transform: uppercase; +} +li a +{ + text-decoration: none; + color: #515151; +} +li a:hover +{ + color: #7a7a7a; +} +.menu_left +{ + float: left; + border-right: 1px solid #ccc; + padding-right: 10px; +} +.menu_left:first-child +{ + border-left: 1px solid #ccc +} +.menu_right +{ + float: right; + border-left: 1px solid #ccc; + padding-right: 10px; +} + +.container +{ + width: 90%; + padding: 0px; + margin-left: auto; + margin-right: auto; +} + +.rowblock +{ + border: 1px solid #ccc; + width: 100%; + padding: 0px; + padding-top: 0px; +} +.rowblock:empty +{ + display: none; +} + +.colblock_left +{ + border: 1px solid #ccc; + padding: 0px; + padding-top: 0px; + width: 30%; + float: left; + margin-right: 8px; +} +.colblock_right +{ + border: 1px solid #ccc; + padding: 0px; + padding-top: 0px; + width: 65%; + overflow: hidden; + word-wrap: break-word; +} +.colblock_left:empty +{ + display: none; +} +.colblock_right:empty +{ + display: none; +} + +.rowitem +{ + width: 100%; + padding-left: 8px; + padding-right: 8px; + padding-top: 17px; + padding-bottom: 12px; + font-weight: bold; + text-transform: uppercase; +} +.rowitem.passive +{ + font-weight: normal; + text-transform: none; +} +.rowitem:not(:last-child)/*:not(:only-child)*/ +{ + border-bottom: 1px dotted #ccc; +} +.rowitem a +{ + text-decoration: none; + color: black; +} +.rowitem a:hover +{ + color: silver; +} + +.col_left +{ + width: 30%; + float: left; +} +.col_right +{ + width: 69%; + overflow: hidden; +} +.colitem +{ + padding-left: 8px; + padding-right: 8px; + padding-top: 17px; + padding-bottom: 12px; + font-weight: bold; + text-transform: uppercase; +} +.colitem.passive +{ + font-weight: normal; + text-transform: none; +} +.colitem a +{ + text-decoration: none; + color: black; +} +.colitem a:hover +{ + color: silver; +} + +.formrow +{ + /*height: 40px;*/ + width: 100%; +} + +/*Clearfix*/ +.formrow:before, +.formrow:after { + content: " "; + display: table; +} + +.formrow:after { + clear: both; +} + +.formrow:not(:last-child) +{ + border-bottom: 1px dotted #ccc; +} + +.formitem +{ + float: left; + padding-left: 8px; + padding-right: 8px; + padding-top: 13px; + padding-bottom: 8px; + font-weight: bold; +} + +.formitem:first-child +{ + font-weight: bold; +} + +.formitem:not(:last-child) +{ + border-right: 1px dotted #ccc; +} + +.formitem.invisible_border +{ + border: none; +} + +/* Mostly for textareas */ +.formitem:only-child +{ + width: 97%; +} +.formitem textarea +{ + width: 100%; + height: 100px; +} +.formitem:has-child() +{ + margin: 0 auto; + float: none; +} + +button +{ + background: white; + border: 1px solid #8e8e8e; +} + +/* Topics */ +.topic_status +{ + text-transform: none; + margin-left: 8px; + padding-left: 2px; + padding-right: 2px; + padding-top: 2px; + padding-bottom: 2px; + background-color: #E8E8E8; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */ + color: #505050; /* 80,80,80 */ + border-radius: 2px; +} + +.topic_status:empty +{ + display: none; +} + +.username +{ + text-transform: none; + margin-left: 0px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + color: #505050; /* 80,80,80 */ + background-color: #FFFFFF; + border-style: dotted; + border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */ + border-width: 1px; + font-size: 15px; +} +button.username +{ + position: relative; + top: -0.25px; +} + +.show_on_edit +{ + display: none; +} + +.alert +{ + display: block; + padding: 5px; + margin-bottom: 10px; + border: 1px solid #ccc; +} +.alert_success +{ + display: block; + padding: 5px; + border: 1px solid A2FC00; + margin-bottom: 10px; + background-color: DAF7A6; +} +.alert_error +{ + display: block; + padding: 5px; + border: 1px solid #FF004B; + margin-bottom: 8px; + background-color: #FEB7CC; +} \ No newline at end of file diff --git a/experimental/plugin_sendmail.go b/experimental/plugin_sendmail.go index dc3159f8..9b250d34 100644 --- a/experimental/plugin_sendmail.go +++ b/experimental/plugin_sendmail.go @@ -14,7 +14,7 @@ func init() { } func init_sendmail() { - add_vhook("email_send_intercept", send_sendmail) + add_hook("email_send_intercept", send_sendmail) } // Sendmail is only available on Linux diff --git a/extend.go b/extend.go index 8bc50c15..546ff1c1 100644 --- a/extend.go +++ b/extend.go @@ -20,8 +20,19 @@ type Plugin struct Deactivate func() } -func add_hook(name string, handler func(interface{})interface{}) { +/*func add_hook(name string, handler func(interface{})interface{}) { hooks[name] = handler +}*/ + +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) { @@ -32,10 +43,6 @@ func run_hook(name string, data interface{}) interface{} { return hooks[name](data) } -func add_vhook(name string, handler func(...interface{}) interface{}) { - vhooks[name] = handler -} - func remove_vhook(name string) { delete(vhooks, name) } diff --git a/general_test.go b/general_test.go index eb6f4701..758feccc 100644 --- a/general_test.go +++ b/general_test.go @@ -10,25 +10,45 @@ func BenchmarkTemplates(b *testing.B) { noticeList[0] = "test" topic := TopicUser{0,"Lol",template.HTML("Hey everyone!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""} + var replyList map[int]interface{} = make(map[int]interface{}) replyList[0] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} - pi := Page{"Topic Blah","topic",user,noticeList,replyList,topic} - pi2 := Page{"Topic Blah","topic",admin,noticeList,replyList,topic} + replyList[1] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + replyList[2] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + replyList[3] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + replyList[4] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + replyList[5] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + replyList[6] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + replyList[7] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + replyList[8] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + replyList[9] = Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + + var replyList2 []interface{} + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + + pi := Page2{"Topic Blah","topic",user,noticeList,replyList,topic} + pi2 := Page2{"Topic Blah","topic",admin,noticeList,replyList,topic} + pi3 := Page{"Topic Blah","topic",user,noticeList,replyList2,topic} + pi4 := Page{"Topic Blah","topic",admin,noticeList,replyList2,topic} w := ioutil.Discard - b.Run("compiled_writer_collated_useradmin", func(b *testing.B) { + b.Run("compiled_sliceloop_useradmin", func(b *testing.B) { for i := 0; i < b.N; i++ { - template_topic(pi2,w) + template_topic(pi4,w) } }) - b.Run("compiled_writer_useradmin", func(b *testing.B) { + b.Run("compiled_maploop_useradmin", func(b *testing.B) { for i := 0; i < b.N; i++ { - template_topic2(pi2,w) - } - }) - b.Run("compiled_useradmin", func(b *testing.B) { - for i := 0; i < b.N; i++ { - w.Write([]byte(template_topic3(pi2))) + template_topic_maploop(pi2,w) } }) b.Run("interpreted_useradmin", func(b *testing.B) { @@ -36,19 +56,15 @@ func BenchmarkTemplates(b *testing.B) { templates.ExecuteTemplate(w,"topic.html", pi2) } }) - b.Run("compiled_writer_collated_userguest", func(b *testing.B) { + + b.Run("compiled_sliceloop_userguest", func(b *testing.B) { for i := 0; i < b.N; i++ { - template_topic(pi,w) + template_topic(pi3,w) } }) - b.Run("compiled_writer_userguest", func(b *testing.B) { + b.Run("compiled_maploop_userguest", func(b *testing.B) { for i := 0; i < b.N; i++ { - template_topic2(pi,w) - } - }) - b.Run("compiled_userguest", func(b *testing.B) { - for i := 0; i < b.N; i++ { - w.Write([]byte(template_topic3(pi))) + template_topic_maploop(pi,w) } }) b.Run("interpreted_userguest", func(b *testing.B) { diff --git a/gosora.exe b/gosora.exe index e07ce32f..d0a4f659 100644 Binary files a/gosora.exe and b/gosora.exe differ diff --git a/gosora.exe~ b/gosora.exe~ new file mode 100644 index 00000000..e693a454 Binary files /dev/null and b/gosora.exe~ differ diff --git a/images/notices.PNG b/images/notices.PNG new file mode 100644 index 00000000..217e4c8b Binary files /dev/null and b/images/notices.PNG differ diff --git a/images/gosora-test.PNG b/images/test_compiled_vs_interpreted.PNG similarity index 100% rename from images/gosora-test.PNG rename to images/test_compiled_vs_interpreted.PNG diff --git a/images/test_maps_vs_slices.PNG b/images/test_maps_vs_slices.PNG new file mode 100644 index 00000000..c0d246fa Binary files /dev/null and b/images/test_maps_vs_slices.PNG differ diff --git a/main.go b/main.go index ec5cabb5..df6d14e2 100644 --- a/main.go +++ b/main.go @@ -43,22 +43,43 @@ func compile_templates() { log.Print("Compiling the templates") topic := TopicUser{0,"",template.HTML(""),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""} - var replyList map[int]interface{} = make(map[int]interface{}) - replyList[0] = Reply{0,0,"",template.HTML(""),0,"","",0,0,"",no_css_tmpl,0,"","","",""} + var replyList []interface{} + replyList = append(replyList, Reply{0,0,"",template.HTML(""),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) var varList map[string]VarItem = make(map[string]VarItem) varList["extra_data"] = VarItem{"extra_data","tmpl_topic_vars.Something.(TopicUser)","TopicUser"} pi := Page{"Title","name",user,noticeList,replyList,topic} - topic_id := c.compile_template("topic.html","templates/","Page", pi, varList) + topic_id_tmpl := c.compile_template("topic.html","templates/","Page", pi, varList) varList = make(map[string]VarItem) varList["extra_data"] = VarItem{"extra_data","tmpl_profile_vars.Something.(User)","User"} pi = Page{"Title","name",user,noticeList,replyList,user} - profile := c.compile_template("profile.html","templates/","Page", pi, varList) + profile_tmpl := c.compile_template("profile.html","templates/","Page", pi, varList) + + var forumList []interface{} + for _, forum := range forums { + if forum.Active { + forumList = append(forumList, forum) + } + } + varList = make(map[string]VarItem) + pi = Page{"Forum List","forums",user,noticeList,forumList,0} + forums_tmpl := c.compile_template("forums.html","templates/","Page", pi, varList) + + var topicList []interface{} + topicList = append(topicList, TopicUser{1,"Topic Title","The topic content.",1,false,false,"",1,"open","Admin","","",0,"","","",""}) + pi = Page{"Topic List","topics",user,noticeList,topicList,""} + topics_tmpl := c.compile_template("topics.html","templates/","Page", pi, varList) + + pi = Page{"General Forum","forum",user,noticeList,topicList,"There aren't any topics in this forum yet."} + forum_tmpl := c.compile_template("forum.html","templates/","Page", pi, varList) log.Print("Writing the templates") - write_template("topic", topic_id) - write_template("profile", profile) + write_template("topic", topic_id_tmpl) + write_template("profile", profile_tmpl) + write_template("forums", forums_tmpl) + write_template("topics", topics_tmpl) + write_template("forum", forum_tmpl) } func write_template(name string, content string) { @@ -77,8 +98,8 @@ func write_template(name string, content string) { func main(){ var err error - compile_templates() init_database(err); + compile_templates() log.Print("Loading the static files.") err = filepath.Walk("./public", func(path string, f os.FileInfo, err error) error { @@ -167,6 +188,7 @@ func main(){ 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/forums/", route_panel_forums) diff --git a/mod_routes.go b/mod_routes.go index dc470f2d..23d5cf1b 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -454,7 +454,6 @@ func route_unban(w http.ResponseWriter, r *http.Request) { if !ok { return } - if !user.Is_Mod && !user.Is_Admin { NoPermissions(w,r,user) return @@ -490,6 +489,46 @@ func route_unban(w http.ResponseWriter, r *http.Request) { http.Redirect(w,r,"/users/" + strconv.Itoa(uid),http.StatusSeeOther) } +func route_activate(w http.ResponseWriter, r *http.Request) { + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + if !user.Is_Mod && !user.Is_Admin { + NoPermissions(w,r,user) + return + } + + uid, err := strconv.Atoi(r.URL.Path[len("/users/activate/"):]) + if err != nil { + LocalError("The provided User ID is not a valid number.",w,r,user) + return + } + + var uname string + var active bool + err = db.QueryRow("SELECT `name`, `active` from users where `uid` = ?", uid).Scan(&uname, &active) + if err == sql.ErrNoRows { + LocalError("The account you're trying to activate no longer exists.",w,r,user) + return + } else if err != nil { + InternalError(err,w,r,user) + return + } + + if active { + LocalError("The account you're trying to activate has already been activated.",w,r,user) + return + } + + _, err = activate_user_stmt.Exec(uid) + if err != nil { + InternalError(err,w,r,user) + return + } + http.Redirect(w,r,"/users/" + strconv.Itoa(uid),http.StatusSeeOther) +} + func route_panel_forums(w http.ResponseWriter, r *http.Request){ user, noticeList, ok := SessionCheck(w,r) if !ok { @@ -501,13 +540,10 @@ func route_panel_forums(w http.ResponseWriter, r *http.Request){ return } - var forumList map[int]interface{} = make(map[int]interface{}) - currentID := 0 - + var forumList []interface{} for _, forum := range forums { if forum.ID > -1 { - forumList[currentID] = forum - currentID++ + forumList = append(forumList, forum) } } @@ -778,18 +814,14 @@ func route_panel_plugins(w http.ResponseWriter, r *http.Request){ if !ok { return } - if !user.Is_Admin { NoPermissions(w,r,user) return } - var pluginList map[int]interface{} = make(map[int]interface{}) - currentID := 0 - + var pluginList []interface{} for _, plugin := range plugins { - pluginList[currentID] = plugin - currentID++ + pluginList = append(pluginList, plugin) } pi := Page{"Plugin Manager","panel-plugins",user,noticeList,pluginList,0} @@ -911,9 +943,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ return } - var userList map[int]interface{} = make(map[int]interface{}) - currentID := 0 - + var userList []interface{} rows, err := db.Query("SELECT `uid`, `name`, `group`, `active`, `is_super_admin`, `avatar` FROM users") if err != nil { InternalError(err,w,r,user) @@ -951,8 +981,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ puser.Tag = "" } - userList[currentID] = puser - currentID++ + userList = append(userList, puser) } err = rows.Err() if err != nil { diff --git a/mysql.go b/mysql.go index 12f35072..2018a98d 100644 --- a/mysql.go +++ b/mysql.go @@ -28,6 +28,7 @@ var set_username_stmt *sql.Stmt var register_stmt *sql.Stmt var username_exists_stmt *sql.Stmt var change_group_stmt *sql.Stmt +var activate_user_stmt *sql.Stmt var create_profile_reply_stmt *sql.Stmt var edit_profile_reply_stmt *sql.Stmt var delete_profile_reply_stmt *sql.Stmt @@ -183,6 +184,12 @@ func init_database(err error) { log.Fatal(err) } + log.Print("Preparing activate_user statement.") + activate_user_stmt, err = db.Prepare("UPDATE users SET active = 1 WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + log.Print("Preparing create_profile_reply statement.") create_profile_reply_stmt, err = db.Prepare("INSERT INTO users_replies(uid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)") if err != nil { diff --git a/pages.go b/pages.go index e13be6ec..892b5b9f 100644 --- a/pages.go +++ b/pages.go @@ -3,6 +3,17 @@ import "strings" //import "regexp" type Page struct +{ + Title string + Name string + CurrentUser User + NoticeList map[int]string + ItemList []interface{} + Something interface{} +} + +/* For testing maps versus slices */ +type Page2 struct { Title string Name string diff --git a/public/main.css b/public/main.css index 180d1e98..0b34c255 100644 --- a/public/main.css +++ b/public/main.css @@ -28,41 +28,56 @@ body } } +/*.move_left +{ + float: left; + position: relative; + left: 50%; +} +.move_right +{ + float: left; + position: relative; + left: -50%; +}*/ ul { - border: 1px solid #ccc; - padding-top: 5px; - padding-bottom: 5px; padding-left: 0px; padding-right: 0px; height: 28px; list-style-type: none; + border: 1px solid #ccc; } - li { - float: left; + height: 26px; padding-left: 10px; + padding-top: 5px; + padding-bottom: 5px; font-weight: bold; text-transform: uppercase; } - li a { text-decoration: none; color: #515151; } - li a:hover { color: #7a7a7a; } - -li:not(:last-child) +.menu_left { + float: left; border-right: 1px solid #ccc; padding-right: 10px; } +.menu_right +{ + float: right; + border-left: 1px solid #ccc; + padding-right: 10px; +} .container { @@ -288,18 +303,26 @@ button.username display: none; } +.alert +{ + display: block; + padding: 5px; + margin-bottom: 10px; + border: 1px solid #ccc; +} .alert_success { display: block; - padding: 3px; + padding: 5px; border: 1px solid A2FC00; + margin-bottom: 10px; background-color: DAF7A6; } - .alert_error { display: block; - padding: 3px; + padding: 5px; border: 1px solid #FF004B; + margin-bottom: 8px; background-color: #FEB7CC; } \ No newline at end of file diff --git a/routes.go b/routes.go index 3181c301..1648b2a2 100644 --- a/routes.go +++ b/routes.go @@ -19,7 +19,7 @@ import _ "github.com/go-sql-driver/mysql" import "golang.org/x/crypto/bcrypt" // A blank list to fill out that parameter in Page for routes which don't use it -var tList map[int]interface{} +var tList []interface{} var nList map[int]string // GET functions @@ -80,7 +80,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ } var( - topicList map[int]interface{} + topicList []interface{} currentID int tid int @@ -95,8 +95,6 @@ func route_topics(w http.ResponseWriter, r *http.Request){ name string avatar string ) - topicList = make(map[int]interface{}) - currentID = 0 rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC") if err != nil { @@ -125,12 +123,11 @@ func route_topics(w http.ResponseWriter, r *http.Request){ avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(createdBy),1) } - topicList[currentID] = TopicUser{tid,title,content,createdBy,is_closed,sticky, createdAt,parentID,status,name,avatar,"",0,"","","",""} + topicList = append(topicList, TopicUser{tid,title,content,createdBy,is_closed,sticky, createdAt,parentID,status,name,avatar,"",0,"","","",""}) if hooks["trow_assign"] != nil { topicList[currentID] = run_hook("trow_assign", topicList[currentID]) } - currentID++ } err = rows.Err() if err != nil { @@ -146,10 +143,14 @@ func route_topics(w http.ResponseWriter, r *http.Request){ } pi := Page{"Topic List","topics",user,noticeList,topicList,msg} - err = templates.ExecuteTemplate(w,"topics.html", pi) - if err != nil { - InternalError(err, w, r, user) - } + if ctemplates["topics"] != nil { + ctemplates["topics"](pi,w) + } else { + err = templates.ExecuteTemplate(w,"topics.html", pi) + if err != nil { + InternalError(err, w, r, user) + } + } } func route_forum(w http.ResponseWriter, r *http.Request){ @@ -159,7 +160,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){ } var( - topicList map[int]interface{} + topicList []interface{} currentID int tid int @@ -174,8 +175,6 @@ func route_forum(w http.ResponseWriter, r *http.Request){ name string avatar string ) - topicList = make(map[int]interface{}) - currentID = 0 fid, err := strconv.Atoi(r.URL.Path[len("/forum/"):]) if err != nil { @@ -216,12 +215,11 @@ func route_forum(w http.ResponseWriter, r *http.Request){ avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(createdBy),1) } - topicList[currentID] = TopicUser{tid,title,content,createdBy,is_closed,sticky,createdAt,parentID,status,name,avatar,"",0,"","","",""} + topicList = append(topicList, TopicUser{tid,title,content,createdBy,is_closed,sticky,createdAt,parentID,status,name,avatar,"",0,"","","",""}) if hooks["trow_assign"] != nil { topicList[currentID] = run_hook("trow_assign", topicList[currentID]) } - currentID++ } err = rows.Err() if err != nil { @@ -237,10 +235,14 @@ func route_forum(w http.ResponseWriter, r *http.Request){ } pi := Page{forums[fid].Name,"forum",user,noticeList,topicList,msg} - err = templates.ExecuteTemplate(w,"forum.html", pi) - if err != nil { - InternalError(err, w, r, user) - } + if ctemplates["forum"] != nil { + ctemplates["forum"](pi,w) + } else { + err = templates.ExecuteTemplate(w,"forum.html", pi) + if err != nil { + InternalError(err, w, r, user) + } + } } func route_forums(w http.ResponseWriter, r *http.Request){ @@ -249,13 +251,10 @@ func route_forums(w http.ResponseWriter, r *http.Request){ return } - var forumList map[int]interface{} = make(map[int]interface{}) - currentID := 0 - + var forumList []interface{} for _, forum := range forums { if forum.Active { - forumList[currentID] = forum - currentID++ + forumList = append(forumList, forum) } } @@ -265,10 +264,14 @@ func route_forums(w http.ResponseWriter, r *http.Request){ } pi := Page{"Forum List","forums",user,noticeList,forumList,0} - err := templates.ExecuteTemplate(w,"forums.html", pi) - if err != nil { - InternalError(err, w, r, user) - } + if ctemplates["forums"] != nil { + ctemplates["forums"](pi,w) + } else { + err := templates.ExecuteTemplate(w,"forums.html", pi) + if err != nil { + InternalError(err, w, r, user) + } + } } func route_topic_id(w http.ResponseWriter, r *http.Request){ @@ -297,11 +300,8 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ is_super_admin bool group int - currentID int - replyList map[int]interface{} + replyList []interface{} ) - replyList = make(map[int]interface{}) - currentID = 0 topic := TopicUser{0,"","",0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""} topic.ID, err = strconv.Atoi(r.URL.Path[len("/topic/"):]) @@ -398,12 +398,12 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } } - replyList[currentID] = Reply{rid,topic.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,replyURL,replyURLPrefix,replyURLName} + replyItem := Reply{rid,topic.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,replyURL,replyURLPrefix,replyURLName} if hooks["rrow_assign"] != nil { - replyList[currentID] = run_hook("rrow_assign", replyList[currentID]) + replyItem = run_hook("rrow_assign", replyItem).(Reply) } - currentID++ + replyList = append(replyList, replyItem) } err = rows.Err() if err != nil { @@ -444,11 +444,8 @@ func route_profile(w http.ResponseWriter, r *http.Request){ is_super_admin bool group int - currentID int - replyList map[int]interface{} + replyList []interface{} ) - replyList = make(map[int]interface{}) - currentID = 0 puser := User{0,"",0,false,false,false,false,false,false,"",false,"","","","",""} puser.ID, err = strconv.Atoi(r.URL.Path[len("/user/"):]) @@ -530,8 +527,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ replyTag = "" } - replyList[currentID] = Reply{rid,puser.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","",""} - currentID++ + replyList = append(replyList, Reply{rid,puser.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","",""}) } err = rows.Err() if err != nil { @@ -540,11 +536,14 @@ func route_profile(w http.ResponseWriter, r *http.Request){ } pi := Page{puser.Name + "'s Profile","profile",user,noticeList,replyList,puser} - //w.Write([]byte(template_profile(pi))) - err = templates.ExecuteTemplate(w,"profile.html", pi) - if err != nil { - InternalError(err, w, r, user) - } + if ctemplates["profile"] != nil { + ctemplates["profile"](pi,w) + } else { + err = templates.ExecuteTemplate(w,"profile.html", pi) + if err != nil { + InternalError(err, w, r, user) + } + } } func route_topic_create(w http.ResponseWriter, r *http.Request){ diff --git a/template_forum.go b/template_forum.go new file mode 100644 index 00000000..82df2d08 --- /dev/null +++ b/template_forum.go @@ -0,0 +1,104 @@ +package main +import "strconv" +import "io" + +func init() { +ctemplates["forum"] = template_forum +} + +func template_forum(tmpl_forum_vars Page, w io.Writer) { +w.Write([]byte(` + + + ` + tmpl_forum_vars.Title + ` + + + + + + +
+ +`)) +if len(tmpl_forum_vars.NoticeList) != 0 { +for _, item := range tmpl_forum_vars.NoticeList { +w.Write([]byte(`
` + item + `
`)) +} +} +w.Write([]byte(` +
+ +
+
+ `)) +if len(tmpl_forum_vars.ItemList) != 0 { +for _, item := range tmpl_forum_vars.ItemList { +w.Write([]byte(`
+ ` + item.(TopicUser).Title + ` `)) +if item.(TopicUser).Is_Closed { +w.Write([]byte(`closed + `)) +} else { +w.Write([]byte(`open`)) +} +w.Write([]byte(` + Status +
`)) +} +} +w.Write([]byte(` +
+`)) +if tmpl_forum_vars.Something.(string) != "" { +w.Write([]byte(` +
+
` + tmpl_forum_vars.Something.(string) + `
+
+`)) +} +w.Write([]byte(` + +
+ +`)) +} diff --git a/template_forums.go b/template_forums.go new file mode 100644 index 00000000..0d300fe8 --- /dev/null +++ b/template_forums.go @@ -0,0 +1,78 @@ +package main +import "io" +import "strconv" + +func init() { +ctemplates["forums"] = template_forums +} + +func template_forums(tmpl_forums_vars Page, w io.Writer) { +w.Write([]byte(` + + + ` + tmpl_forums_vars.Title + ` + + + + + + +
+ +`)) +if len(tmpl_forums_vars.NoticeList) != 0 { +for _, item := range tmpl_forums_vars.NoticeList { +w.Write([]byte(`
` + item + `
`)) +} +} +w.Write([]byte(` +
+ `)) +if len(tmpl_forums_vars.ItemList) != 0 { +for _, item := range tmpl_forums_vars.ItemList { +w.Write([]byte(``)) +} +} +w.Write([]byte(` +
+ +
+ +`)) +} diff --git a/template_profile.go b/template_profile.go index 5c4ca506..85a48a3f 100644 --- a/template_profile.go +++ b/template_profile.go @@ -22,31 +22,36 @@ w.Write([]byte(`
`)) if len(tmpl_profile_vars.NoticeList) != 0 { diff --git a/template_topic.go b/template_topic.go index cc9078d0..2367561d 100644 --- a/template_topic.go +++ b/template_topic.go @@ -23,31 +23,36 @@ w.Write([]byte(`
`)) if len(tmpl_topic_vars.NoticeList) != 0 { @@ -158,7 +163,7 @@ w.Write([]byte(` w.Write([]byte(`
`)) -if !tmpl_topic_vars.CurrentUser.Is_Banned { +if !tmpl_topic_vars.CurrentUser.Is_Banned && tmpl_topic_vars.CurrentUser.Loggedin { w.Write([]byte(`
diff --git a/template_topic_maploop.go b/template_topic_maploop.go new file mode 100644 index 00000000..14d2afd9 --- /dev/null +++ b/template_topic_maploop.go @@ -0,0 +1,186 @@ +package main +import "io" +import "strconv" +import "html/template" + +func init() { +ctemplates["topic"] = template_topic +} + +func template_topic_maploop(tmpl_topic_vars Page2, w io.Writer) { +var extra_data TopicUser = tmpl_topic_vars.Something.(TopicUser) +w.Write([]byte(` + + + ` + tmpl_topic_vars.Title + ` + + + + + + +
+ +`)) +if len(tmpl_topic_vars.NoticeList) != 0 { +for _, item := range tmpl_topic_vars.NoticeList { +w.Write([]byte(`
` + item + `
`)) +} +} +w.Write([]byte(` +
+ +
+ ` + extra_data.Title + ` + ` + extra_data.Status + ` + Status + `)) +if tmpl_topic_vars.CurrentUser.Is_Mod { +w.Write([]byte(` + Edit + Delete + `)) +if extra_data.Sticky { +w.Write([]byte(`Unpin`)) +} else { +w.Write([]byte(`Pin`)) +} +w.Write([]byte(` + + + + + `)) +} +w.Write([]byte(` + Report +
+ +
+
+
+ ` + string(extra_data.Content.(template.HTML)) + ` + +

+ ` + extra_data.CreatedByName + ` + `)) +if extra_data.Tag != "" { +w.Write([]byte(`` + extra_data.Tag + ``)) +} else { +if extra_data.URLName != "" { +w.Write([]byte(`` + extra_data.URLName + ` + ` + extra_data.URLPrefix + ``)) +} +} +w.Write([]byte(` +
+

+
+ `)) +if len(tmpl_topic_vars.ItemList) != 0 { +for _, item := range tmpl_topic_vars.ItemList { +w.Write([]byte(` +
+ ` + string(item.(Reply).ContentHtml) + ` +

+ ` + item.(Reply).CreatedByName + ` + `)) +if tmpl_topic_vars.CurrentUser.Is_Mod { +w.Write([]byte(` + `)) +} +w.Write([]byte(` + + `)) +if item.(Reply).Tag != "" { +w.Write([]byte(`` + item.(Reply).Tag + ``)) +} else { +if item.(Reply).URLName != "" { +w.Write([]byte(`` + item.(Reply).URLName + ` + ` + item.(Reply).URLPrefix + ``)) +} +} +w.Write([]byte(` +
`)) +} +} +w.Write([]byte(` +
+`)) +if !tmpl_topic_vars.CurrentUser.Is_Banned && tmpl_topic_vars.CurrentUser.Loggedin { +w.Write([]byte(` +
+
+ +
+
+
+
+
+
+
+
+`)) +} +w.Write([]byte(` + +
+ +`)) +} diff --git a/template_topic_old.go b/template_topic_old.go deleted file mode 100644 index 81d54454..00000000 --- a/template_topic_old.go +++ /dev/null @@ -1,262 +0,0 @@ -package main -import "strconv" -import "html/template" - -//func init() { -//ctemplates["topic2"] = template_topic2 -//} - -func template_topic3(tmpl_topic_vars Page) (tmpl string) { -var extra_data TopicUser = tmpl_topic_vars.Something.(TopicUser) -tmpl += ` - - - ` -tmpl += tmpl_topic_vars.Title -tmpl += ` - - - - - - -
-` -tmpl += `` -tmpl += ` -` -if len(tmpl_topic_vars.NoticeList) != 0 { -for _, item := range tmpl_topic_vars.NoticeList { -tmpl += `
` -tmpl += item -tmpl += `
` -} -} -tmpl += ` -
-
-
- ` -tmpl += extra_data.Title -tmpl += ` - ` -tmpl += extra_data.Status -tmpl += ` - Status - ` -if tmpl_topic_vars.CurrentUser.Is_Mod { -tmpl += ` - Edit - Delete - ` -if extra_data.Sticky { -tmpl += `Unpin` -} else { -tmpl += `Pin` -} -tmpl += ` - - - - - ` -} -tmpl += ` - Report -
-
-
-
-
- ` -tmpl += string(extra_data.Content.(template.HTML)) -tmpl += ` - -

- ` -tmpl += extra_data.CreatedByName -tmpl += ` - ` -if extra_data.Tag != "" { -tmpl += `` -tmpl += extra_data.Tag -tmpl += `` -} else { -if extra_data.URLName != "" { -tmpl += `` -tmpl += extra_data.URLName -tmpl += ` - ` -tmpl += extra_data.URLPrefix -tmpl += `` -} -} -tmpl += ` -
-

-
- ` -if len(tmpl_topic_vars.ItemList) != 0 { -for _, item := range tmpl_topic_vars.ItemList { -tmpl += ` -
- ` -tmpl += string(item.(Reply).ContentHtml) -tmpl += ` -

- ` -tmpl += item.(Reply).CreatedByName -tmpl += ` - ` -if tmpl_topic_vars.CurrentUser.Is_Mod { -tmpl += ` - ` -} -tmpl += ` - - ` -if item.(Reply).Tag != "" { -tmpl += `` -tmpl += item.(Reply).Tag -tmpl += `` -} else { -if item.(Reply).URLName != "" { -tmpl += `` -tmpl += item.(Reply).URLName -tmpl += ` - ` -tmpl += item.(Reply).URLPrefix -tmpl += `` -} -} -tmpl += ` -
` -} -} -tmpl += ` -
-` -if !tmpl_topic_vars.CurrentUser.Is_Banned { -tmpl += ` -
-
- -
-
-
-
-
-
-
-
-` -} -tmpl += ` -` -tmpl += ` -
- -` -return tmpl -} diff --git a/template_topic_writer.go b/template_topic_writer.go deleted file mode 100644 index 9e406069..00000000 --- a/template_topic_writer.go +++ /dev/null @@ -1,262 +0,0 @@ -package main -import "io" -import "strconv" -import "html/template" - -/*func init() { -ctemplates["topic"] = template_topic -}*/ - -func template_topic2(tmpl_topic_vars Page, w io.Writer) { -var extra_data TopicUser = tmpl_topic_vars.Something.(TopicUser) -w.Write([]byte(` - - - `)) -w.Write([]byte(tmpl_topic_vars.Title)) -w.Write([]byte(` - - - - - - -
-`)) -w.Write([]byte(``)) -w.Write([]byte(` -`)) -if len(tmpl_topic_vars.NoticeList) != 0 { -for _, item := range tmpl_topic_vars.NoticeList { -w.Write([]byte(`
`)) -w.Write([]byte(item)) -w.Write([]byte(`
`)) -} -} -w.Write([]byte(` -
-
-
- `)) -w.Write([]byte(extra_data.Title)) -w.Write([]byte(` - `)) -w.Write([]byte(extra_data.Status)) -w.Write([]byte(` - Status - `)) -if tmpl_topic_vars.CurrentUser.Is_Mod { -w.Write([]byte(` - Edit - Delete - `)) -if extra_data.Sticky { -w.Write([]byte(`Unpin`)) -} else { -w.Write([]byte(`Pin`)) -} -w.Write([]byte(` - - - - - `)) -} -w.Write([]byte(` - Report -
-
-
-
-
- `)) -w.Write([]byte(string(extra_data.Content.(template.HTML)))) -w.Write([]byte(` - -

- `)) -w.Write([]byte(extra_data.CreatedByName)) -w.Write([]byte(` - `)) -if extra_data.Tag != "" { -w.Write([]byte(``)) -w.Write([]byte(extra_data.Tag)) -w.Write([]byte(``)) -} else { -if extra_data.URLName != "" { -w.Write([]byte(``)) -w.Write([]byte(extra_data.URLName)) -w.Write([]byte(` - `)) -w.Write([]byte(extra_data.URLPrefix)) -w.Write([]byte(``)) -} -} -w.Write([]byte(` -
-

-
- `)) -if len(tmpl_topic_vars.ItemList) != 0 { -for _, item := range tmpl_topic_vars.ItemList { -w.Write([]byte(` -
- `)) -w.Write([]byte(string(item.(Reply).ContentHtml))) -w.Write([]byte(` -

- `)) -w.Write([]byte(item.(Reply).CreatedByName)) -w.Write([]byte(` - `)) -if tmpl_topic_vars.CurrentUser.Is_Mod { -w.Write([]byte(` - `)) -} -w.Write([]byte(` - - `)) -if item.(Reply).Tag != "" { -w.Write([]byte(``)) -w.Write([]byte(item.(Reply).Tag)) -w.Write([]byte(``)) -} else { -if item.(Reply).URLName != "" { -w.Write([]byte(``)) -w.Write([]byte(item.(Reply).URLName)) -w.Write([]byte(` - `)) -w.Write([]byte(item.(Reply).URLPrefix)) -w.Write([]byte(``)) -} -} -w.Write([]byte(` -
`)) -} -} -w.Write([]byte(` -
-`)) -if !tmpl_topic_vars.CurrentUser.Is_Banned { -w.Write([]byte(` -
-
- -
-
-
-
-
-
-
-
-`)) -} -w.Write([]byte(` -`)) -w.Write([]byte(` -
- -`)) -} diff --git a/template_topics.go b/template_topics.go new file mode 100644 index 00000000..0d3de866 --- /dev/null +++ b/template_topics.go @@ -0,0 +1,104 @@ +package main +import "io" +import "strconv" + +func init() { +ctemplates["topics"] = template_topics +} + +func template_topics(tmpl_topics_vars Page, w io.Writer) { +w.Write([]byte(` + + + ` + tmpl_topics_vars.Title + ` + + + + + + +
+ +`)) +if len(tmpl_topics_vars.NoticeList) != 0 { +for _, item := range tmpl_topics_vars.NoticeList { +w.Write([]byte(`
` + item + `
`)) +} +} +w.Write([]byte(` + +
+ `)) +if len(tmpl_topics_vars.ItemList) != 0 { +for _, item := range tmpl_topics_vars.ItemList { +w.Write([]byte(`
+ ` + item.(TopicUser).Title + ` `)) +if item.(TopicUser).Is_Closed { +w.Write([]byte(`closed + `)) +} else { +w.Write([]byte(`open`)) +} +w.Write([]byte(` + Status +
`)) +} +} +w.Write([]byte(` +
+`)) +if tmpl_topics_vars.Something.(string) != "" { +w.Write([]byte(` +
+
` + tmpl_topics_vars.Something.(string) + `
+
+`)) +} +w.Write([]byte(` + +
+ +`)) +} diff --git a/templates.go b/templates.go index 617a1f78..82d57be1 100644 --- a/templates.go +++ b/templates.go @@ -33,6 +33,9 @@ type CTemplateSet struct stats map[string]int pVarList string pVarPosition int + previousNode parse.NodeType + currentNode parse.NodeType + nextNode parse.NodeType //tempVars map[string]string doImports bool expectsInt interface{} @@ -97,10 +100,17 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string, fmt.Println(subtree.Root) } - for _, node := range subtree.Root.Nodes { + treeLength := len(subtree.Root.Nodes) + for index, node := range subtree.Root.Nodes { if debug { fmt.Println("Node: " + node.String()) } + + c.previousNode = c.currentNode + c.currentNode = node.Type() + if treeLength != (index + 1) { + c.nextNode = subtree.Root.Nodes[index + 1].Type() + } out += c.compile_switch(varholder, holdreflect, fname, node) } @@ -125,6 +135,7 @@ w.Write([]byte(`," + ",-1) for index, count := range c.stats { fmt.Println(index + ": " + strconv.Itoa(count)) } + fmt.Println(" ") if debug { fmt.Println("Output!") @@ -163,6 +174,9 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu expr += c.compile_varswitch(varholder, holdreflect, template_name, cmd) } + c.previousNode = c.currentNode + c.currentNode = parse.NodeList + c.nextNode = -1 if node.ElseList == nil { if debug { fmt.Println("Branch 1") @@ -210,6 +224,10 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu item = outVal.MapIndex(key) } + out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}" + case reflect.Slice: + item := outVal.Index(0) + out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}" case reflect.Invalid: return "" @@ -227,6 +245,9 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu } return c.compile_subtemplate(varholder, holdreflect, node) case *parse.TextNode: + c.previousNode = c.currentNode + c.currentNode = node.Type() + c.nextNode = 0 return "w.Write([]byte(`" + string(node.Text) + "`))\n" default: panic("Unknown Node in main switch") @@ -266,7 +287,7 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V /*if cur.Kind() == reflect.String && cur.Type().Name() != "string" { varbit = "string(" + varbit + "." + id + ")"*/ //if cur.Kind() == reflect.String && cur.Type().Name() != "string" { - if cur.Type().PkgPath() != "main" { + if cur.Type().PkgPath() != "main" && cur.Type().PkgPath() != "" { c.importMap["html/template"] = "html/template" varbit += "." + id + ".(" + strings.TrimPrefix(cur.Type().PkgPath(),"html/") + "." + cur.Type().Name() + ")" } else { @@ -364,42 +385,9 @@ func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.V if debug { fmt.Println("Pipe Node!") fmt.Println(n) - } - - /*for _, cmd := range n.Cmds { - if debug { - fmt.Println("Pipe Bit: ") - fmt.Println(cmd) - } - out += c.compile_if_varsub_n(n.String(), varholder, template_name, holdreflect) - }*/ - - if debug { fmt.Println("Args: ") fmt.Println(node.Args) } - - /*argcopy := node.Args[1:] - for _, arg := range argcopy { - if debug { - fmt.Println("Pipe Arg: ") - fmt.Println(arg) - fmt.Println(reflect.ValueOf(arg).Elem().Type().Name()) - fmt.Println(reflect.ValueOf(arg).Kind()) - } - - switch arg.(type) { - case *parse.IdentifierNode: - out += c.compile_identswitch(varholder, holdreflect, template_name, node) - break - case *parse.PipeNode: - break - //out += c.compile_if_varsub_n(a.String(), varholder, template_name, holdreflect) - default: - panic("Unknown Pipe Arg type! Did Mario get stuck in the pipes again?") - } - //out += c.compile_varswitch(arg.String(), holdreflect, template_name, arg) - }*/ out += c.compile_identswitch(varholder, holdreflect, template_name, node) if debug { @@ -663,10 +651,17 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle c.localVars[fname] = make(map[string]VarItemReflect) c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect} - for _, node := range subtree.Root.Nodes { + treeLength := len(subtree.Root.Nodes) + for index, node := range subtree.Root.Nodes { if debug { fmt.Println("Node: " + node.String()) } + + c.previousNode = c.currentNode + c.currentNode = node.Type() + if treeLength != (index + 1) { + c.nextNode = subtree.Root.Nodes[index + 1].Type() + } out += c.compile_switch(varholder, holdreflect, fname, node) } return out diff --git a/templates/menu.html b/templates/menu.html index 3c3c6336..dc7cd02a 100644 --- a/templates/menu.html +++ b/templates/menu.html @@ -1,17 +1,22 @@ \ No newline at end of file diff --git a/templates/topic.html b/templates/topic.html index 53890635..26d96e7b 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -44,7 +44,7 @@ {{.URLPrefix}}{{end}}
{{end}}
-{{if not .CurrentUser.Is_Banned}} +{{if not (.CurrentUser.Is_Banned) and (.CurrentUser.Loggedin)}}
diff --git a/user.go b/user.go index 99fe0a11..26734e3a 100644 --- a/user.go +++ b/user.go @@ -47,6 +47,8 @@ func SetPassword(uid int, password string) (error) { } func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList map[int]string, success bool) { + noticeList = make(map[int]string) + // Are there any session cookies..? // Assign it to user.name to avoid having to create a temporary variable for the type conversion cookie, err := r.Cookie("uid") @@ -83,7 +85,7 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList } if user.Is_Banned { - noticeList[0] = "You have been banned. Your ability to post has been revoked." + noticeList[0] = "Your account has been suspended. Some of your permissions may have been revoked." } if user.Avatar != "" {