diff --git a/data.sql b/data.sql
index 577cef3f..a5b8a076 100644
--- a/data.sql
+++ b/data.sql
@@ -99,8 +99,15 @@ CREATE TABLE `plugins`(
unique(`uname`)
);
+CREATE TABLE `themes`(
+ `uname` varchar(200) not null,
+ `default` tinyint DEFAULT 0 not null,
+ unique(`uname`)
+);
+
INSERT INTO settings(`name`,`content`,`type`) VALUES ('url_tags','1','bool');
INSERT INTO settings(`name`,`content`,`type`,`constraints`) VALUES ('activation_type','1','list','1-3',);
+INSERT INTO themes(`uname`,`default`) VALUES ('tempra-simple',1);
INSERT INTO users(`name`,`email`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`)
VALUES ('Admin','admin@localhost',1,1,NOW(),NOW(),'');
@@ -118,6 +125,7 @@ EditUserGroupSuperMod
EditUserGroupAdmin
ManageForums
EditSettings
+ManageThemes
ManagePlugins
ViewIPs
@@ -132,11 +140,11 @@ PinTopic
CloseTopic
*/
-INSERT INTO users_groups(`name`,`permissions`,`active`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManagePlugins":true,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,1,1,"Admin");
-INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":true,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,"Mod");
-INSERT INTO users_groups(`name`,`permissions`) VALUES ('Member','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":true,"EditTopic":false,"DeleteTopic":false,"CreateReply":true,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
-INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Banned','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}',1);
-INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Awaiting Activation','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
+INSERT INTO users_groups(`name`,`permissions`,`active`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,1,1,"Admin");
+INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":true,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":false,"ManagePlugins":false,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,"Mod");
+INSERT INTO users_groups(`name`,`permissions`) VALUES ('Member','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":true,"EditTopic":false,"DeleteTopic":false,"CreateReply":true,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
+INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Banned','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}',1);
+INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Awaiting Activation','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
INSERT INTO forums(`name`,`lastTopicTime`) VALUES ('General',NOW());
INSERT INTO topics(`title`,`content`,`createdAt`,`lastReplyAt`,`createdBy`,`parentID`)
diff --git a/experimental/theme-ext.json b/experimental/theme-ext.json
new file mode 100644
index 00000000..52eed859
--- /dev/null
+++ b/experimental/theme-ext.json
@@ -0,0 +1,19 @@
+{
+ "Name": "tempra-simple",
+ "FriendlyName": "Tempra Simple",
+ "Version": "0.0.1",
+ "Creator": "Azareal",
+ "Settings": {
+ "PostLayout": {
+ "FriendlyName":"Post Layout",
+ "Options": ["Compact","Alternate"]
+ }
+ },
+ "Templates": [
+ {
+ "Name": "topic",
+ "Source": "topic_alt",
+ "When": "PostLayout=Alternate"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/experimental/theme-ext.xml b/experimental/theme-ext.xml
new file mode 100644
index 00000000..fd81450a
--- /dev/null
+++ b/experimental/theme-ext.xml
@@ -0,0 +1,18 @@
+
+
+ tempra-simple
+ Tempra Simple
+ 0.0.1
+ Azareal
+
+ PostLayout
+ Post Layout
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extend.go b/extend.go
index 6d3f6030..c248324a 100644
--- a/extend.go
+++ b/extend.go
@@ -1,5 +1,6 @@
/* Copyright Azareal 2016 - 2017 */
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{})
@@ -24,6 +25,16 @@ type Plugin struct
hooks[name] = handler
}*/
+func init_plugins() {
+ for name, body := range plugins {
+ log.Print("Added plugin " + name)
+ if body.Active {
+ log.Print("Initialised plugin " + name)
+ plugins[name].Init()
+ }
+ }
+}
+
func add_hook(name string, handler interface{}) {
switch h := handler.(type) {
case func(interface{})interface{}:
diff --git a/forum.go b/forum.go
index 0913b48d..45d56670 100644
--- a/forum.go
+++ b/forum.go
@@ -17,4 +17,4 @@ type ForumSimple struct
ID int
Name string
Active bool
-}
\ No newline at end of file
+}
diff --git a/general_test.go b/general_test.go
index e138d4e5..d0485e3a 100644
--- a/general_test.go
+++ b/general_test.go
@@ -31,8 +31,8 @@ func BenchmarkTopicTemplate(b *testing.B) {
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
- tpage := TopicPage{"Topic Blah","topic",user,noticeList,replyList,topic,false}
- tpage2 := TopicPage{"Topic Blah","topic",admin,noticeList,replyList,topic,false}
+ tpage := TopicPage{"Topic Blah",user,noticeList,replyList,topic,false}
+ tpage2 := TopicPage{"Topic Blah",admin,noticeList,replyList,topic,false}
w := ioutil.Discard
b.Run("compiled_useradmin", func(b *testing.B) {
@@ -65,7 +65,7 @@ func BenchmarkTopicsTemplate(b *testing.B) {
var noticeList map[int]string = make(map[int]string)
noticeList[0] = "test"
- var topicList []interface{}
+ var topicList []TopicUser
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
@@ -77,8 +77,8 @@ func BenchmarkTopicsTemplate(b *testing.B) {
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
- tpage := Page{"Topic Blah","topic",user,noticeList,topicList,0}
- tpage2 := Page{"Topic Blah","topic",admin,noticeList,topicList,0}
+ tpage := TopicsPage{"Topic Blah",user,noticeList,topicList,0}
+ tpage2 := TopicsPage{"Topic Blah",admin,noticeList,topicList,0}
w := ioutil.Discard
b.Run("compiled_useradmin", func(b *testing.B) {
@@ -138,6 +138,10 @@ func BenchmarkRoute(b *testing.B) {
forums_req_admin.AddCookie(&admin_session_cookie)
forums_handler := http.HandlerFunc(route_forums)
+ static_w := httptest.NewRecorder()
+ static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil))
+ static_handler := http.HandlerFunc(route_static)
+
debug = false
nogrouplog = true
@@ -146,16 +150,18 @@ func BenchmarkRoute(b *testing.B) {
log.SetOutput(discard)
var err error
- init_database(err);
+ init_database(err)
external_sites["YT"] = "https://www.youtube.com/"
hooks["trow_assign"] = nil
hooks["rrow_assign"] = nil
+ init_plugins()
- for name, body := range plugins {
- if body.Active {
- plugins[name].Init()
+ b.Run("static_files", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ static_w.Body.Reset()
+ static_handler.ServeHTTP(static_w,static_req)
}
- }
+ })
b.Run("topic_admin", func(b *testing.B) {
for i := 0; i < b.N; i++ {
diff --git a/gosora.exe b/gosora.exe
index 82e5dbbd..1860abde 100644
Binary files a/gosora.exe and b/gosora.exe differ
diff --git a/group.go b/group.go
index 155f39e7..8cc683ec 100644
--- a/group.go
+++ b/group.go
@@ -30,6 +30,7 @@ type Perms struct
EditUserGroupAdmin bool
ManageForums bool // This could be local, albeit limited for per-forum managers
EditSettings bool
+ ManageThemes bool
ManagePlugins bool
ViewIPs bool
@@ -86,6 +87,7 @@ func init() {
EditUserGroupAdmin: true,
ManageForums: true,
EditSettings: true,
+ ManageThemes: true,
ManagePlugins: true,
ViewIPs: true,
diff --git a/images/bench_round3.PNG b/images/bench_round3.PNG
new file mode 100644
index 00000000..4ef0093b
Binary files /dev/null and b/images/bench_round3.PNG differ
diff --git a/images/bench_round3_staticfileimprovements.PNG b/images/bench_round3_staticfileimprovements.PNG
new file mode 100644
index 00000000..62b415fc
Binary files /dev/null and b/images/bench_round3_staticfileimprovements.PNG differ
diff --git a/images/layout2-gradients-test.PNG b/images/layout2-gradients-test.PNG
new file mode 100644
index 00000000..883719b9
Binary files /dev/null and b/images/layout2-gradients-test.PNG differ
diff --git a/images/layout2-gradients-test2.PNG b/images/layout2-gradients-test2.PNG
new file mode 100644
index 00000000..620dd871
Binary files /dev/null and b/images/layout2-gradients-test2.PNG differ
diff --git a/images/panel-theme-list.PNG b/images/panel-theme-list.PNG
new file mode 100644
index 00000000..8b8ab873
Binary files /dev/null and b/images/panel-theme-list.PNG differ
diff --git a/main.go b/main.go
index 1c694290..1dc6cc73 100644
--- a/main.go
+++ b/main.go
@@ -31,52 +31,54 @@ var external_sites map[string]string = make(map[string]string)
var groups map[int]Group = make(map[int]Group)
var forums map[int]Forum = make(map[int]Forum)
var static_files map[string]SFile = make(map[string]SFile)
-var ctemplates []string
+
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(Page,io.Writer) = nil
-var template_forum_handle func(Page,io.Writer) = nil
-var template_forums_handle func(Page,io.Writer) = nil
+var template_topics_handle func(TopicsPage,io.Writer) = nil
+var template_forum_handle func(ForumPage,io.Writer) = nil
+var template_forums_handle func(ForumsPage,io.Writer) = nil
var template_profile_handle func(ProfilePage,io.Writer) = nil
func compile_templates() {
var c CTemplateSet
- user := User{0,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
+ user := User{62,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
var noticeList map[int]string = make(map[int]string)
noticeList[0] = "test"
log.Print("Compiling the templates")
- topic := TopicUser{0,"",template.HTML(""),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""}
+ topic := TopicUser{1,"Blah",template.HTML("Hey there!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""}
var replyList []Reply
- replyList = append(replyList, Reply{0,0,"",template.HTML(""),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
+ replyList = append(replyList, Reply{0,0,"",template.HTML("Yo!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
var varList map[string]VarItem = make(map[string]VarItem)
- tpage := TopicPage{"Title","name",user,noticeList,replyList,topic,false}
+ tpage := TopicPage{"Title",user,noticeList,replyList,topic,false}
topic_id_tmpl := c.compile_template("topic.html","templates/","TopicPage", tpage, varList)
topic_id_alt_tmpl := c.compile_template("topic_alt.html","templates/","TopicPage", tpage, varList)
varList = make(map[string]VarItem)
- ppage := ProfilePage{"Title",user,noticeList,replyList,user,false}
+ ppage := ProfilePage{"User 526",user,noticeList,replyList,user,false}
profile_tmpl := c.compile_template("profile.html","templates/","ProfilePage", ppage, varList)
- var forumList []interface{}
+ var forumList []Forum
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)
+ forums_page := ForumsPage{"Forum List",user,noticeList,forumList,0}
+ forums_tmpl := c.compile_template("forums.html","templates/","ForumsPage", forums_page, varList)
- var topicList []interface{}
+ var topicList []TopicUser
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)
+ 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)
- 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)
+ 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)
log.Print("Writing the templates")
write_template("topic", topic_id_tmpl)
@@ -102,8 +104,9 @@ func write_template(name string, content string) {
}
func main(){
+ init_themes()
var err error
- init_database(err);
+ init_database(err)
compile_templates()
log.Print("Loading the static files.")
@@ -132,19 +135,11 @@ func main(){
hooks["rrow_assign"] = nil
templates.ParseGlob("pages/*")
- for name, body := range plugins {
- log.Print("Added plugin " + name)
- if body.Active {
- log.Print("Initialised plugin " + name)
- plugins[name].Init()
- }
- }
+ init_plugins()
// In a directory to stop it clashing with the other paths
http.HandleFunc("/static/", route_static)
- //http.HandleFunc("/static/", route_fstatic)
- //fs_p := http.FileServer(http.Dir("./public"))
- //http.Handle("/static/", http.StripPrefix("/static/",fs_p))
+
fs_u := http.FileServer(http.Dir("./uploads"))
http.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u))
@@ -205,6 +200,8 @@ func main(){
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)
diff --git a/mod_routes.go b/mod_routes.go
index a7855614..34ed7ddf 100644
--- a/mod_routes.go
+++ b/mod_routes.go
@@ -42,8 +42,6 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) {
var is_closed bool
if topic_status == "closed" {
is_closed = true
- } else {
- is_closed = false
}
topic_content := html.EscapeString(r.PostFormValue("topic_content"))
@@ -910,7 +908,6 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request){
NoPermissions(w,r,user)
return
}
-
if r.FormValue("session") != user.Session {
SecurityError(w,r,user)
return
@@ -1243,3 +1240,95 @@ func route_panel_groups(w http.ResponseWriter, r *http.Request){
pi := Page{"Group Manager","panel-groups",user,noticeList,groupList,0}
templates.ExecuteTemplate(w,"panel-groups.html", pi)
}
+
+func route_panel_themes(w http.ResponseWriter, r *http.Request){
+ user, noticeList, ok := SessionCheck(w,r)
+ if !ok {
+ return
+ }
+ if !user.Is_Super_Mod || !user.Perms.ManageThemes {
+ NoPermissions(w,r,user)
+ return
+ }
+
+ var themeList []interface{}
+ for _, theme := range themes {
+ themeList = append(themeList, theme)
+ }
+
+ pi := Page{"Theme Manager","panel-themes",user,noticeList,themeList,0}
+ templates.ExecuteTemplate(w,"panel-themes.html", pi)
+}
+
+func route_panel_themes_default(w http.ResponseWriter, r *http.Request){
+ user, ok := SimpleSessionCheck(w,r)
+ if !ok {
+ return
+ }
+ if !user.Is_Super_Mod || !user.Perms.ManageThemes {
+ NoPermissions(w,r,user)
+ return
+ }
+ if r.FormValue("session") != user.Session {
+ SecurityError(w,r,user)
+ return
+ }
+
+ uname := r.URL.Path[len("/panel/themes/default/"):]
+ theme, ok := themes[uname]
+ if !ok {
+ LocalError("The theme isn't registered in the system",w,r,user)
+ return
+ }
+
+ var isDefault bool
+ err := db.QueryRow("SELECT `default` from `themes` where `uname` = ?", uname).Scan(&isDefault)
+ if err != nil && err != sql.ErrNoRows {
+ InternalError(err,w,r,user)
+ return
+ }
+
+ has_theme := err != sql.ErrNoRows
+ if has_theme {
+ if isDefault {
+ LocalError("The theme is already active",w,r,user)
+ return
+ }
+ _, err = update_theme_stmt.Exec(1, uname)
+ if err != nil {
+ InternalError(err,w,r,user)
+ return
+ }
+ } else {
+ _, err := add_theme_stmt.Exec(uname,1)
+ if err != nil {
+ InternalError(err,w,r,user)
+ return
+ }
+ }
+
+ _, err = update_theme_stmt.Exec(0, defaultTheme)
+ if err != nil {
+ InternalError(err,w,r,user)
+ return
+ }
+
+ log.Print("Setting theme '" + theme.Name + "' as the default theme")
+ theme.Active = true
+ themes[uname] = theme
+
+ dTheme, ok := themes[defaultTheme]
+ if !ok {
+ log.Fatal("The default theme is missing")
+ return
+ }
+ dTheme.Active = false
+ themes[defaultTheme] = dTheme
+
+ defaultTheme = uname
+ reset_template_overrides()
+ add_theme_static_files(uname)
+ map_theme_templates(theme)
+
+ http.Redirect(w,r,"/panel/themes/",http.StatusSeeOther)
+}
diff --git a/mysql.go b/mysql.go
index b0e98394..dede2a45 100644
--- a/mysql.go
+++ b/mysql.go
@@ -42,6 +42,8 @@ var update_setting_stmt *sql.Stmt
var add_plugin_stmt *sql.Stmt
var update_plugin_stmt *sql.Stmt
var update_user_stmt *sql.Stmt
+var add_theme_stmt *sql.Stmt
+var update_theme_stmt *sql.Stmt
func init_database(err error) {
if(dbpassword != ""){
@@ -253,6 +255,18 @@ func init_database(err error) {
log.Fatal(err)
}
+ log.Print("Preparing add_theme statement.")
+ add_theme_stmt, err = db.Prepare("INSERT INTO `themes`(`uname`,`default`) VALUES(?,?)")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ log.Print("Preparing update_theme statement.")
+ update_theme_stmt, err = db.Prepare("UPDATE `themes` SET `default` = ? WHERE `uname` = ?")
+ if err != nil {
+ log.Fatal(err)
+ }
+
log.Print("Preparing update_user statement.")
update_user_stmt, err = db.Prepare("UPDATE `users` SET `name` = ?, `email` = ?, `group` = ? WHERE `uid` = ?")
if err != nil {
@@ -381,4 +395,42 @@ func init_database(err error) {
if err != nil {
log.Fatal(err)
}
+
+ log.Print("Loading the themes.")
+ rows, err = db.Query("SELECT `uname`, `default` FROM `themes`")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer rows.Close()
+
+ var defaultThemeSwitch bool
+ for rows.Next() {
+ err := rows.Scan(&uname, &defaultThemeSwitch)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Was the theme deleted at some point?
+ theme, ok := themes[uname]
+ if !ok {
+ continue
+ }
+
+ if defaultThemeSwitch {
+ log.Print("Loading the theme '" + theme.Name + "'")
+ theme.Active = true
+ defaultTheme = uname
+ add_theme_static_files(uname)
+ map_theme_templates(theme)
+ } else {
+ theme.Active = false
+ }
+ themes[uname] = theme
+ }
+ err = rows.Err()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+
}
diff --git a/pages.go b/pages.go
index 2399ea92..54012b41 100644
--- a/pages.go
+++ b/pages.go
@@ -15,7 +15,6 @@ type Page struct
type TopicPage struct
{
Title string
- Name string
CurrentUser User
NoticeList map[int]string
ItemList []Reply
@@ -23,6 +22,33 @@ type TopicPage struct
ExtData interface{}
}
+type TopicsPage struct
+{
+ Title string
+ CurrentUser User
+ NoticeList map[int]string
+ ItemList []TopicUser
+ ExtData interface{}
+}
+
+type ForumPage struct
+{
+ Title string
+ CurrentUser User
+ NoticeList map[int]string
+ ItemList []TopicUser
+ ExtData interface{}
+}
+
+type ForumsPage struct
+{
+ Title string
+ CurrentUser User
+ NoticeList map[int]string
+ ItemList []Forum
+ ExtData interface{}
+}
+
type ProfilePage struct
{
Title string
@@ -36,7 +62,6 @@ type ProfilePage struct
type PageSimple struct
{
Title string
- Name string
Something interface{}
}
diff --git a/public/fabric-base-simple-alpha.png b/public/fabric-base-simple-alpha.png
new file mode 100644
index 00000000..7a102a54
Binary files /dev/null and b/public/fabric-base-simple-alpha.png differ
diff --git a/routes.go b/routes.go
index 04c34962..68fa0a25 100644
--- a/routes.go
+++ b/routes.go
@@ -24,18 +24,27 @@ var nList map[int]string
// GET functions
func route_static(w http.ResponseWriter, r *http.Request){
//name := r.URL.Path[len("/static/"):]
- if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && static_files[r.URL.Path].Info.ModTime().Before(t.Add(1*time.Second)) {
+ //log.Print("Outputting static file '" + r.URL.Path + "'")
+
+ file, ok := static_files[r.URL.Path]
+ if !ok {
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+
+ // Surely, there's a more efficient way of doing this?
+ if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && file.Info.ModTime().Before(t.Add(1 * time.Second)) {
w.WriteHeader(http.StatusNotModified)
return
}
h := w.Header()
- h.Set("Last-Modified", static_files[r.URL.Path].FormattedModTime)
- h.Set("Content-Type", static_files[r.URL.Path].Mimetype)
- h.Set("Content-Length", strconv.FormatInt(static_files[r.URL.Path].Length, 10))
- //http.ServeContent(w,r,r.URL.Path,static_files[r.URL.Path].Info.ModTime(),static_files[r.URL.Path])
- //w.Write(static_files[r.URL.Path].Data)
- io.Copy(w, bytes.NewReader(static_files[r.URL.Path].Data))
- //io.CopyN(w, bytes.NewReader(static_files[r.URL.Path].Data), static_files[r.URL.Path].Length)
+ h.Set("Last-Modified", file.FormattedModTime)
+ h.Set("Content-Type", file.Mimetype)
+ h.Set("Content-Length", strconv.FormatInt(file.Length, 10)) // Avoid doing a type conversion every time?
+ //http.ServeContent(w,r,r.URL.Path,file.Info.ModTime(),file)
+ //w.Write(file.Data)
+ io.Copy(w, bytes.NewReader(file.Data)) // Use w.Write instead?
+ //io.CopyN(w, bytes.NewReader(file.Data), static_files[r.URL.Path].Length)
}
func route_fstatic(w http.ResponseWriter, r *http.Request){
@@ -83,21 +92,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){
return
}*/
- var(
- topicList []interface{}
- tid int
- title string
- content string
- createdBy int
- is_closed bool
- sticky bool
- createdAt string
- parentID int
- status string
- name string
- avatar string
- )
-
+ var topicList []TopicUser
rows, err := get_topic_list_stmt.Query()
if err != nil {
InternalError(err,w,r,user)
@@ -105,27 +100,27 @@ func route_topics(w http.ResponseWriter, r *http.Request){
}
defer rows.Close()
+ topicItem := TopicUser{ID: 0,}
for rows.Next() {
- err := rows.Scan(&tid, &title, &content, &createdBy, &is_closed, &sticky, &createdAt, &parentID, &name, &avatar)
+ err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.Is_Closed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.ParentID, &topicItem.CreatedByName, &topicItem.Avatar)
if err != nil {
InternalError(err,w,r,user)
return
}
- if is_closed {
- status = "closed"
+ if topicItem.Is_Closed {
+ topicItem.Status = "shut"
} else {
- status = "open"
+ topicItem.Status = "open"
}
- if avatar != "" {
- if avatar[0] == '.' {
- avatar = "/uploads/avatar_" + strconv.Itoa(createdBy) + avatar
+ if topicItem.Avatar != "" {
+ if topicItem.Avatar[0] == '.' {
+ topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar
}
} else {
- avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(createdBy),1)
+ topicItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1)
}
- topicItem := TopicUser{tid,title,content,createdBy,is_closed,sticky, createdAt,parentID,status,name,avatar,"",0,"","","",""}
if hooks["trow_assign"] != nil {
topicItem = run_hook("trow_assign", topicItem).(TopicUser)
}
@@ -137,7 +132,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){
return
}
- pi := Page{"Topic List","topics",user,noticeList,topicList,0}
+ pi := TopicsPage{"Topic List",user,noticeList,topicList,0}
if template_topics_handle != nil {
template_topics_handle(pi,w)
} else {
@@ -154,20 +149,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){
return
}
- var(
- topicList []interface{}
- tid int
- title string
- content string
- createdBy int
- is_closed bool
- sticky bool
- createdAt string
- parentID int
- status string
- name string
- avatar string
- )
+ var topicList []TopicUser
fid, err := strconv.Atoi(r.URL.Path[len("/forum/"):])
if err != nil {
@@ -192,27 +174,27 @@ func route_forum(w http.ResponseWriter, r *http.Request){
}
defer rows.Close()
+ topicItem := TopicUser{ID: 0}
for rows.Next() {
- err := rows.Scan(&tid, &title, &content, &createdBy, &is_closed, &sticky, &createdAt, &parentID, &name, &avatar)
+ err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.Is_Closed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.ParentID, &topicItem.CreatedByName, &topicItem.Avatar)
if err != nil {
InternalError(err,w,r,user)
return
}
- if is_closed {
- status = "closed"
+ if topicItem.Is_Closed {
+ topicItem.Status = "shut"
} else {
- status = "open"
+ topicItem.Status = "open"
}
- if avatar != "" {
- if avatar[0] == '.' {
- avatar = "/uploads/avatar_" + strconv.Itoa(createdBy) + avatar
+ if topicItem.Avatar != "" {
+ if topicItem.Avatar[0] == '.' {
+ topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar
}
} else {
- avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(createdBy),1)
+ topicItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1)
}
- topicItem := TopicUser{tid,title,content,createdBy,is_closed,sticky,createdAt,parentID,status,name,avatar,"",0,"","","",""}
if hooks["trow_assign"] != nil {
topicItem = run_hook("trow_assign", topicItem).(TopicUser)
}
@@ -224,7 +206,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){
return
}
- pi := Page{forums[fid].Name,"forum",user,noticeList,topicList,0}
+ pi := ForumPage{forums[fid].Name,user,noticeList,topicList,0}
if template_forum_handle != nil {
template_forum_handle(pi,w)
} else {
@@ -241,14 +223,14 @@ func route_forums(w http.ResponseWriter, r *http.Request){
return
}
- var forumList []interface{}
+ var forumList []Forum
for _, forum := range forums {
if forum.Active {
forumList = append(forumList, forum)
}
}
- pi := Page{"Forum List","forums",user,noticeList,forumList,0}
+ pi := ForumsPage{"Forum List",user,noticeList,forumList,0}
if template_forums_handle != nil {
template_forums_handle(pi,w)
} else {
@@ -315,7 +297,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
topic.ContentLines = strings.Count(content,"\n")
if topic.Is_Closed {
- topic.Status = "closed"
+ topic.Status = "shut"
// We don't want users posting in locked topics...
if !user.Is_Mod {
@@ -407,9 +389,9 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
return
}
- tpage := TopicPage{topic.Title,"topic",user,noticeList,replyList,topic,0}
- if template_topic_handle != nil { //if template_topic_alt_handle != nil {
- template_topic_handle(tpage,w) //template_topic_alt_handle(tpage,w)
+ tpage := TopicPage{topic.Title,user,noticeList,replyList,topic,0}
+ if template_topic_handle != nil {
+ template_topic_handle(tpage,w)
} else {
err = templates.ExecuteTemplate(w,"topic.html", tpage)
if err != nil {
diff --git a/template_forum.go b/template_forum.go
index d734569d..58b2b2a7 100644
--- a/template_forum.go
+++ b/template_forum.go
@@ -1,12 +1,17 @@
+/* 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 "io"
import "strconv"
func init() {
-template_forum_handle = template_forum
+ template_forum_handle = template_forum
+ //o_template_forum_handle = template_forum
+ ctemplates = append(ctemplates,"forum")
+ tmpl_ptr_map["forum"] = &template_forum_handle
+ tmpl_ptr_map["o_forum"] = template_forum
}
-func template_forum(tmpl_forum_vars Page, w io.Writer) {
+func template_forum(tmpl_forum_vars ForumPage, w io.Writer) {
w.Write([]byte(`
@@ -68,20 +73,20 @@ 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
+
` + item.Title + ` `))
+if item.Is_Closed {
+w.Write([]byte(`
shut
`))
} else {
w.Write([]byte(`
open`))
diff --git a/template_forums.go b/template_forums.go
index 6b1ccd73..09e1a3fb 100644
--- a/template_forums.go
+++ b/template_forums.go
@@ -1,12 +1,17 @@
+/* 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 "io"
import "strconv"
func init() {
-template_forums_handle = template_forums
+ template_forums_handle = template_forums
+ //o_template_forums_handle = template_forums
+ ctemplates = append(ctemplates,"forums")
+ tmpl_ptr_map["forums"] = &template_forums_handle
+ tmpl_ptr_map["o_forums"] = template_forums
}
-func template_forums(tmpl_forums_vars Page, w io.Writer) {
+func template_forums(tmpl_forums_vars ForumsPage, w io.Writer) {
w.Write([]byte(`
@@ -65,8 +70,8 @@ w.Write([]byte(`
if len(tmpl_forums_vars.ItemList) != 0 {
for _, item := range tmpl_forums_vars.ItemList {
w.Write([]byte(`
`))
}
diff --git a/template_profile.go b/template_profile.go
index 5fecd56e..fce15a79 100644
--- a/template_profile.go
+++ b/template_profile.go
@@ -1,9 +1,14 @@
+/* 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_profile_handle = template_profile
+ template_profile_handle = template_profile
+ //o_template_profile_handle = template_profile
+ ctemplates = append(ctemplates,"profile")
+ tmpl_ptr_map["profile"] = &template_profile_handle
+ tmpl_ptr_map["o_profile"] = template_profile
}
func template_profile(tmpl_profile_vars ProfilePage, w io.Writer) {
diff --git a/template_topic.go b/template_topic.go
index 105852ef..27b47526 100644
--- a/template_topic.go
+++ b/template_topic.go
@@ -1,10 +1,15 @@
+/* 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 "io"
import "strconv"
import "html/template"
func init() {
-template_topic_handle = template_topic
+ template_topic_handle = template_topic
+ //o_template_topic_handle = template_topic
+ ctemplates = append(ctemplates,"topic")
+ tmpl_ptr_map["topic"] = &template_topic_handle
+ tmpl_ptr_map["o_topic"] = template_topic
}
func template_topic(tmpl_topic_vars TopicPage, w io.Writer) {
@@ -91,7 +96,7 @@ w.Write([]byte(`
`))
diff --git a/template_topic_alt.go b/template_topic_alt.go
index 0f7f953a..20b7149b 100644
--- a/template_topic_alt.go
+++ b/template_topic_alt.go
@@ -1,10 +1,15 @@
+/* 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 "html/template"
import "io"
+import "strconv"
func init() {
-template_topic_alt_handle = template_topic_alt
+ template_topic_alt_handle = template_topic_alt
+ //o_template_topic_alt_handle = template_topic_alt
+ ctemplates = append(ctemplates,"topic_alt")
+ tmpl_ptr_map["topic_alt"] = &template_topic_alt_handle
+ tmpl_ptr_map["o_topic_alt"] = template_topic_alt
}
func template_topic_alt(tmpl_topic_alt_vars TopicPage, w io.Writer) {
@@ -63,15 +68,17 @@ w.Write([]byte(`
` + item + `
`))
w.Write([]byte(`